updating to Eclipse 3.1 v_530a compiler
diff --git a/org.eclipse.jdt.core/.classpath b/org.eclipse.jdt.core/.classpath
index fed27a0..f95921f 100644
--- a/org.eclipse.jdt.core/.classpath
+++ b/org.eclipse.jdt.core/.classpath
@@ -9,7 +9,7 @@
 	<classpathentry kind="src" path="formatter"/>
 	<classpathentry kind="src" path="model"/>
 	<classpathentry kind="src" path="search"/>
-	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins" excluding="**/internal/"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/org.eclipse.jdt.core/.cvsignore b/org.eclipse.jdt.core/.cvsignore
index da63a8f..20c95dc 100644
--- a/org.eclipse.jdt.core/.cvsignore
+++ b/org.eclipse.jdt.core/.cvsignore
@@ -1,2 +1 @@
-bin
-antbin
\ No newline at end of file
+antbin
diff --git a/org.eclipse.jdt.core/.options b/org.eclipse.jdt.core/.options
index 41b29e1..0daf859 100644
--- a/org.eclipse.jdt.core/.options
+++ b/org.eclipse.jdt.core/.options
@@ -32,6 +32,9 @@
 # Reports post actions addition/run

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

 

+# Reports name resolution activity

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

+

 # Reports java search activity

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

 

diff --git a/org.eclipse.jdt.core/.project b/org.eclipse.jdt.core/.project
index 1de109a..5e05291 100644
--- a/org.eclipse.jdt.core/.project
+++ b/org.eclipse.jdt.core/.project
@@ -1,8 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <projectDescription>
-	<name>shadows.org.eclipse.jdt.core</name>
+	<name>org.eclipse.jdt.core</name>
 	<comment></comment>
 	<projects>
+		<project>org.eclipse.ant.core</project>
 	</projects>
 	<buildSpec>
 		<buildCommand>
@@ -23,5 +24,6 @@
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.PluginNature</nature>
 	</natures>
 </projectDescription>
diff --git a/org.eclipse.jdt.core/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jdt.core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..4bcd4d1
--- /dev/null
+++ b/org.eclipse.jdt.core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,65 @@
+#Fri Sep 03 12:55:26 CEST 2004
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.source=1.3
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.compliance=1.4
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+eclipse.preferences.version=1
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.incompleteClasspath=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/core/JDTCompilerAdapter.java b/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/core/JDTCompilerAdapter.java
index 27222d6..ea751ba 100644
--- a/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/core/JDTCompilerAdapter.java
+++ b/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/core/JDTCompilerAdapter.java
@@ -15,6 +15,7 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.Map;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -25,6 +26,7 @@
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.util.JavaEnvUtils;
 import org.eclipse.jdt.internal.antadapter.AntAdapterMessages;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 
 /**
  * Ant 1.5 compiler adapter for the Eclipse Java compiler. This adapter permits the
@@ -42,6 +44,7 @@
 public class JDTCompilerAdapter extends DefaultCompilerAdapter {
 	private static String compilerClass = "org.eclipse.jdt.internal.compiler.batch.Main"; //$NON-NLS-1$
 	String logFileName;
+	Map customDefaultOptions;
 	
 	/**
 	 * Performs a compile using the JDT batch compiler
@@ -49,17 +52,17 @@
 	 * @return boolean true if the compilation is ok, false otherwise
 	 */
 	public boolean execute() throws BuildException {
-		attributes.log(AntAdapterMessages.getString("ant.jdtadapter.info.usingJDTCompiler"), Project.MSG_VERBOSE); //$NON-NLS-1$
+		this.attributes.log(AntAdapterMessages.getString("ant.jdtadapter.info.usingJDTCompiler"), Project.MSG_VERBOSE); //$NON-NLS-1$
 		Commandline cmd = setupJavacCommand();
 
 		try {
 			Class c = Class.forName(compilerClass);
-			Constructor batchCompilerConstructor = c.getConstructor(new Class[] { PrintWriter.class, PrintWriter.class, Boolean.TYPE});
-			Object batchCompilerInstance = batchCompilerConstructor.newInstance(new Object[] {new PrintWriter(System.out), new PrintWriter(System.err), new Boolean(true)});
+			Constructor batchCompilerConstructor = c.getConstructor(new Class[] { PrintWriter.class, PrintWriter.class, Boolean.TYPE, Map.class});
+			Object batchCompilerInstance = batchCompilerConstructor.newInstance(new Object[] {new PrintWriter(System.out), new PrintWriter(System.err), Boolean.TRUE, this.customDefaultOptions});
 			Method compile = c.getMethod("compile", new Class[] {String[].class}); //$NON-NLS-1$
 			Object result = compile.invoke(batchCompilerInstance, new Object[] { cmd.getArguments()});
 			final boolean resultValue = ((Boolean) result).booleanValue();
-			if (!resultValue && verbose) {
+			if (!resultValue && this.verbose) {
 				System.out.println(AntAdapterMessages.getString("ant.jdtadapter.error.compilationFailed", this.logFileName)); //$NON-NLS-1$
 			}
 			return resultValue;
@@ -73,30 +76,31 @@
 	
 	protected Commandline setupJavacCommand() throws BuildException {
 		Commandline cmd = new Commandline();
-		
+		this.customDefaultOptions = new CompilerOptions().getMap();
+
 		/*
 		 * This option is used to never exit at the end of the ant task. 
 		 */
 		cmd.createArgument().setValue("-noExit"); //$NON-NLS-1$
 
-        if (bootclasspath != null && bootclasspath.size() != 0) {
+        if (this.bootclasspath != null && this.bootclasspath.size() != 0) {
 			/*
 			 * Set the bootclasspath for the Eclipse compiler.
 			 */
 			cmd.createArgument().setValue("-bootclasspath"); //$NON-NLS-1$
-			cmd.createArgument().setPath(bootclasspath);        	
+			cmd.createArgument().setPath(this.bootclasspath);        	
         } else {
-            includeJavaRuntime = true;
+            this.includeJavaRuntime = true;
         }
 
-        Path classpath = new Path(project);
+        Path classpath = new Path(this.project);
 
        /*
          * Eclipse compiler doesn't support -extdirs.
          * It is emulated using the classpath. We add extdirs entries after the 
          * bootclasspath.
          */
-        addExtdirs(extdirs, classpath);
+        addExtdirs(this.extdirs, classpath);
 
 		/*
 		 * The java runtime is already handled, so we simply want to retrieve the
@@ -120,7 +124,7 @@
         Path compileSourcePath = null;
         if (getSourcepathMethod != null) {
 	 		try {
-				compileSourcePath = (Path) getSourcepathMethod.invoke(attributes, null);
+				compileSourcePath = (Path) getSourcepathMethod.invoke(this.attributes, null);
 			} catch (IllegalAccessException e) {
 				// should never happen
 			} catch (InvocationTargetException e) {
@@ -130,7 +134,7 @@
         if (compileSourcePath != null) {
             sourcepath = compileSourcePath;
         } else {
-            sourcepath = src;
+            sourcepath = this.src;
         }
 		classpath.append(sourcepath);
 		/*
@@ -140,25 +144,25 @@
 		cmd.createArgument().setPath(classpath);
 
         String memoryParameterPrefix = JavaEnvUtils.getJavaVersion().equals(JavaEnvUtils.JAVA_1_1) ? "-J-" : "-J-X";//$NON-NLS-1$//$NON-NLS-2$
-        if (memoryInitialSize != null) {
-            if (!attributes.isForkedJavac()) {
-                attributes.log(AntAdapterMessages.getString("ant.jdtadapter.info.ignoringMemoryInitialSize"), Project.MSG_WARN); //$NON-NLS-1$
+        if (this.memoryInitialSize != null) {
+            if (!this.attributes.isForkedJavac()) {
+                this.attributes.log(AntAdapterMessages.getString("ant.jdtadapter.info.ignoringMemoryInitialSize"), Project.MSG_WARN); //$NON-NLS-1$
             } else {
                 cmd.createArgument().setValue(memoryParameterPrefix
-                                              + "ms" + memoryInitialSize); //$NON-NLS-1$
+                                              + "ms" + this.memoryInitialSize); //$NON-NLS-1$
             }
         }
 
-        if (memoryMaximumSize != null) {
-            if (!attributes.isForkedJavac()) {
-                attributes.log(AntAdapterMessages.getString("ant.jdtadapter.info.ignoringMemoryMaximumSize"), Project.MSG_WARN); //$NON-NLS-1$
+        if (this.memoryMaximumSize != null) {
+            if (!this.attributes.isForkedJavac()) {
+                this.attributes.log(AntAdapterMessages.getString("ant.jdtadapter.info.ignoringMemoryMaximumSize"), Project.MSG_WARN); //$NON-NLS-1$
             } else {
                 cmd.createArgument().setValue(memoryParameterPrefix
-                                              + "mx" + memoryMaximumSize); //$NON-NLS-1$
+                                              + "mx" + this.memoryMaximumSize); //$NON-NLS-1$
             }
         }
 
-        if (debug) {
+        if (this.debug) {
 	       // retrieve the method getSourcepath() using reflect
 	        // This is done to improve the compatibility to ant 1.5
 	        Method getDebugLevelMethod = null;
@@ -171,7 +175,7 @@
      	    String debugLevel = null;
 	        if (getDebugLevelMethod != null) {
 				try {
-					debugLevel = (String) getDebugLevelMethod.invoke(attributes, null);
+					debugLevel = (String) getDebugLevelMethod.invoke(this.attributes, null);
 				} catch (IllegalAccessException e) {
 					// should never happen
 				} catch (InvocationTargetException e) {
@@ -180,15 +184,32 @@
         	}
 			if (debugLevel != null) {
 				if (debugLevel.length() == 0) {
-					cmd.createArgument().setValue("-g:none"); //$NON-NLS-1$
+					this.customDefaultOptions.put(CompilerOptions.OPTION_LocalVariableAttribute, CompilerOptions.DO_NOT_GENERATE);
+					this.customDefaultOptions.put(CompilerOptions.OPTION_LineNumberAttribute, CompilerOptions.DO_NOT_GENERATE);
+					this.customDefaultOptions.put(CompilerOptions.OPTION_SourceFileAttribute , CompilerOptions.DO_NOT_GENERATE);
 				} else {
-					cmd.createArgument().setValue("-g:" + debugLevel); //$NON-NLS-1$
+					this.customDefaultOptions.put(CompilerOptions.OPTION_LocalVariableAttribute, CompilerOptions.DO_NOT_GENERATE);
+					this.customDefaultOptions.put(CompilerOptions.OPTION_LineNumberAttribute, CompilerOptions.DO_NOT_GENERATE);
+					this.customDefaultOptions.put(CompilerOptions.OPTION_SourceFileAttribute , CompilerOptions.DO_NOT_GENERATE);
+					if (debugLevel.indexOf("vars") != -1) {//$NON-NLS-1$
+						this.customDefaultOptions.put(CompilerOptions.OPTION_LocalVariableAttribute, CompilerOptions.GENERATE);
+					}
+					if (debugLevel.indexOf("lines") != -1) {//$NON-NLS-1$
+						this.customDefaultOptions.put(CompilerOptions.OPTION_LineNumberAttribute, CompilerOptions.GENERATE);
+					}
+					if (debugLevel.indexOf("source") != -1) {//$NON-NLS-1$
+						this.customDefaultOptions.put(CompilerOptions.OPTION_SourceFileAttribute , CompilerOptions.GENERATE);
+					}
 				}
 			} else {
-				cmd.createArgument().setValue("-g"); //$NON-NLS-1$
+				this.customDefaultOptions.put(CompilerOptions.OPTION_LocalVariableAttribute, CompilerOptions.GENERATE);
+				this.customDefaultOptions.put(CompilerOptions.OPTION_LineNumberAttribute, CompilerOptions.GENERATE);
+				this.customDefaultOptions.put(CompilerOptions.OPTION_SourceFileAttribute , CompilerOptions.GENERATE);
             }
         } else {
-            cmd.createArgument().setValue("-g:none"); //$NON-NLS-1$
+			this.customDefaultOptions.put(CompilerOptions.OPTION_LocalVariableAttribute, CompilerOptions.DO_NOT_GENERATE);
+			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
@@ -203,7 +224,7 @@
  	    String[] compilerArgs = null;
         if (getCurrentCompilerArgsMethod != null) {
 			try {
-				compilerArgs = (String[]) getCurrentCompilerArgsMethod.invoke(attributes, null);
+				compilerArgs = (String[]) getCurrentCompilerArgsMethod.invoke(this.attributes, null);
 			} catch (IllegalAccessException e) {
 				// should never happen
 			} catch (InvocationTargetException e) {
@@ -211,41 +232,127 @@
 			}
     	}
     	
-	   	if (compilerArgs == null) {
-			/*
-			 * Handle the nowarn option. If none, then we generate all warnings.
-			 */
-			if (attributes.getNowarn()) {
-				if (deprecation) {
-					cmd.createArgument().setValue("-warn:allDeprecation"); //$NON-NLS-1$
-				} else {
-					cmd.createArgument().setValue("-nowarn"); //$NON-NLS-1$
-				}
-			} else if (deprecation) {
-				cmd.createArgument().setValue("-warn:allDeprecation,constructorName,packageDefaultMethod,maskedCatchBlocks,unusedImports,staticReceiver"); //$NON-NLS-1$
-			} else {
-				cmd.createArgument().setValue("-warn:constructorName,packageDefaultMethod,maskedCatchBlocks,unusedImports,staticReceiver"); //$NON-NLS-1$
-			}
-    	} else {
-			/*
-			 * Handle the nowarn option. If none, then we generate all warnings.
-			 */
-			if (attributes.getNowarn()) {
-				if (deprecation) {
-					cmd.createArgument().setValue("-warn:allDeprecation"); //$NON-NLS-1$
-				} else {
-					cmd.createArgument().setValue("-nowarn"); //$NON-NLS-1$
-				}
-			} else {
-				if (deprecation) {
-					cmd.createArgument().setValue("-warn:+allDeprecation"); //$NON-NLS-1$
-				} else {
-					cmd.createArgument().setValue("-warn:-allDeprecation,deprecation"); //$NON-NLS-1$
-				}
-				if (compilerArgs.length == 0) {
-					cmd.createArgument().setValue("-warn:+constructorName,packageDefaultMethod,maskedCatchBlocks,unusedImports,staticReceiver"); //$NON-NLS-1$
+		/*
+		 * Handle the nowarn option. If none, then we generate all warnings.
+		 */
+		if (this.attributes.getNowarn()) {
+	        // disable all warnings
+			Object[] entries = this.customDefaultOptions.entrySet().toArray();
+			for (int i = 0, max = entries.length; i < max; i++) {
+				Map.Entry entry = (Map.Entry) entries[i];
+				if (!(entry.getKey() instanceof String))
+					continue;
+				if (!(entry.getValue() instanceof String))
+					continue;
+				if (((String) entry.getValue()).equals(CompilerOptions.WARNING)) {
+					this.customDefaultOptions.put(entry.getKey(), CompilerOptions.IGNORE);
 				}
 			}
+			this.customDefaultOptions.put(CompilerOptions.OPTION_TaskTags, ""); //$NON-NLS-1$
+			if (this.deprecation) {
+				this.customDefaultOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING); 
+				this.customDefaultOptions.put(CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, CompilerOptions.ENABLED); 
+				this.customDefaultOptions.put(CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, CompilerOptions.ENABLED); 
+			}
+		} else if (this.deprecation) {
+			this.customDefaultOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING); 
+			this.customDefaultOptions.put(CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, CompilerOptions.ENABLED); 
+			this.customDefaultOptions.put(CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, CompilerOptions.ENABLED); 
+		} else {
+			this.customDefaultOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE); 
+			this.customDefaultOptions.put(CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, CompilerOptions.DISABLED); 
+			this.customDefaultOptions.put(CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, CompilerOptions.DISABLED); 
+		}
+
+	   	/*
+		 * destDir option.
+		 */		
+		if (this.destDir != null) {
+			cmd.createArgument().setValue("-d"); //$NON-NLS-1$
+			cmd.createArgument().setFile(this.destDir.getAbsoluteFile());
+		}
+
+		/*
+		 * target option.
+		 */		
+		if (this.target != null) {
+			if (this.target.equals("1.1")) { //$NON-NLS-1$
+				this.customDefaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
+			} else if (this.target.equals("1.2")) { //$NON-NLS-1$
+				this.customDefaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
+			} else if (this.target.equals("1.3")) { //$NON-NLS-1$
+				this.customDefaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_3);
+			} else if (this.target.equals("1.4")) { //$NON-NLS-1$
+				this.customDefaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
+			} else if (this.target.equals("1.5")) { //$NON-NLS-1$
+				this.customDefaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
+			} else {
+	            this.attributes.log(AntAdapterMessages.getString("ant.jdtadapter.info.unknownTarget", this.target), Project.MSG_WARN); //$NON-NLS-1$
+			}
+		}
+
+		/*
+		 * verbose option
+		 */
+		if (this.verbose) {
+			cmd.createArgument().setValue("-verbose"); //$NON-NLS-1$
+			/*
+			 * extra option allowed by the Eclipse compiler
+			 */
+			cmd.createArgument().setValue("-log"); //$NON-NLS-1$
+			this.logFileName = this.destDir.getAbsolutePath() + ".log"; //$NON-NLS-1$
+			cmd.createArgument().setValue(this.logFileName);
+		}
+
+		/*
+		 * failnoerror option
+		 */
+		if (!this.attributes.getFailonerror()) {
+			cmd.createArgument().setValue("-proceedOnError"); //$NON-NLS-1$
+		}
+
+		/*
+		 * source option
+		 */
+		String source = this.attributes.getSource();
+        if (source != null) {
+        	if (source.equals("1.3")) { //$NON-NLS-1$
+				this.customDefaultOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
+			} else if (source.equals("1.4")) { //$NON-NLS-1$
+				this.customDefaultOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4);
+			} else if (source.equals("1.5")) { //$NON-NLS-1$
+				this.customDefaultOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
+			} else {
+	            this.attributes.log(AntAdapterMessages.getString("ant.jdtadapter.info.unknownSource", source), Project.MSG_WARN); //$NON-NLS-1$
+			}
+        }
+        
+		if (JavaEnvUtils.getJavaVersion().equals(JavaEnvUtils.JAVA_1_0)
+				|| JavaEnvUtils.getJavaVersion().equals(JavaEnvUtils.JAVA_1_1)
+				|| JavaEnvUtils.getJavaVersion().equals(JavaEnvUtils.JAVA_1_2)
+				|| JavaEnvUtils.getJavaVersion().equals(JavaEnvUtils.JAVA_1_3)) {
+			this.customDefaultOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_3);
+		} else if (JavaEnvUtils.getJavaVersion().equals(JavaEnvUtils.JAVA_1_4)) {
+			if (this.target != null && this.target.equals("1.1")) {			   //$NON-NLS-1$	
+				this.customDefaultOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_3);
+			} else {
+				this.customDefaultOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
+			}
+		} else if (JavaEnvUtils.getJavaVersion().equals(JavaEnvUtils.JAVA_1_5)) {
+			this.customDefaultOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
+		} else {
+            this.attributes.log(AntAdapterMessages.getString("ant.jdtadapter.info.unknownVmVersion", JavaEnvUtils.getJavaVersion()), Project.MSG_WARN); //$NON-NLS-1$
+		}
+		
+		/*
+		 * encoding option
+		 */
+        if (this.encoding != null) {
+            cmd.createArgument().setValue("-encoding"); //$NON-NLS-1$
+            cmd.createArgument().setValue(this.encoding);
+        }
+
+		if (compilerArgs != null) {
 	        /*
 			 * Add extra argument on the command line
 			 */
@@ -253,70 +360,6 @@
 		        cmd.addArguments(compilerArgs);
 			}
 	   	}
-
-	   	/*
-		 * destDir option.
-		 */		
-		if (destDir != null) {
-			cmd.createArgument().setValue("-d"); //$NON-NLS-1$
-			cmd.createArgument().setFile(destDir.getAbsoluteFile());
-		}
-
-		/*
-		 * target option.
-		 */		
-		if (target != null) {
-			cmd.createArgument().setValue("-target"); //$NON-NLS-1$
-			cmd.createArgument().setValue(target);
-		}
-
-		/*
-		 * verbose option
-		 */
-		if (verbose) {
-			cmd.createArgument().setValue("-verbose"); //$NON-NLS-1$
-			/*
-			 * extra option allowed by the Eclipse compiler
-			 */
-			cmd.createArgument().setValue("-log"); //$NON-NLS-1$
-			logFileName = destDir.getAbsolutePath() + ".log"; //$NON-NLS-1$
-			cmd.createArgument().setValue(logFileName);
-		}
-
-		/*
-		 * failnoerror option
-		 */
-		if (!attributes.getFailonerror()) {
-			cmd.createArgument().setValue("-proceedOnError"); //$NON-NLS-1$
-		}
-
-		/*
-		 * source option
-		 */
-		String source = attributes.getSource();
-        if (source != null) {
-            cmd.createArgument().setValue("-source"); //$NON-NLS-1$
-            cmd.createArgument().setValue(source);
-        }
-        
-		if (JavaEnvUtils.getJavaVersion().equals(JavaEnvUtils.JAVA_1_4)) {
-			if (target != null && target.equals("1.1")) {			   //$NON-NLS-1$	
-				cmd.createArgument().setValue("-1.3"); //$NON-NLS-1$
-			} else {
-				cmd.createArgument().setValue("-1.4"); //$NON-NLS-1$
-			}
-		} else {
-			cmd.createArgument().setValue("-1.3"); //$NON-NLS-1$
-		}
-		
-		/*
-		 * encoding option
-		 */
-        if (encoding != null) {
-            cmd.createArgument().setValue("-encoding"); //$NON-NLS-1$
-            cmd.createArgument().setValue(encoding);
-        }
-
      	/*
 		 * Eclipse compiler doesn't have a -sourcepath option. This is
 		 * handled through the javac task that collects all source files in
diff --git a/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/internal/antadapter/messages.properties b/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/internal/antadapter/messages.properties
index c09de8d..781388a 100644
--- a/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/internal/antadapter/messages.properties
+++ b/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/internal/antadapter/messages.properties
@@ -14,6 +14,9 @@
 ant.jdtadapter.error.cannotFindJDTCompiler=Cannot find the JDT compiler
 ant.jdtadapter.info.ignoringMemoryInitialSize=Since fork is false, ignoring memoryInitialSize setting
 ant.jdtadapter.info.ignoringMemoryMaximumSize=Since fork is false, ignoring memoryMaximumSize setting
+ant.jdtadapter.info.unknownVmVersion={0} : Unknown VM version, default compliance used
+ant.jdtadapter.info.unknownTarget={0} : Unknown target, default used
+ant.jdtadapter.info.unknownSource={0} : Unknown source, default used
 
 checkDebugAttributes.file.argument.cannot.be.null=The file argument cannot be null
 checkDebugAttributes.property.argument.cannot.be.null=The property argument cannot be null
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
index 2fe7ad9..707a9db 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
@@ -90,18 +90,18 @@
 	if (sourceExists) {
 		String fullSourcePath = this.path + qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6)  + SUFFIX_STRING_java;
 		if (!binaryExists)
-			return new NameEnvironmentAnswer(new CompilationUnit(null, fullSourcePath, this.encoding));
+			return new NameEnvironmentAnswer(new CompilationUnit(null, fullSourcePath, this.encoding), null/* TODO no access restriction*/);
 
 		String fullBinaryPath = this.path + qualifiedBinaryFileName;
 		long binaryModified = new File(fullBinaryPath).lastModified();
 		long sourceModified = new File(fullSourcePath).lastModified();
 		if (sourceModified > binaryModified)
-			return new NameEnvironmentAnswer(new CompilationUnit(null, fullSourcePath, this.encoding));
+			return new NameEnvironmentAnswer(new CompilationUnit(null, fullSourcePath, this.encoding), null/* TODO no access restriction*/);
 	}
 	if (binaryExists) {
 		try {
 			ClassFileReader reader = ClassFileReader.read(this.path + qualifiedBinaryFileName);
-			if (reader != null) return new NameEnvironmentAnswer(reader);
+			if (reader != null) return new NameEnvironmentAnswer(reader, null/* TODO no access restriction*/);
 		} catch (Exception e) { 
 			// treat as if file is missing
 		}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
index 7915f78..6bc60be 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
@@ -40,7 +40,7 @@
 
 	try {
 		ClassFileReader reader = ClassFileReader.read(this.zipFile, qualifiedBinaryFileName);
-		if (reader != null) return new NameEnvironmentAnswer(reader);
+		if (reader != null) return new NameEnvironmentAnswer(reader, null /*no access restriction*/);
 	} catch (Exception e) {
 		// treat as if class file is missing
 	}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java
index d9870d5..fea1e7d 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java
@@ -60,6 +60,9 @@
 	}
 	return CharOperation.NO_CHAR;
 }
+/**
+ * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
+ */
 public char[] getFileName() {
 	return this.fileName;
 }
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
index dc912ac..d3ad3c8 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
@@ -21,6 +21,7 @@
 import java.io.StringReader;
 import java.io.UnsupportedEncodingException;
 import java.util.Enumeration;
+import java.util.Iterator;
 import java.util.Locale;
 import java.util.Map;
 import java.util.MissingResourceException;
@@ -49,6 +50,61 @@
 
 public class Main implements ProblemSeverities, SuffixConstants {
 
+	public static class Logger {
+		
+		PrintWriter out;
+		PrintWriter err;
+		PrintWriter log;
+		
+		public Logger(PrintWriter out, PrintWriter err) {
+			this.out = out;
+			this.err = err;
+		}
+		
+		public void setLog(PrintWriter log) {
+			this.log = log;
+		}
+		
+		public void close() {
+			if (this.log != null) {
+				this.log.close();
+			}
+		}
+		
+		public void flush() {
+			this.out.flush();
+			this.err.flush();
+			if (this.log != null) {
+				this.log.flush();
+			}
+		}
+		
+		public void printErr(String s) {
+			this.err.print(s);
+			if (this.log != null) {
+				this.log.print(s);
+			}
+		}
+		
+		public void printlnErr(String s) {
+			this.err.println(s);
+			if (this.log != null) {
+				this.log.println(s);
+			}
+		}
+		
+		public void printlnOut(String s) {
+			this.out.println(s);
+		}
+		
+		public void printlnOut() {
+			this.out.println();
+		}
+		
+		public void printOut(char c) {
+			this.out.print(c);
+		}
+	}
 	static {
 		relocalize();
 	}
@@ -63,7 +119,7 @@
 	public String[] classpaths;
 	public String destinationPath;
 	public String[] encodings;
-	public PrintWriter err;	
+	public Logger logger;	
 	public int exportedClassFilesCounter;
 	public String[] filenames;
 	public boolean generatePackagesStructure;
@@ -78,8 +134,6 @@
 	public Map options; 
 	public CompilerOptions compilerOptions; // read-only
 
-	public PrintWriter out;
-
 	public boolean proceed = true;
 	public boolean proceedOnError = false;
 	public boolean produceRefInfo = false;
@@ -92,53 +146,49 @@
 	public boolean verbose = false;
 
 	public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished) {
-
-		this.out = outWriter;
-		this.err = errWriter;
+		this(outWriter, errWriter, systemExitWhenFinished, null);
+	}
+	
+	public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished, Map customDefaultOptions) {
+		this.logger = new Logger(outWriter, errWriter);
 		this.systemExitWhenFinished = systemExitWhenFinished;
 		this.options = new CompilerOptions().getMap();
+		if (customDefaultOptions != null) {
+			for (Iterator iter = customDefaultOptions.keySet().iterator(); iter.hasNext();) {
+				Object key = iter.next();
+				this.options.put(key, customDefaultOptions.get(key));
+			}
+		}
 	}
-
-	/**
+	
+	/*
 	 * Lookup the message with the given ID in this catalog 
-	 * @param id
-	 * @return
 	 */
 	public static String bind(String id) {
 		return bind(id, (String[]) null);
 	}
 
-	/**
+	/*
 	 * Lookup the message with the given ID in this catalog and bind its
 	 * substitution locations with the given string.
-	 * @param id
-	 * @param binding
-	 * @return
 	 */
 	public static String bind(String id, String binding) {
 		return bind(id, new String[] { binding });
 	}
 
-	/**
+	/*
 	 * Lookup the message with the given ID in this catalog and bind its
 	 * substitution locations with the given strings.
-	 * @param id
-	 * @param binding1
-	 * @param binding2
-	 * @return
 	 */
 	public static String bind(String id, String binding1, String binding2) {
 		return bind(id, new String[] { binding1, binding2 });
 	}
 
-	/**
+	/*
 	 * Lookup the message with the given ID in this catalog and bind its
 	 * substitution locations with the given string values.
-	 * @param id
-	 * @param bindings
-	 * @return
 	 */
-	public static String bind(String id, String[] bindings) {
+	public static String bind(String id, String[] arguments) {
 		if (id == null)
 			return "No message available"; //$NON-NLS-1$
 		String message = null;
@@ -152,8 +202,8 @@
 		// for compatibility with MessageFormat which eliminates double quotes in original message
 		char[] messageWithNoDoubleQuotes =
 			CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
+		
 		message = new String(messageWithNoDoubleQuotes);
-
 		int length = message.length();
 		int start = -1;
 		int end = length;
@@ -165,8 +215,13 @@
 				if ((start = message.indexOf('}', end)) > -1) {
 					int index = -1;
 					try {
-						index = Integer.parseInt(message.substring(end + 1, start));
-						output.append(bindings[index]);
+						String argId = message.substring(end + 1, start);
+						index = Integer.parseInt(argId);
+						if (arguments[index] == null) {
+							output.append('{').append(argId).append('}'); // leave parameter in since no better arg '{0}'
+						} else {
+							output.append(arguments[index]);
+						}						
 					} catch (NumberFormatException nfe) { // could be nested message ID {compiler.name}
 						String argId = message.substring(end + 1, start);
 						boolean done = false;
@@ -300,7 +355,7 @@
 //					System.out.println(new CompilerOptions(this.options));
 //				}
 				if (this.showProgress)
-					this.out.println(Main.bind("progress.compiling")); //$NON-NLS-1$
+					this.logger.printlnOut(Main.bind("progress.compiling")); //$NON-NLS-1$
 				for (int i = 0; i < this.repetitions; i++) {
 					this.globalProblemsCount = 0;
 					this.globalErrorsCount = 0;
@@ -309,8 +364,8 @@
 					this.exportedClassFilesCounter = 0;
 
 					if (this.repetitions > 1) {
-						this.out.flush();
-						this.out.println(
+						this.logger.flush();
+						this.logger.printlnOut(
 							Main.bind(
 								"compile.repetition", //$NON-NLS-1$
 								String.valueOf(i + 1),
@@ -320,36 +375,31 @@
 					performCompilation();
 				}
 				if (this.showProgress)
-					this.out.println();
+					this.logger.printlnOut();
 			}
 			if (this.systemExitWhenFinished) {
-				this.out.flush();
-				this.err.flush();
+				this.logger.flush();
 				System.exit(this.globalErrorsCount > 0 ? -1 : 0);
 			}
 		} catch (InvalidInputException e) {
-			this.err.println(e.getMessage());
+			this.logger.printlnErr(e.getMessage());
 			if (this.systemExitWhenFinished) {
+    			this.logger.flush();
+    			this.logger.close();
 				System.exit(-1);
 			}
 			return false;
 		} catch (RuntimeException e) { // internal compiler failure
 			if (this.systemExitWhenFinished) {
-				this.out.flush();
-				this.err.flush();
-				if (this.log != null) {
-					this.err.close();
-				}
+				this.logger.flush();
+				this.logger.close();
 				System.exit(-1);
 			}
 			return false;
 			//e.printStackTrace();
 		} finally {
-			this.out.flush();
-			this.err.flush();
-			if (this.log != null) {
-				this.err.close();
-			}
+			this.logger.flush();
+			this.logger.close();
 		}
 		if (this.globalErrorsCount == 0)
 			return true;
@@ -385,6 +435,7 @@
 		boolean printUsageRequired = false;
 		boolean printVersionRequired = false;
 		
+		boolean didSpecifySource = false;
 		boolean didSpecifyCompliance = false;
 		boolean didSpecifyDefaultEncoding = false;
 		boolean didSpecifyTarget = false;
@@ -545,6 +596,16 @@
 				mode = Default;
 				continue;
 			}
+			if (currentArg.equals("-1.5")) { //$NON-NLS-1$
+				if (didSpecifyCompliance) {
+					throw new InvalidInputException(
+						Main.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
+				}
+				didSpecifyCompliance = true;
+				this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
+				mode = Default;
+				continue;
+			}			
 			if (currentArg.equals("-d")) { //$NON-NLS-1$
 				if (this.destinationPath != null)
 					throw new InvalidInputException(
@@ -819,6 +880,10 @@
 						this.options.put(
 							CompilerOptions.OPTION_ReportEmptyStatement,
 							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("serial")) {//$NON-NLS-1$ 
+						this.options.put(
+							CompilerOptions.OPTION_ReportMissingSerialVersion,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
 					} else if (token.equals("emptyBlock")) {//$NON-NLS-1$ 
 						this.options.put(
 							CompilerOptions.OPTION_ReportUndocumentedEmptyBlock,
@@ -827,11 +892,19 @@
 						this.options.put(
 							CompilerOptions.OPTION_ReportUnnecessaryTypeCheck,
 							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("unchecked") || token.equals("unsafe")) {//$NON-NLS-1$ //$NON-NLS-2$ 
+						this.options.put(
+							CompilerOptions.OPTION_ReportUncheckedTypeOperation,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("finalBound")) {//$NON-NLS-1$ 
+						this.options.put(
+							CompilerOptions.OPTION_ReportFinalParameterBound,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
 					} else if (token.equals("unnecessaryElse")) {//$NON-NLS-1$ 
 						this.options.put(
 							CompilerOptions.OPTION_ReportUnnecessaryElse,
 							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("javadoc")) {//$NON-NLS-1$
+					} else if (token.equals("javadoc")) {//$NON-NLS-1$ 
 						if (!useEnableJavadoc) {
 							this.options.put(
 								CompilerOptions.OPTION_DocCommentSupport,
@@ -846,6 +919,12 @@
 								CompilerOptions.OPTION_ReportInvalidJavadocTags,
 								CompilerOptions.ENABLED);
 							this.options.put(
+								CompilerOptions.OPTION_ReportInvalidJavadocTagsDeprecatedRef,
+								CompilerOptions.DISABLED);
+							this.options.put(
+								CompilerOptions.OPTION_ReportInvalidJavadocTagsNotVisibleRef,
+								CompilerOptions.DISABLED);
+							this.options.put(
 								CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility,
 								CompilerOptions.PRIVATE);
 							this.options.put(
@@ -900,6 +979,10 @@
 						this.options.put(
 							CompilerOptions.OPTION_ReportAssertIdentifier,
 							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("enumIdentifier")) { //$NON-NLS-1$
+						this.options.put(
+								CompilerOptions.OPTION_ReportEnumIdentifier,
+								isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
 					} else if (token.equals("finally")) { //$NON-NLS-1$
 						this.options.put(
 							CompilerOptions.OPTION_ReportFinallyBlockNotCompletingNormally,
@@ -912,6 +995,18 @@
 						this.options.put(
 							CompilerOptions.OPTION_ReportUnqualifiedFieldAccess,
 							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("varargsCast")) { //$NON-NLS-1$
+						this.options.put(
+							CompilerOptions.OPTION_ReportVarargsArgumentNeedCast,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);						
+					} else if (token.equals("null")) { //$NON-NLS-1$
+						this.options.put(
+							CompilerOptions.OPTION_ReportNullReference,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);						
+					} else if (token.equals("boxing")) { //$NON-NLS-1$
+						this.options.put(
+							CompilerOptions.OPTION_ReportAutoboxing,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);						
 					} else {
 						throw new InvalidInputException(Main.bind("configure.invalidWarning", token)); //$NON-NLS-1$
 					}
@@ -940,6 +1035,10 @@
 				continue;
 			}
 			if (mode == TargetSetting) {
+				if (didSpecifyTarget) {
+					throw new InvalidInputException(
+						Main.bind("configure.duplicateTarget", currentArg));//$NON-NLS-1$
+				}				
 				didSpecifyTarget = true;
 				if (currentArg.equals("1.1")) { //$NON-NLS-1$
 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
@@ -949,10 +1048,16 @@
 					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_3) {
-						throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget14", (String)this.options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$
+					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$
 					}
 					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
+				} else if (currentArg.equals("1.5") || currentArg.equals("5")) { //$NON-NLS-1$//$NON-NLS-2$
+					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$
+					}
+					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
 				} else {
 					throw new InvalidInputException(Main.bind("configure.targetJDK", currentArg)); //$NON-NLS-1$
 				}
@@ -990,10 +1095,17 @@
 				continue;
 			}
 			if (mode == InsideSource) {
+				if (didSpecifySource) {
+					throw new InvalidInputException(
+						Main.bind("configure.duplicateSource", currentArg));//$NON-NLS-1$
+				}				
+				didSpecifySource = true;
 				if (currentArg.equals("1.3")) { //$NON-NLS-1$
 					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
 				} else if (currentArg.equals("1.4")) { //$NON-NLS-1$
 					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4);
+				} else if (currentArg.equals("1.5") || currentArg.equals("5")) { //$NON-NLS-1$//$NON-NLS-2$
+					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
 				} else {
 					throw new InvalidInputException(Main.bind("configure.source", currentArg)); //$NON-NLS-1$
 				}
@@ -1124,7 +1236,7 @@
 			// no user classpath specified.
 			String classProp = System.getProperty("java.class.path"); //$NON-NLS-1$
 			if ((classProp == null) || (classProp.length() == 0)) {
-				this.err.println(Main.bind("configure.noClasspath")); //$NON-NLS-1$
+				this.logger.printlnErr(Main.bind("configure.noClasspath")); //$NON-NLS-1$
 				classProp = System.getProperty("user.dir"); //$NON-NLS-1$
 			}
 			StringTokenizer tokenizer = new StringTokenizer(classProp, File.pathSeparator);
@@ -1142,7 +1254,7 @@
 			 */
 			 String javaversion = System.getProperty("java.version");//$NON-NLS-1$
 			 if (javaversion != null && javaversion.equalsIgnoreCase("1.1.8")) { //$NON-NLS-1$
-				this.err.println(Main.bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$
+				this.logger.printlnErr(Main.bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$
 				this.proceed = false;
 				return;
 			 }
@@ -1180,7 +1292,7 @@
 
 		if (this.log != null) {
 			try {
-				this.err = new PrintWriter(new FileOutputStream(this.log, false));
+				this.logger.setLog(new PrintWriter(new FileOutputStream(this.log, false)));
 			} catch (IOException e) {
 				throw new InvalidInputException(Main.bind("configure.cannotOpenLog")); //$NON-NLS-1$
 			}
@@ -1219,7 +1331,7 @@
 		for (int i = 0, max = this.classpaths.length; i < max; i++) {
 			File file = new File(this.classpaths[i]);
 			if (!file.exists()) { // signal missing classpath entry file
-				this.out.println(Main.bind("configure.incorrectClasspath", this.classpaths[i])); //$NON-NLS-1$
+				this.logger.printlnErr(Main.bind("configure.incorrectClasspath", this.classpaths[i])); //$NON-NLS-1$
 			}
 		}
 		if (this.destinationPath == null) {
@@ -1227,32 +1339,59 @@
 		} else if ("none".equals(this.destinationPath)) { //$NON-NLS-1$
 			this.destinationPath = null;
 		}
-
-		// target must be 1.4 if source is 1.4
-		if (CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Source)) >= ClassFileConstants.JDK1_4
-				&& CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_TargetPlatform)) < ClassFileConstants.JDK1_4
-				&& didSpecifyTarget){ 
-				throw new InvalidInputException(Main.bind("configure.incompatibleTargetForSource14", (String)this.options.get(CompilerOptions.OPTION_TargetPlatform))); //$NON-NLS-1$
-		}
-
-		// target cannot be 1.4 if compliance is 1.3
-		if (CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) < ClassFileConstants.JDK1_4
-				&& CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_TargetPlatform)) >= ClassFileConstants.JDK1_4
-				&& didSpecifyTarget){ 
-				throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget14", (String)this.options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$
-		}
 		
-		// check and set compliance/source/target compatibilities
-		if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)){
-			if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
-			if (!didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
+		if (didSpecifyCompliance) {
+			Object version = this.options.get(CompilerOptions.OPTION_Compliance);
+			if (CompilerOptions.VERSION_1_3.equals(version)) {
+					if (!didSpecifySource) this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
+					if (!didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
+			} else if (CompilerOptions.VERSION_1_4.equals(version)) {
+					if (!didSpecifySource) this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
+					if (!didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
+			} else if (CompilerOptions.VERSION_1_5.equals(version)) {
+					if (!didSpecifySource) this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
+					if (!didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
+			}
 		}
-		// compliance must be 1.4 if source is 1.4
-		if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)
-				&& !this.options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_4)){ 
-				throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForSource14", (String)this.options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$
+		if (didSpecifySource) {
+			Object version = this.options.get(CompilerOptions.OPTION_Source);
+			 if (CompilerOptions.VERSION_1_4.equals(version)) {
+					if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
+					if (!didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
+			} else if (CompilerOptions.VERSION_1_5.equals(version)) {
+					if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
+					if (!didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
+			}
 		}
 
+		// check and set compliance/source/target compatibilities
+		if (didSpecifyTarget) {
+			// target must be 1.5 if source is 1.5
+			if (CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Source)) >= ClassFileConstants.JDK1_5
+					&& CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_TargetPlatform)) < ClassFileConstants.JDK1_5){ 
+				throw new InvalidInputException(Main.bind("configure.incompatibleTargetForSource", (String)this.options.get(CompilerOptions.OPTION_TargetPlatform), CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
+			}
+	   		 // target must be 1.4 if source is 1.4
+	   		if (CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Source)) >= ClassFileConstants.JDK1_4
+					&& CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_TargetPlatform)) < ClassFileConstants.JDK1_4){ 
+				throw new InvalidInputException(Main.bind("configure.incompatibleTargetForSource", (String)this.options.get(CompilerOptions.OPTION_TargetPlatform), CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
+	   		}
+			// target cannot be greater than compliance level
+			if (CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) < CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_TargetPlatform))){ 
+					throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget", (String)this.options.get(CompilerOptions.OPTION_Compliance), (String)this.options.get(CompilerOptions.OPTION_TargetPlatform))); //$NON-NLS-1$
+			}
+		}
+
+		// compliance must be 1.5 if source is 1.5
+		if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_5)
+				&& CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) < ClassFileConstants.JDK1_5) {
+			throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForSource", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
+		} else 
+			// compliance must be 1.4 if source is 1.4
+			if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)
+					&& CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) < ClassFileConstants.JDK1_4) { 
+				throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForSource", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
+		}
 		// set default target according to compliance & sourcelevel.
 		if (!didSpecifyTarget) {
 			if (this.options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_3)) {
@@ -1263,6 +1402,14 @@
 				} else if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)) {
 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
 				}
+			} else if (this.options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_5)) {
+				if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_3)) {
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
+				} else if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)) {
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
+				} else if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_5)) {
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
+				}
 			}
 		}
 
@@ -1311,7 +1458,7 @@
 					this.lineDelta += unitLineCount;
 					if (Main.this.showProgress
 						&& this.lineDelta > 2000) { // in -log mode, dump a dot every 2000 lines compiled
-						Main.this.out.print('.');
+						Main.this.logger.printOut('.');
 						this.lineDelta = 0;
 					}
 				}
@@ -1324,8 +1471,8 @@
 						if (problems[i] != null) {
 							Main.this.globalProblemsCount++;
 							if (localErrorCount == 0)
-								Main.this.err.println("----------"); //$NON-NLS-1$
-							Main.this.err.print(
+								Main.this.logger.printlnErr("----------"); //$NON-NLS-1$
+							Main.this.logger.printErr(
 								Main.this.globalProblemsCount
 									+ ". "  //$NON-NLS-1$
 									+ (problems[i].isError()
@@ -1336,18 +1483,18 @@
 							} else {
 								Main.this.globalWarningsCount++;
 							}
-							Main.this.err.print(" "); //$NON-NLS-1$
-							Main.this.err.print(
+							Main.this.logger.printErr(" "); //$NON-NLS-1$
+							Main.this.logger.printErr(
 								Main.bind("requestor.in", new String(problems[i].getOriginatingFileName()))); //$NON-NLS-1$
 							try {
-								Main.this.err.println(
+								Main.this.logger.printlnErr(
 									((DefaultProblem) problems[i]).errorReportSource(unitSource));
-								Main.this.err.println(problems[i].getMessage());
+								Main.this.logger.printlnErr(problems[i].getMessage());
 							} catch (Exception e) {
-								Main.this.err.println(
+								Main.this.logger.printlnErr(
 									Main.bind("requestor.notRetrieveErrorMessage", problems[i].toString())); //$NON-NLS-1$
 							}
-							Main.this.err.println("----------"); //$NON-NLS-1$
+							Main.this.logger.printlnErr("----------"); //$NON-NLS-1$
 							if (problems[i].isError())
 								localErrorCount++;
 						}
@@ -1355,8 +1502,7 @@
 					// exit?
 					if (Main.this.systemExitWhenFinished && !Main.this.proceedOnError && (localErrorCount > 0)) {
 						Main.this.printStats();
-						Main.this.err.flush();
-						Main.this.out.flush();
+						Main.this.logger.flush();
 						System.exit(-1);
 					}
 				}
@@ -1485,7 +1631,7 @@
 					} catch (IOException e) {
 						String fileName = this.destinationPath + new String(relativeName);
 						e.printStackTrace();
-						this.err.println(Main.bind("output.noClassFileCreated", fileName));  //$NON-NLS-1$
+						this.logger.printlnErr(Main.bind("output.noClassFileCreated", fileName));  //$NON-NLS-1$
 					}
 					this.exportedClassFilesCounter++;
 				}
@@ -1513,7 +1659,7 @@
 					} catch (IOException e) {
 						String fileName = this.destinationPath + new String(relativeName);
 						e.printStackTrace();
-						this.err.println(Main.bind("output.noClassFileCreated", fileName)); //$NON-NLS-1$
+						this.logger.printlnErr(Main.bind("output.noClassFileCreated", fileName)); //$NON-NLS-1$
 					}
 					this.exportedClassFilesCounter++;
 				}
@@ -1553,7 +1699,7 @@
 
 			long time = System.currentTimeMillis() - this.startTime;
 			if (this.lineCount != 0) {
-				this.out.println(
+				this.logger.printlnOut(
 					Main.bind(
 						"compile.instantTime", 	//$NON-NLS-1$
 						new String[] {
@@ -1561,44 +1707,44 @@
 							String.valueOf(time),
 							String.valueOf(((int)(this.lineCount * 10000.0 / time)) / 10.0)}));
 			} else {
-				this.out.println(Main.bind("compile.totalTime", String.valueOf(time))); //$NON-NLS-1$
+				this.logger.printlnOut(Main.bind("compile.totalTime", String.valueOf(time))); //$NON-NLS-1$
 			}
 		}
 		if (this.globalProblemsCount > 0) {
 			if (this.globalProblemsCount == 1) {
-				this.err.print(Main.bind("compile.oneProblem")); //$NON-NLS-1$
+				this.logger.printErr(Main.bind("compile.oneProblem")); //$NON-NLS-1$
 			} else {
-				this.err.print(
+				this.logger.printErr(
 					Main.bind("compile.severalProblems", String.valueOf(this.globalProblemsCount))); 	//$NON-NLS-1$
 			}
-			this.err.print(" ("); //$NON-NLS-1$
+			this.logger.printErr(" ("); //$NON-NLS-1$
 			if (this.globalErrorsCount > 0) {
 				if (this.globalErrorsCount == 1) {
-					this.err.print(Main.bind("compile.oneError")); //$NON-NLS-1$
+					this.logger.printErr(Main.bind("compile.oneError")); //$NON-NLS-1$
 				} else {
-					this.err.print(
+					this.logger.printErr(
 						Main.bind("compile.severalErrors", String.valueOf(this.globalErrorsCount))); 	//$NON-NLS-1$
 				}
 			}
 			if (this.globalWarningsCount > 0) {
 				if (this.globalErrorsCount > 0) {
-					this.err.print(", "); //$NON-NLS-1$
+					this.logger.printErr(", "); //$NON-NLS-1$
 				}
 				if (this.globalWarningsCount == 1) {
-					this.err.print(Main.bind("compile.oneWarning")); //$NON-NLS-1$
+					this.logger.printErr(Main.bind("compile.oneWarning")); //$NON-NLS-1$
 				} else {
-					this.err.print(
+					this.logger.printErr(
 						Main.bind("compile.severalWarnings", String.valueOf(this.globalWarningsCount))); 	//$NON-NLS-1$
 				}
 			}
-			this.err.println(")"); //$NON-NLS-1$
+			this.logger.printlnErr(")"); //$NON-NLS-1$
 		}
 		if (this.exportedClassFilesCounter != 0
 			&& (this.showProgress || this.timing || this.verbose)) {
 			if (this.exportedClassFilesCounter == 1) {
-				this.out.println(Main.bind("compile.oneClassFileGenerated")); //$NON-NLS-1$
+				this.logger.printlnOut(Main.bind("compile.oneClassFileGenerated")); //$NON-NLS-1$
 			} else {
-				this.out.println(
+				this.logger.printlnOut(
 					Main.bind(
 						"compile.severalClassFilesGenerated", //$NON-NLS-1$
 						String.valueOf(this.exportedClassFilesCounter)));
@@ -1606,13 +1752,11 @@
 		}
 	}
 	public void printUsage() {
-		this.out.println(Main.bind("misc.usage", System.getProperty("path.separator"))); //$NON-NLS-1$//$NON-NLS-2$
-		this.out.flush();
-		this.err.flush();
+		this.logger.printlnOut(Main.bind("misc.usage", System.getProperty("path.separator"))); //$NON-NLS-1$//$NON-NLS-2$
+		this.logger.flush();
 	}
 	public void printVersion() {
-		this.out.println(Main.bind("misc.version"));  //$NON-NLS-1$
-		this.out.flush();
-		this.err.flush();
+		this.logger.printlnOut(Main.bind("misc.version"));  //$NON-NLS-1$
+		this.logger.flush();
 	}
 }
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
index 2b042c0..5fc0791 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
@@ -10,10 +10,12 @@
 ###############################################################################
 ### JavaBatchCompiler messages.
 
-### compiler 
+### compiler
+#Format: compiler.name = word1 word2 word3
 compiler.name = Eclipse Java Compiler
-compiler.version = 0.450
-compiler.copyright = Copyright IBM Corp 2000, 2004. All rights reserved.
+#Format: compiler.version = 0.XXX[, other words (don't forget the comma if adding other words)]
+compiler.version = 0.531, pre-3.1.0 milestone-5
+compiler.copyright = Copyright IBM Corp 2000, 2005. All rights reserved.
 
 ### scanning
 scanning.start = Collecting source files inside {0}
@@ -40,18 +42,19 @@
 configure.duplicateRepeat = duplicate repeat specification: {0}
 configure.duplicateMaxProblems = duplicate max problems specification: {0}
 configure.duplicateCompliance = duplicate compliance setting specification: {0}
-configure.source = invalid source option, source is either ''1.3'' or ''1.4'': {0}
+configure.duplicateSource = duplicate source compliance setting specification: {0}
+configure.duplicateTarget = duplicate target compliance setting specification: {0}
+configure.source = source level should be comprised in between ''1.3'' and ''1.5'' or ''5'': {0}
 configure.duplicateOutputPath = duplicate output path specification: {0}
 configure.duplicateBootClasspath = duplicate bootclasspath specification: {0}
 configure.invalidDebugOption = invalid debug option: {0}
 configure.invalidWarningConfiguration = invalid warning configuration: {0}
 configure.invalidWarning = invalid warning: {0}
 configure.invalidWarningOption = invalid warning option: {0}
-configure.targetJDK = target JDK should be comprised in between ''1.1'' and ''1.4'': {0}
-configure.incompatibleTargetForSource14 = ''1.4'' source mode requires ''-target 1.4'' : {0}
-configure.incompatibleComplianceForSource14 = ''1.4'' source mode requires ''-1.4'' compliance mode: {0}
-configure.incompatibleComplianceForTarget14 = ''1.4'' target mode requires ''-1.4'' compliance mode: {0}
-configure.incompatibleComplianceForTarget11 = ''1.1'' target mode requires ''-1.3'' compliance mode: {0}
+configure.targetJDK = target level should be comprised in between ''1.1'' and ''1.5'' or ''5'': {0}
+configure.incompatibleTargetForSource = Target level ''{0}'' is incompatible with source level ''{1}''. A target level ''{1}'' or better is required
+configure.incompatibleComplianceForSource = Compliance level ''{0}'' is incompatible with source level ''{1}''. A compliance level ''{1}'' or better is required
+configure.incompatibleComplianceForTarget = Compliance level ''{0}'' is incompatible with target level ''{1}''. A compliance level ''{1}'' or better is required
 configure.repetition = repetition must be a positive integer: {0}
 configure.maxProblems = max problems must be a positive integer: {0}
 configure.directoryNotExist = directory does not exist: {0}
@@ -99,8 +102,9 @@
 \ Compliance options:\n\
 \    -1.3               use 1.3 compliance level (implicit -source 1.3 -target 1.1)\n\
 \    -1.4             + use 1.4 compliance level (implicit -source 1.3 -target 1.2)\n\
-\    -source <version>  set source level (1.3 or 1.4)\n\
-\    -target <version>  set classfile target (1.1 to 1.4)\n\
+\    -1.5               use 1.5 compliance level (implicit -source 1.5 -target 1.5)\n\
+\    -source <version>  set source level (1.3 to 1.5 or 5)\n\
+\    -target <version>  set classfile target level (1.1 to 1.5 or 5)\n\
 \ \n\
 \ Warning options:\n\
 \    -deprecation     + deprecation outside deprecated code\n\
@@ -112,12 +116,14 @@
 \      allDeprecation       deprecation including inside deprecated code\n\
 \      allJavadoc           invalid or missing javadoc\n\
 \      assertIdentifier   + ''assert'' used as identifier\n\
+\      boxing               autoboxing conversion\n\
 \      charConcat         + char[] in String concat\n\
 \      conditionAssign      possible accidental boolean assignment\n\
 \      constructorName    + method with constructor name\n\
 \      deprecation        + deprecation outside deprecated code\n\
 \      emptyBlock           undocumented empty block\n\
 \      fieldHiding          field hiding another variable\n\
+\      finalBound           type parameter with final bound\n\
 \      finally            + finally block not completing normally\n\
 \      indirectStatic       indirect reference to static member\n\
 \      intfNonInherited   + interface non-inherited method compatibility\n\
@@ -126,9 +132,13 @@
 \      maskedCatchBlock   + hidden catch block\n\
 \      nls                  string literal lacking non-nls tag //$NON-NLS-<n>$\n\
 \      noEffectAssign     + assignment without effect\n\
+\      nullCheck          + missing or redundant null check\n\
 \      pkgDefaultMethod   + attempt to override package-default method\n\
 \      semicolon            unnecessary semicolon, empty statement\n\
+\      serial             + missing serialVersionUID\n\
 \      unqualifiedField     unqualified reference to field\n\
+\      unchecked          + unchecked type operation\n\
+\      unusedArgument       unread method parameter\n\
 \      unusedImport       + unused import declaration\n\
 \      unusedLocal          unread local variable\n\
 \      unusedPrivate        unused private member declaration\n\
@@ -139,6 +149,8 @@
 \      staticReceiver     + non-static reference to static member\n\
 \      syntheticAccess      synthetic access for innerclass\n\
 \      tasks(<tags separated by |>) tasks identified by tags inside comments\n\
+\      varargsCast        + varargs argument need explicit cast\n\
+\
 \ \n\
 \ Debug options:\n\
 \    -g[:lines,vars,source] custom debug info\n\
@@ -158,7 +170,7 @@
 \    -time              display speed information \n\
 \    -noExit            do not call System.exit(n) at end of compilation (n==0 if no error)\n\
 \    -repeat <n>        repeat compilation process <n> times for perf analysis\n\
-\    -inlineJSR         inline JSR bytecode\n\
+\    -inlineJSR         inline JSR bytecode (implicit if target >= 1.5)\n\
 \    -enableJavadoc     consider references in javadoc\n\
 \ \n\
 \    -? -help           print this help message\n\
diff --git a/org.eclipse.jdt.core/buildnotes_jdt-core.html b/org.eclipse.jdt.core/buildnotes_jdt-core.html
index 5d7dced..d34328c 100644
--- a/org.eclipse.jdt.core/buildnotes_jdt-core.html
+++ b/org.eclipse.jdt.core/buildnotes_jdt-core.html
@@ -15,7 +15,7 @@
 <table border=0 cellspacing=5 cellpadding=2 width="100%" >
   <tr> 
     <td align=left width="72%">
-      <font face="Verdana, Arial, Helvetica" size="+3"><b>jdt core - build notes 3.0 stream</b></font>
+      <font face="Verdana, Arial, Helvetica" size="+3"><b>jdt core - build notes 3.1 stream</b></font>
       <br><font face="Arial, Helvetica, sans-serif" size="-2" color="#8080ff">java development tooling core</font></td>
   </tr>
 	<tr><td>&nbsp;</td></tr>
@@ -25,4486 +25,2087 @@
 	  Here are the build notes for the Eclipse JDT/Core plug-in project 
 	  <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/jdt-core-home/main.html"><b>org.eclipse.jdt.core</b></a>, 
 	  describing <a href="http://bugs.eclipse.org/bugs" target=new>bug</a> resolution and substantial changes in the <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core"><b>HEAD</b></a> branch. 
-	  This present document covers all changes since Release 2.1 (also see a summary of <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.jdt.core/notes/API_changes.html">API changes</a>).
-	  Older changes which occurred up to Release 2.1 can be found in 
+	  <!--
+	  This present document covers all changes since Release 3.0 (also see a summary of <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.jdt.core/notes/API_changes.html">API changes</a>).
+	  Older changes which occurred up to Release 3.0 can be found in 
 	  <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.jdt.core/notes/R21_buildnotes_jdt-core.html">build notes R2.1</a>.
+	  -->
+	  This present document covers all changes since Release 3.0 (also see a summary of <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.jdt.core/notes/API_changes.html">API changes</a>).
+	  <br>Maintenance of previous releases of JDT/Core is performed in parallel branches: 
+		  <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=R3_0_maintenance">R3.0.x</a>,
+		  <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=R2_1_maintenance">R2.1.x</a>,
+		  <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=R2_0_1">R2.0.x</a>, 
+		  <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=ECLIPSE_1_0">R1.0.x</a>.
 	  </font>
 	</td>
   </tr>
 </table>
 
-<a name="v_450"></a>
+<a name="v_531"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0.1 Build - ?th June 2004
-<br>Project org.eclipse.jdt.core v_450
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_450">cvs</a>).
+Eclipse SDK 3.1M5 - ?th January 2005
+<br>Project org.eclipse.jdt.core v_531
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_531">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=68772">68772</a>
-IDOMMember.getComments() sometimes returns wrong results.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68863">68863</a>
-Missing entry in local variable attribute
-
-
-<a name="v_449"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0RC4 Build - 24th June 2004 - 3.0 RELEASE CANDIDATE 4
-<br>Project org.eclipse.jdt.core v_449
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_449">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Fixed schema copyrights.</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44068">44068</a>
-[DOC] Need more project configuration tutorials
-
-<a name="v_448"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0RC4 Build - 24th June 2004
-<br>Project org.eclipse.jdt.core v_448
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_448">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Fixed mixed line delimiters.</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-
-<a name="v_447"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0RC4 Build - 23rd June 2004
-<br>Project org.eclipse.jdt.core v_447
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_447">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Copyright update to 2004.</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-
-<a name="v_446"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0RC4 Build - 22nd June 2004
-<br>Project org.eclipse.jdt.core v_446
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_446">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=67769">67769</a>
-Internal StackOverflowError occurred during project build
-
-<a name="v_445"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0RC3 Build - 18th June 2004 - 3.0 RELEASE CANDIDATE 3
-<br>Project org.eclipse.jdt.core v_445
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_445">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=66898">66898</a>
-refactor-rename: encoding is not preserved
-
-<a name="v_444"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0RC3 Build - 18th June 2004
-<br>Project org.eclipse.jdt.core v_444
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_444">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=67297">67297</a>
-Renaming included package folder throws JME 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=67786">67786</a>
-OutOfMemoryError searching for reference to Object 
-
-<a name="v_443"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0RC3 Build - 18th June 2004
-<br>Project org.eclipse.jdt.core v_443
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_443">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=67717">67717</a>
-NPE disassembling .class file
-
-<a name="v_442"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0RC3 Build - 17th June 2004
-<br>Project org.eclipse.jdt.core v_442
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_442">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=67600">67600</a>
-String Index out of bounds when searching for all types 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=67599">67599</a>
-NPE when cancelling search 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66271">66271</a>
-No need to resolve type names when selecting declaration
-
-<a name="v_441"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0RC3 Build - 16th June 2004
-<br>Project org.eclipse.jdt.core v_441
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_441">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=67324">67324</a>
-Package Explorer doesn't update included package after moving contents of source folder 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41434">41434</a>
-[msic] Slow Down using classes with many methods
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64646">64646</a>
-[Navigator] Navigator popup causes Eclipse to hang. 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65186">65186</a>
-Can't attach source from project directory [build path] 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65831">65831</a>
-search for all types slow/memory intensive [search] 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66675">66675</a>
-Extra period in the doc in 200406110010
-
-<a name="v_440"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0RC2 Build - 10th June 2004 - 3.0 RELEASE CANDIDATE 2
-<br>Project org.eclipse.jdt.core v_440
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_440">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=66551">66551</a>
-Error in org.eclipse.swt project on class PrinterData
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66573">66573</a>
-Shouldn't bind to local constructs
-
-<a name="v_439"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0RC2 Build - 10th June 2004
-<br>Project org.eclipse.jdt.core v_439
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_439">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=66216">66216</a>
-Sort Members is broken.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66437">66437</a>
-Canceling search leads to broken workspace 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65266">65266</a>
-JarPackageFragmentInfo has unnecessary field 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66098">66098</a>
-MatchLocatorParser does not need advanced syntax diagnosis
-
-<a name="v_438"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0RC2 Build - 9th June 2004
-<br>Project org.eclipse.jdt.core v_438
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_438">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=66026">66026</a>
-Large amount of garbage created by DefaultCommentMapper
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64646">64646</a>
-[Navigator] Navigator popup causes Eclipse to hang. 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65288">65288</a>
-Javadoc: tag gets mangled when javadoc closing on same line without whitespace
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65253">65253</a>
-[Javadoc] @@tag is wrongly parsed as @tag
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65180">65180</a>
-Spurious "Javadoc: xxx cannot be resolved or is not a field" error with inner classes
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65174">65174</a>
-Spurious "Javadoc: Missing reference" error
-
-<a name="v_437"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0RC2 Build - 8th June 2004
-<br>Project org.eclipse.jdt.core v_437
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_437">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=66142">66142</a>
-SearchParticipant#scheduleDocumentIndexing() fails silently if index doesn't exist 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65795">65795</a>
-source inclusion mechanism breaks type lookups 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66099">66099</a>
-Persisted container/variable values are leaked throughout a session
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65250">65250</a>
-Problem selection does not choose first n errors
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65259">65259</a>
-CodeSelect should only find one match for dup methods
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65737">65737</a>
-Strange completion by code assist 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65871">65871</a>
-Missing SUPER_INTERFACE_TYPES_PROPERTY in EnumDeclaration 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53072">53072</a>
-[DOC] Search for fully qualified constructor name reports nothing 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65116">65116</a>
-IProjectDescription.getBuildSpec copies commands 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65234">65234</a>
-Inclusion filter not working 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64657">64657</a>
-better documentation for IType#resolveType behavior 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65693">65693</a>
-Package Explorer shows .class files instead of .java 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64750">64750</a>
-NPE in Java AST Creation - editing some random file 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65562">65562</a>
-Java AST creation failure
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65531">65531</a>
-out of the box formatter settings need to be improved
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65677">65677</a>
-Creating hierarchy failed. See log for details. 0 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65090">65090</a>
-ASTParser with kind == K_STATEMENTS doesn't work unless source range specified
-	  	
-<a name="v_436"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0RC1 Build - 28th May 2004 - 3.0 RELEASE CANDIDATE 1
-<br>Project org.eclipse.jdt.core v_436
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_436">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=63534">63534</a>
-ConcurrentModificationException after "catching up" 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62131">62131</a>
-CodeStream should do bounds checks
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64470">64470</a>
-&lt;packages prefixes=..../&gt; should be removed
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64299">64299</a>
-NullPointerException when OverrideIndicatorLabelDecorator is decorating
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63550">63550</a>
-NPE "Java AST Creation"
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64421">64421</a>
-ArrayIndexOutOfBoundsException in PackageReferenceLocator.matchReportReference()
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62453">62453</a>
-Large File: Java builder not reacting on cancel
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64377">64377</a>
-CRASH: An internal error occurred during: "Java AST creation"
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64378">64378</a>
-Wording of error message
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64332">64332</a>
-Javadoc errors in non-API doc comments
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64329">64329</a>
-Missing Javadoc tags declaration in API methods
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64170">64170</a>
-Classpath reentrance protection is not thread-safe 
-
-<a name="v_435"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0RC1 Build - 27th May 2004
-<br>Project org.eclipse.jdt.core v_435
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_435">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>API polish on search matches (org.eclipse.jdt.core.search.SearchMatch hierarchy):
-<ul>
-<li>added setters for all match properties (not just length & offset)</li>
-<li>add insideDocComment argument to PackageReferenceMatch constructor (for 
-being consistent with other reference matches)</li>
-</ul>
-See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62697">62697</a> for more details.
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62854">62854</a>
-refactoring does not trigger reconcile 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62697">62697</a>
-Need to know if a package reference match is in Javadoc or in Code
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63756">63756</a>
-multiple builds early
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63077">63077</a>
-IllegalArgumentException in Openable.codeSelect 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62861">62861</a>
-ArrayIndexOutOfBoundsException in SearchableEnvironment 
-
-
-<a name="v_434"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0RC1 Build - 26th May 2004
-<br>Project org.eclipse.jdt.core v_434
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_434">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=56870">56870</a>
-copied file not shown in package explorer / java browser [ccp] 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63748">63748</a>
-Type Hierarchy: null pointer when pressing F4 on ListCellRenderer 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38839">38839</a>
-org.eclipse.jdt.internal.compiler.parser.Scanner throws thousands of Exceptions
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62869">62869</a>
-[navigation] 'Go to Next Annotation' doesn't find next error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63871">63871</a>
-Using M9, -warn: option crashes the batch compiler
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63434">63434</a>
-NPE during checkout/build 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62737">62737</a>
-Code formatter doesn't work on some files
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62639">62639</a>
-[1.5] Cheetah and extending Vector
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62769">62769</a>
-Javadoc errors in 200405180816
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62952">62952</a>
-Ant adapter behavior is a little strange
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62704">62704</a>
-Using 05180816, //toto is a task if //toto is a task tag.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51660">51660</a>
-[DOM/AST] AST.parse* should handle all legal doc tags
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51606">51606</a>
-Javadoc - {@inheritDoc} should be inefficient when not in first text element
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62713">62713</a>
-should not be able to nest output folders [build path]
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63245">63245</a>
-findPackageFragment won't return default package 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62698">62698</a>
-NPE while searching for declaration of binary package 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61017">61017</a>
-Refactoring - test case that results in uncompilable source 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63044">63044</a>
-Reference to a constructor inside a javadoc should point to a type binding and not a constructor binding
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62812">62812</a>
-Some malformed javadoc tags are not reported as malformed
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62810">62810</a>
-Deadlock when closing editors and save 
-
-
-<a name="v_433"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M9 Build - 21st May 2004 - 3.0 MILESTONE-9 / 3.0 RELEASE CANDIDATE 0
-<br>Project org.eclipse.jdt.core v_433
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_433">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>Put back test org.eclipse.jdt.core.tests.model.JavaElementDeltaTests.testBuildProjectUsedAsLib()
-after bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62927">62927</a> was fixed.
-</ul>
-
-<a name="v_432"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M9 Build - 20th May 2004
-<br>Project org.eclipse.jdt.core v_432
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_432">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>Excluded test org.eclipse.jdt.core.tests.model.JavaElementDeltaTests.testBuildProjectUsedAsLib()
-</ul>
-
-<a name="v_431"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M9 Build - 20th May 2004
-<br>Project org.eclipse.jdt.core v_431
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_431">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=62881">62881</a>
-JDT/Core could be contributing a content type for JAR manifests
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58580">58580</a>
-VariableBinding.getVariableId() returns wrong IDs for nested types
-
-<a name="v_430"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M9 Build - 18th May 2004
-<br>Project org.eclipse.jdt.core v_430
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_430">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=62608">62608</a>
-Include pattern ending with slash should include all subtree 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59933">59933</a>
-applying exclusion filter to opened java file makes it appear twice [build path]
-
-
-<a name="v_429"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M9 Build - 18th May 2004
-<br>Project org.eclipse.jdt.core v_429
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_429">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=39499">39499</a>
-keyword completion does not work in anonymous inner classes 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59282">59282</a>
-Unable to include an external folder with class files to project classpath 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52422">52422</a>
-F3 can't find method def'n inside inner (anonymous) class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62463">62463</a>
-Wrong length for ExpressionStatement after conversion
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61831">61831</a>
-Full build happens on every start of Eclipse 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62201">62201</a>
-NPE in MethodScope
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61872">61872</a>
-library looses content when setting source attachment
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54962">54962</a>
-plain reference to package not found in (@see) javadoc
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54424">54424</a>
-AST has structural problems with incomplete javadoc tags
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51951">51951</a>
-codeComplete finds no completion in method of local class inside static method 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50686">50686</a>
-NPE in MethodScope.createMethod 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61952">61952</a>
-Bad deprecation -- IJavaSearchConstants#CASE_SENSITIVE 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62068">62068</a>
-Index manager should use client's index location 
-
-<a name="v_428"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M9 Build - 13th May 2004
-<br>Project org.eclipse.jdt.core v_428
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_428">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li> Due to an implementation cleanup, the optional diagnosis for unnecessary empty statement or empty control-flow
-statement, will be reverted to ignore by default. If you did set it differently in the past, you will have to manually
-set it back. We now conform to the spec for this option (until JDT/UI converted, the old option ID was 
-incorrectly used: "org.eclipse.jdt.core.compiler.problem.superfluousSemicolon"):
-<pre>
-* COMPILER / Reporting Empty Statements and Unnecessary Semicolons
-*    When enabled, the compiler will issue an error or a warning if an empty statement or a
-*    unnecessary semicolon is encountered.
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.emptyStatement"
-*     - possible values:   { "error", "warning", "ignore" }
-*     - default:           "ignore"
-</pre>	 
+<li>Fix for <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=82004">bug 82004</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>Improved error location when type indirectly referenced from required .class files.</li>
 </ul>
 
 <h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61959">61959</a>
-dangerous practice of catching Throwable
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61882">61882</a>
-Inconsistency between build errors and reconcile errors
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35356">35356</a>
-Convert local variable to field refactoring proposes weird name 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53555">53555</a>
-SourceType#get*QualifiedName() methods return unusable/invalid names for local types 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48752">48752</a>
-Completion: relevance could be improved for non static field
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61877">61877</a>
-ClassCastException in DefaultBindingResolver
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59769">59769</a>
-Javadoc of SearchMatch#getElement(): is *enclosing* element 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58440">58440</a>
-type hierarchy incomplete when implementing fully qualified interface 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61719">61719</a>
-Incorrect fine grain delta after method copy-rename 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61075">61075</a>
-[Compiler] implementation uses numerous ArrayIndexOutOfBoundsException
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=19898">19898</a>
-StackOverflowError in BinaryExpression
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61706">61706</a>
-Improve error message when unbound reference from binaries
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78698">78698</a>
+[format] Space before ? should default to false
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81063">81063</a>
+[model] Clarify the problem requestor paramter in becomeWorkingCopy
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=82004">82004</a>
+[model][5.0] 3.1M4 type hierarchy for generic interface
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=82141">82141</a>
+AST: Missing Bindings on annotations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=82140">82140</a>
+AST: Annotation node not in AST
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=82136">82136</a>
+Interface with own Annotations not accessible when used as a library
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81727">81727</a>
+[1.5] Redundant warning of parameterized return type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81762">81762</a>
+[model] AIOOB in breakpoints view
 
-<a name="v_427"></a>
+<a name="v_530"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0M9 Build - 11th May 2004
-<br>Project org.eclipse.jdt.core v_427
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_427">cvs</a>).
+Eclipse SDK 3.1M5 - 4th January 2005
+<br>Project org.eclipse.jdt.core v_530
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_530">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
-<li>A system job now reports progress when the indexer is running.</li>
-<li>The org.eclipse.jdt.core.jdom package has been deprecated. The JDOM was made obsolete by 
-      the addition in 2.0 of the more powerful, fine-grained DOM/AST API found in the 
-      org.eclipse.jdt.core.dom package.</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60689">60689</a>
-AST on reconcile: AST without Javadoc comments created
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60365">60365</a>
-hierarchy view shows some interfaces as classes [type hierarchy] 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53290">53290</a>
-[Javadoc] Compiler should complain when tag name is not correct
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53279">53279</a>
-[Javadoc] Compiler should complain when inline tag is not terminated
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51600">51600</a>
-Javadoc: tags with errors are not stored in DOM AST Javadoc hierarchy
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59751">59751</a>
-No Feedback/information from indexing 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42402">42402</a>
-OuterClass.this does not appear in code assist of the InnerClass
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61390">61390</a>
-Indexing thread grabbing resource lock 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61408">61408</a>
-Incorrect parsing
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58859">58859</a>
-[encoding] Editor does not detect BOM on .txt files
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61148">61148</a>
-deprecate JDOM API 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61270">61270</a>
-Wrong delta when copying a package that overrides another package 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61181">61181</a>
-Task tag starting with double-/ (//) causes compile error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61040">61040</a>
-Should add protect for reentrance to #getResolvedClasspath 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61214">61214</a>
-The classpath computation inside the Java builder should get rid of duplicates entries
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60867">60867</a>
-LocalVariableReferenceMatch should offer isReadAccess(), etc. 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59638">59638</a>
-ConcurrentModificationException in JavaModelManager.saving 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61052">61052</a>
-Flatten cp container initialization 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60848">60848</a>
-[reconciling] Unclosed Comment in Java Texteditor
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60822">60822</a>
-Reacting to Project > Clean... 
-	  	
-<a name="v_426"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M9 Build - 4th May 2004
-<br>Project org.eclipse.jdt.core v_426
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_426">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Added new flag IJavaElementDelta.F_PRIMARY_RESOURCE that is set when the resource of a primary working copy 
-     changes (or when it is added or removed).</li>
-<li>Removed dependency on org.eclipse.runtime.compatibility.</li>
-<li>Tuned the diagnosis for unnecessary else statements to tolerate else-if constructs.</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60687">60687</a>
-NPE in JavaCore.getEncoding
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60581">60581</a>
-"Java AST creation" error.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48502">48502</a>
-Exception during "Java AST creation"
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59750">59750</a>
-DCR: Code Assist: Hook to add getter and setters
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47227">47227</a>
-Syntax error diagnosis shouldn't expose internal goal tokens
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60595">60595</a>
-AST: AST from reconcile does not have 'ORIGINAL' bit set
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59500">59500</a>
-Java Model Notification needs notification that a java class was physically saved 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60459">60459</a>
-AST: 'malformed' flag overwrites other flags
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60367">60367</a>
-dynamic project references not maintained
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60257">60257</a>
-SearchPattern API: R_CASE_SENSITIVE vs. boolean isCaseSensitive 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58565">58565</a>
-code formatter doesn't format blocks with a return statement correctly
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58724">58724</a>
-Java code formatter should add space between imports and class definition
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60418">60418</a>
-remove warnings from core runtime deprecations 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57749">57749</a>
-Search in working copies doesn't find all matches 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60235">60235</a>
-WorkingCopyOwner needs clarification on
-
-
-<a name="v_425"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M9 Build - 28th April 2004
-<br>Project org.eclipse.jdt.core v_425
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_425">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Added API to register/deregister a pre-processing resource change listener:
+<li> Added optional compiler diagnosis reporting when boxing/unboxing conversion is performed. Corresponding problem IDs are:
+<code>IProblem.BoxingConversion</code> and <code>IProblem.UnboxingConversion</code>.
 <pre>
-/**
- * Adds the given listener for POST_CHANGE resource change events to the Java core. 
- * The listener is guarantied to be notified of the POST_CHANGE resource change event before
- * the Java core starts processing the resource change event itself.
- * 
- * Has no effect if an identical listener is already registered.
- * 
- * @param listener the listener
- * @see #removePreResourceChangeListener(IResourceChangeListener)
- * @since 3.0
- */
-public static void addPreProcessingResourceChangedListener(IResourceChangeListener listener);
-	
-/**
- * Removes the given pre-processing resource changed listener.
- *
- * Has no affect if an identical listener is not registered.
- *
- * @param listener the listener
- * @since 3.0
- */
-public static void removePreProcessingResourceChangedListener(IResourceChangeListener listener);
-</pre>
-</li>
-<li>When diagnostic for unnecessary semicolon is enabled, the compiler will also flag empty
-control-flow statement: e.g. if (bool);.  Note that the naming of the option is going soon
-to be revised to better reflect this evolution.
-Empty control-flow statement problem ID is: <tt>IProblem.EmptyControlFlowStatement</tt>.
-</li>
-<li>Added compiler style option to report situation where a statement is unnecessarily nested
-in else clause, e.g.: 
-<pre>
- if (bool) 
-   return;
- else
-   System.out.println();   // no need to be inside else
-</pre>    
-Associated problem ID is: <tt>IProblem.UnnecessaryElse</tt>.
-<pre>
-* COMPILER / Reporting Unnecessary Else
-*    When enabled, the compiler will issue an error or a warning when a statement is unnecessarily
-*    nested within an else clause (in situation where then clause is not completing normally).
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.unnecessaryElse"
+* COMPILER / Reporting Boxing/Unboxing Conversion
+*    When enabled, the compiler will issue an error or a warning whenever a boxing or an unboxing
+*    conversion is performed.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.autoboxing"
 *     - possible values:   { "error", "warning", "ignore" }
 *     - default:           "ignore"
 </pre>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42493">42493</a>
-Error message when evaluating: Expressionopt?
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32061">32061</a>
-No code assist in instance variable inner class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49904">49904</a>
-[DCR] Quick Assist : unneeded else
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60081">60081</a>
-[Compiler] java.lang.VerifyError: Illegal target of jump or branch
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52805">52805</a>
-[DCR] Compiler should warn when using if (test);
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58652">58652</a>
-ImageBuilderInternalException during auto build
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60108">60108</a>
-SearchMatch should implement toString() 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60078">60078</a>
-NPE in ASTConverter
-
-<a name="v_424"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M9 Build - 27th April 2004
-<br>Project org.eclipse.jdt.core v_424
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_424">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=54108">54108</a>
-Weird piece of source code in SourceTypeConverter.java
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51500">51500</a>
-[DOM AST] Quick fix "Add unimplemented methods" fails on static variable initialized using anonymous constructor
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59843">59843</a>
-Eclipse 3.0M8 generates ambiguous keys from ITypeBindings for nested classes with the same name
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59937">59937</a>
-Should not process saved state delta during startup 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58069">58069</a>
-Compilation ERROR: Missing code implementation in the compiler
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51911">51911</a>
-@see method w/out ()
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49025">49025</a>
-Util.bind(String, String[]) can be optimized a little bit
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59743">59743</a>
-[Compiler] Incorrect diagnosis of ambiguous method when inheriting
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57871">57871</a>
-Override Indicator: blocks editor from opening when error occurs in java compiler
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59421">59421</a>
-Bad error message from Eclipse Java Compiler when file is missing
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58946">58946</a>
-Standalone compiler help text is incorrect on Unix
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59084">59084</a>
-[content type] ensure content types/file associations are contributed by the right plugins
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59716">59716</a>
-Using 200404201300, one more blank line is inserted in front of import declarations when no package is defined
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59575">59575</a>
-invalid formatting
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51213">51213</a>
-Unable to resolve conflict between type and package name in binaries
-
-<a name="v_423"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M9 Build - 22nd April 2004
-<br>Project org.eclipse.jdt.core v_423
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_423">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=59363">59363</a>
-Should surface cancellation exceptions 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51075">51075</a>
-Compiler warning "is hiding a field" given for static inner class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38658">38658</a>
-Search for existing type fails
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59291">59291</a>
-Deadlock between AllTypes cache and setClasspathContainer
-
-
-<a name="v_422"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M9 Build - 20th April 2004
-<br>Project org.eclipse.jdt.core v_422
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_422">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Added API for User Library Container support in JavaCore:
+</li>	 
+<li> Renamed unsafe type operation optional problem into unchecked type operation, to better match notion of
+"unchecked" warning from JLS 3rd edition.
 <pre>
-
-/**
- * Name of the User Library Container id.
- */
-public static final String USER_LIBRARY_CONTAINER_ID= "org.eclipse.jdt.USER_LIBRARY"; //$NON-NLS-1$
-
-/**
- * Returns the names of all defined user libraries. The corresponding classpath container path
- * is the name appended to the USER_LIBRARY_CONTAINER_ID.  
- * @return Return an array containing the names of all known user defined.
- */
-public static String[] getUserLibraryNames();
-</pre>
-</li>
-<li>Added API to get classpath container comparison ID in ClasspathContainerInitializer:
-<pre>
-/**
- * Returns an object which identifies a container for comparison purpose. This allows
- * to eliminate redundant containers when accumulating classpath entries (e.g. 
- * runtime classpath computation). When requesting a container comparison ID, one
- * should ensure using its corresponding container initializer. Indeed, a random container
- * initializer cannot be held responsible for determining comparison IDs for arbitrary 
- * containers.
- * <p>
- * @param containerPath the path of the container which is being checked
- * @param project the project for which the container is to being checked
- * @return returns an Object identifying the container for comparison
- * @since 3.0
- */
-public Object getComparisonID(IPath containerPath, IJavaProject project);
-</pre>
-By default, containers are identical if they have same container path first segment
-but this may be refined by other container initializer implementations.
-<br>
-For example, the User Library classpath container initializer added for User Library Container API
-implementation (UserLibraryClasspathContainerInitializer) refines the comparison ID to the entire container path.
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52747">52747</a>
-formatter - please special case empty array init
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59000">59000</a>
-Code formatter struggles with end-of-line comments
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52679">52679</a>
-Code formatter formats braces in case and default statements, but no settings exist
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52940">52940</a>
-Formatter: Separate control of new lines in control statements by statement type
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47815">47815</a>
-Refactoring doesn't work with some project names [refactoring] 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37657">37657</a>
-[plan item] Improve code formatter
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50989">50989</a>
-Non-externalized strings wrap lines incorrectly
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57689">57689</a>
-ArrayIndexOutOfBoundsException when creating a new class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55004">55004</a>
-[DCR] IVariableBinding should have a method returning the constant value
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58606">58606</a>
-Inner class in child calling protected method in parent
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55979">55979</a>
-There are still deprecated formatter constants without new way
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57117">57117</a>
-Ant adapter preserves all deprecation when using compiler arg even if deprecation is set to off
-
-<a name="v_421"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M9 Build - 13th April 2004
-<br>Project org.eclipse.jdt.core v_421
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_421">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=57829">57829</a>
-Should optimize assert true case
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57294">57294</a>
-Ignore serialVersionUID hiding another field
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41395">41395</a>
-StackOverflowError when pasting code 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57414">57414</a>
-Summary: GB18030: Can not open Java Search dialog. 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57886">57886</a>
-Concurrency issue while initializing containers and variables 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57858">57858</a>
-[Compiler] Marking a field deprecated still report deprecated usage #46973
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57743">57743</a>
-[Compiler] invalid byte code produced when catching Throwable
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57235">57235</a>
-DCR: AST Name.getQualifiedName()
-
-<a name="v_420"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M9 Build - 6th April 2004
-<br>Project org.eclipse.jdt.core v_420
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_420">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Added inclusion patterns support. See <code>JavaCore.newSourceEntry(IPath,IPath[],IPath[],IPath)</code> 
-	 and <code>IClasspathEntry.getInclusionPatterns()</code> for details.</li>
-<li>Added API on WorkingCopyOwner to set the primary buffer provider (for internal use by the jdt-related plug-ins only).
-<pre>
-/**
- * Sets the buffer provider of the primary working copy owner. Note that even if the
- * buffer provider is a working copy owner, only its createBuffer(ICompilationUnit)
- * method is used by the primary working copy owner. It doesn't replace the internal primary 
- * working owner.
- * 
- * This method is for internal use by the jdt-related plug-ins.
- * Clients outside of the jdt should not reference this method.
- * 
- * @param primaryBufferProvider the primary buffer provider
- */
-public static void setPrimaryBufferProvider(WorkingCopyOwner primaryBufferProvider);
-</pre></li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54009">54009</a>
-jardesc should be known to Team/File Content
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51867">51867</a>
-An anonymous type is missing in type hierarchy when editor is modified 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54763">54763</a>
-[Compiler] Unnecessary cast not detected
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52347">52347</a>
-NPE in LaunchingPlugin.shutdown 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55992">55992</a>
-AssertionFailed during preference import
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29964">29964</a>
-Add inclusion filter 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55088">55088</a>
-IAE when using ICU.reconcile(GET_AST_TRUE, ...) 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=56462">56462</a>
-[formatter] java profile; array initializer before closing brace
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=56449">56449</a>
-Need to know if a reference match is in Javadoc or in Code 
-
-<a name="v_419"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M9 Build - 30th March 2004
-<br>Project org.eclipse.jdt.core v_419
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_419">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Replaced "name" property of ParameterizedType node (DOM/AST) 
-with "type" property. The old methods and fields (added earlier in 3.0 cycle)
-are deprecated and will be removed shortly.</li>
-<li>Added typeParameters property to ClassInstanceCreation node (DOM/AST).</li>
-<li>Package org.eclipse.jdt.core.internal.dom.rewrite renamed to org.eclipse.jdt.internal.core.dom.rewrite.</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=56316">56316</a>
-JavaProject exists should not populate 
-	  	
-<a name="v_418"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M8 Build - 25th March 2004 - 3.0 MILESTONE-8
-<br>Project org.eclipse.jdt.core v_418
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_418">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=55930">55930</a>
-File encoding should be used on save
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55478">55478</a>
-Unused import not reported in IDE
-	  	
-<a name="v_417"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M8 Build - 24th March 2004
-<br>Project org.eclipse.jdt.core v_417
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_417">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Removed failing tests re: encoding support.
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-
-<a name="v_416"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M8 Build - 23rd March 2004
-<br>Project org.eclipse.jdt.core v_416
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_416">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=55504">55504</a>
-@<tasktag> should not be reported
-
-<a name="v_415"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M8 Build - 23rd March 2004
-<br>Project org.eclipse.jdt.core v_415
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_415">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul> 
-<li> Added rewriting support to DOM AST.
-There are two set of API to perform rewriting.
-<ul> 
-<li>An AST-modifying rewrite API<br>
-To use the AST-modifying rewrite the client must create an AST from an existing
-compilation unit (ASTParser#createAST(...)).
-Then the client need to start the record process of the AST changes (CompilationUnit#recordModifications())
-and modify the AST after. When modifications are done, the client can call a method to
-compute a text edit tree containing all the text changes (CompilationUnit#rewrite()).
-
-<pre>
-CompilationUnit
-	public void recordModifications()
-	public TextEdit rewrite(IDocument document, Map options) throws RewriteException
-</pre>
-</li>
-<li>A describing rewrite API<br>
-To use the describing AST rewrite, the client starts with creating an instance of NewASTRewrite. Then the client
-must not modify the AST directly but use NewASTRewrite instead. When modifications are done, the client can call
-a method to compute a text edit tree containing all the text changes (NewASTRewrite#rewrite()).
-<pre>
-NewASTRewrite
-	public final void markAsRemoved(ASTNode node, TextEditGroup editGroup)
-	public final void markAsReplaced(ASTNode node, ASTNode replacingNode, TextEditGroup editGroup)
-	public ListRewriter getListRewrite(ASTNode parent, ChildListPropertyDescriptor childProperty)
-	public TextEdit rewriteAST(IDocument document, Map options) throws RewriteException
-	...
-	
-ListRewriter
-	remove(ASTNode, TextEditGroup)
-	public void replace(ASTNode, ASTNode, TextEditGroup)
-	public void insertAfter(ASTNode, ASTNode, TextEditGroup)
-	public void insertBefore(ASTNode, ASTNode, TextEditGroup)
-	public void insertFirst(ASTNode, TextEditGroup)
-	public void insertLast(ASTNode, TextEditGroup)
-	public void insertAt(ASTNode, int, TextEditGroup)
-	...
+* COMPILER / Reporting Unchecked Type Operation
+*    When enabled, the compiler will issue an error or a warning whenever an operation involves generic types, and potentially
+*    invalidates type safety since involving raw types (e.g. invoking #foo(X&lt;String&gt;) with arguments  (X)).
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "warning"
 </pre>
 </li>
 </ul>
-</li>
-</ul>
 
 <h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39068">39068</a>
-Adopt new core API for encoding on a per file basis
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81556">81556</a>
+[search] correct results are missing in java search
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81825">81825</a>
+[1.5][compiler] Internal compiler error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=71195">71195</a>
+[model] NullPointerException @ org.eclipse.jdt.internal.core.Buffer.removeBufferChangedListener
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79883">79883</a>
+[prefs] -pluginCustomization doesn't pick up compiler preferences
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81718">81718</a>
+[1.5] "Static import never used" warning disappears when variable of same name is declared
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81971">81971</a>
+[1.5][compiler] compiler allows use of void type as method arguments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=82053">82053</a>
+generic semantics have some problems
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=82088">82088</a>
+[search][javadoc] Method parameter types references not found in @see/@link tags
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79766">79766</a>
+[model] NPE in CancelableNameEnvironment
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81417">81417</a>
+[dom] getJavaElement() throws a NPE for WildcardBinding
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81724">81724</a>
+[1.5] NullPointerException in FieldBinding.canBeSeenBy when using static import
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80223">80223</a>
+[search] Declaration search doesn't consider visibility to determine overriding methods
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81084">81084</a>
+[1.5][search]Rename field fails on field based on parameterized type with member type parameter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80890">80890</a>
+[search] Strange search engine behaviour
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81376">81376</a>
+[search] Clarify effects of R_ERASURE_MATCH for searches other than TYPE
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81618">81618</a>
+[1.5][compiler] unsafe type operation warning
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78122">78122</a>
+[compiler] Detect and visually indicate auto-boxing in Jdk1.5 code
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78592">78592</a>
+[1.5][compiler] missing unchecked cast warning
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78591">78591</a>
+[1.5][compiler] missing unchecked cast warning
 
-<a name="v_414"></a>
+
+<a name="v_529"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0M8 Build - 22nd March 2004
-<br>Project org.eclipse.jdt.core v_414
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_414">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=46668">46668</a>
-Changes to class path containers should not change .project 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55421">55421</a>
-Cannot save a .java file in a non-java project anymore 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55223">55223</a>
-Bug in comment mapper: Same comment mapped to 2 statements
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54044">54044</a>
-Ant log does not use system newline character
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55372">55372</a>
-Should not assume that Preferences.defaultPropertyNames() returns default-default properties 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55221">55221</a>
-Bug in comment mapper: Grabs next node's Javadoc
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55102">55102</a>
-NPE when using ICU.reconcile(GET_AST_TRUE, ...) 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49986">49986</a>
-setRawClasspath(...) should fire a F_CLASSPATH_CHANGED delta 
-
-<a name="v_413"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M8 Build - 15th March 2004
-<br>Project org.eclipse.jdt.core v_413
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_413">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul> 
-<li> Added compiler option JavaCore.COMPILER_TASK_CASE_SENSITIVE to control whether the task detection
-should be case sensitive or not. By default, it is.
-<pre>
- * COMPILER / Determine whether task tags are case-sensitive
- *    When enabled, task tags are considered in a case-sensitive way.
- *     - option id:         "org.eclipse.jdt.core.compiler.taskCaseSensitive"
- *     - possible values:   { "enabled", "disabled" }
- *     - default:           "enabled"
-</pre>
-</li>
-<li> Added 2 default task tags: "FIXME" and "XXX".
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54776">54776</a>
-DefaultCommentMapper: different behaviour
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54431">54431</a>
-ASTParser should honor set compiler options in all cases
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54043">54043</a>
-Problems with type hierarchy for binary types
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53095">53095</a>
-I20040225: Won't accept breakpoint on NoClassDefFoundError
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54294">54294</a>
-No default for JavaCore.COMPILER_CODEGEN_INLINE_JSR_BYTECODE
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48435">48435</a>
-Java Search for OR-pattern finds too much in strange project setup
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40921">40921</a>
-Task tags should be case-insensitive
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49266">49266</a>
-FIXME task tag
-
-
-<a name="v_412"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M8 Build - 8th March 2004
-<br>Project org.eclipse.jdt.core v_412
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_412">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li> Added new global JavaCore.COMPILER_DOC_COMMENT_SUPPORT option for doc comment (Javadoc) support. By default, this option is enabled for backward compatibility.
-<pre>
- * COMPILER / Javadoc Comment Support
- *    When this support is disabled, the compiler will ignore all javadoc problems options settings
- *    and will not report any javadoc problem. It will also not find any reference in javadoc comment and
- *    DOM AST Javadoc node will be only a flat text instead of having structured tag elements.
- *     - option id:         "org.eclipse.jdt.core.compiler.doc.comment.support"
- *     - possible values:   { "enabled", "disabled" }
- *     - default:           "enabled"
-</pre>
-See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52264">52264</a>.
-</li>
-<li> Added new JavaCore.COMPILER_CODEGEN_INLINE_JSR_BYTECODE option to allow user to inline subroutine code instead of generating JSR instructions. By default, this option is disabled.
-<pre>
- * COMPILER / Inline JSR Bytecode Instruction
- *    When enabled, the compiler will no longer generate JSR instructions, but rather inline corresponding
- *    subroutine code sequences (mostly corresponding to try finally blocks). The generated code will thus
- *    get bigger, but will load faster on virtual machines since the verification process is then much simpler. 
- *    This mode is anticipating support for the Java Specification Request 202.
- *     - option id:         "org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode"
- *     - possible values:   { "enabled", "disabled" }
- *     - default:           "disabled"
- * 
-</pre>
-Corresponding command line compiler option <code>-noJSR</code> has been renamed to:
-<pre>
-    <code>-inlineJSR</code> : inline JSR bytecode
-</pre>
-which means that when specified, the compiler will no longer generate JSR bytecodes, but instead inlining the corresponding subroutine (e.g. finally block).
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53757">53757</a>
-Javadoc tag @transient  ignored
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=530757">53075</a>
-https://bugs.eclipse.org/bugs/show_bug.cgi?id=53075
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53357">53357</a>
-Java AST creation error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52264">52264</a>
-Need a global preference to enable Javadoc support
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51529">51529</a>
-"Organize imports" is confused by references inside Javadoc
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53477">53477</a>
-AnonymousClassDeclaration has wrong range
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53624">53624</a>
-StackOverFlow in Code assist 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50433">50433</a>
-Rationalize signatures of AST.parse* methods 
-
-<a name="v_411"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M8 Build - 3rd March 2004
-<br>Project org.eclipse.jdt.core v_411
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_411">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Added new constant <code>IJavaElementDelta.F_CLASSPATH_CHANGED</code> that indicates that
-	  the project's raw classpath has changed.
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49986">49986</a>
-setRawClasspath(...) should fire a F_CLASSPATH_CHANGED delta 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53242">53242</a>
-Consitent Out of Memory problems indexing (with multiple Java libraries)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52474">52474</a>
-UI Blocked when opening Java Perspective during CVS check out 
-
-<a name="v_410"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M8 Build - 2nd March 2004
-<br>Project org.eclipse.jdt.core v_410
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_410">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Added following APIs to <code>org.eclipse.jdt.core.dom.CompilationUnit</code>:
-<ul>
-<li><code>getCommentList()</code>: Returns a list of the comments encountered while parsing the compilation unit.</li>
-<li><code>getExtendedStartPosition(ASTNode)</code>: Returns the extended start position of the given node.</li>
-<li><code>getExtendedLength(ASTNode)</code>: Returns the extended source length of the given node.</li>
-</li>
-</ul>
-Unlike <code>ASTNode#getStartPosition()</code> and <code>ASTNode#getLength()</code>, the extended source range may include
-comments and whitespace immediately before or after the normal source range for the node.
-<br>
-See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53445">53445</a> for more details on heuristic to find leading and trailing comments.
-</li>
-<li>Added API <code>FieldReferenceMatch.isReadAccess()</code> and <code>isWriteAccess()</code>.
-<li>Added API <code>JavaCore.run(IWorkspaceRunnable action, ISchedulingRule rule, IProgressMonitor monitor)</code> 
-	 to control the scheduling rule during a Java batch operation.
-</li>
-<li>Added API <code>SearchEngine.createJavaSearchScope(IJavaElement[], int)</code> that allows to filter the
-     classpath entries added in the scope: SOURCES, APPLICATION_LIBRARIES, SYSTEM_LIBRARIES and REQUIRED_PROJECTS.
-</li>
-<li> New command line options for batch compiler:
-  <ul>
-  <li> <code>-maxProblems &lt;n&gt;</code> :  max number of problems per compilation unit (100 by default) </li>
-  <li> <code>-noJSR</code> : do not use JSR bytecode </li>
-  </ul>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53445">53445</a>
-[DCR] [DOM Comments] Provide extended ranges including leading/trailing comments for AST nodes
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53276">53276</a>
-[DOM Comments] Wrong text element length when containing '\' character
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52908">52908</a>
-[DOM Comments] Wrong text element positions when starting/ending with { or }
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48337">48337</a>
-[Search] FieldReferenceMatch should report read/write access 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52691">52691</a>
-Add batch compiler option for maxProblemsPerUnit
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51045">51045</a>
-Offer to call JavaCore.run with scheduling rule 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52273">52273</a>
-Add option on predefined search scope to include/exclude system contain libraries 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49809">49809</a>
-NPE from MethodVerifier 
-
-<a name="v_409"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M8 Build - 24th February 2004
-<br>Project org.eclipse.jdt.core v_409
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_409">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Added new API to create a DOM AST while reconciling 
-	 <code>ICompilationUnit.reconcile(boolean, boolean, WorkingCopyOwner, IProgressMonitor)</code>.
-</li>
-<li>Removed compiler support for deprecating jsr bytecode in 1.5 compliant mode (turned off until future release).
-</li>
-<li>The constant DefaultCodeFormatterConstants.FORMATTER_PRESERVE_USER_LINEBREAKS will be removed. It has been deprecated for now and
-has no effect in the UI anymore.
-</li>
-<li>The constant DefaultCodeFormatterConstants.FORMATTER_FILLING_SPACE will be removed. It has been deprecated for now and
-has no effect in the UI anymore.
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52916">52916</a>
-Strang error message when using jre1.5.0 libraries
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50586">50586</a>
-[Code Formatter] trim trailing blanks/whitespace
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52851">52851</a>
-Space before else should be removed in some cases
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52283">52283</a>
-do <single-statement> while(<condition>) is ill-formatted
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52479">52479</a>
-Code Format fails on not on-demand imports
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52246">52246</a>
-M7 Source formatter fails silently when assert present in source
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52429">52429</a>
-code formatter seems to ignore settings
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51623">51623</a>
-[formatter] Wrong formatting when "Preserve existing line breaks" switched on
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52305">52305</a>
-Code Formatter strips blank lines in methods and field definitions when I try to tell it not to
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52746">52746</a>
-Formatter - preserve line breaks conflicts with keep blank lines
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52804">52804</a>
-Deprecated formatter constant should indicate new way
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52619">52619</a>
-NPE running Java model tests
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36889">36889</a>
-[DCR] Keep AST created in reconcile for active editor 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52384">52384</a>
-OutOfMemoryError opening hierarchy on Object 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52355">52355</a>
-Not present exception trying to create a class in excluded package
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49809">49809</a>
-NPE from MethodVerifier
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22104">22104</a>
-[infrastructure] NPE from IndexSummary.read(...)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31013">31013</a>
- [infrastructure] npe in index crash recovery
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31014">31014</a>
-[infrastructure] exception in indexer
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51447">51447</a>
-[infrastructure] NPE running JDT Core tests
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52221">52221</a>
-[Compiler] should reject Local type usage when defined in other switch case block
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52216">52216</a>
-[regression in M7] javadoc: @see <a href> shows a warning
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51990">51990</a>
-'parameter' vs 'argument' in compiler errors/settings
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52012">52012</a>
-Special 'serialPersistentFields' marked as 'never used locally'
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51353">51353</a>
-The type AbstractStringBuilder is not visible
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49259">49259</a>
-Task tags starting with TODO don't correctly display their priority in Tasks View
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49879">49879</a>
-java.lang.ClassCastException (SourceTypeBinding to a BinaryTypeBinding) in 30M6 within jdt.core.dom.TypeBinding.getKey(TypeBinding.java:411)
-
-<a name="v_408"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M7 Build - 12th February 2004 - 3.0 MILESTONE-7
-<br>Project org.eclipse.jdt.core v_408
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_408">cvs</a>).
+Eclipse SDK 3.1M4 - 16th December 2004 - 3.1 MILESTONE 4
+<br>Project org.eclipse.jdt.core v_529
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_529">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=51603">51603</a>
-[preferences] Code formatter line wrapping preference inconsistent preview behaviour
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51476">51476</a>
-Javadoc: String or URL @see references are not stored in DOM AST Javadoc structure
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51478">51478</a>
-Javadoc: @deprecated/@inheritDoc tags are not stored in DOM AST Javadoc structure
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51508">51508</a>
-Javadoc: Package references DOM AST nodes binding is null
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51626">51626</a>
-Javadoc - DOM/AST is not correct after a @see tag
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51650">51650</a>
-Incorrected deprecation check
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51770">51770</a>
-Javadoc AST Node: wrong binding on qualified name part
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81258">81258</a>
+IMethodBinding#getJavaElement() is null with inferred method parameterization
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80765">80765</a>
+[1.5][generics] Invalid class files generated, compiler strange behaviour 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81317">81317</a>
+ClasspathTests.java and GenericTypeTest.java could not be read (illegal characters)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81262">81262</a>
+[Java 5] Verification error when creating anonymous enum subtypes
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80964">80964</a>
+[1.5] Annotations with RetentionPolicy.RUNTIME are lost after a rebuild
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80028">80028</a>
+Ambiguous method error where javac succeeds
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80739">80739</a>
+[1.5] Two methods ends up with the same signatures
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81134">81134</a>
+[dom] [5.0] NPE when creating AST
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81023">81023</a>
+[1.5] Wrong position for class instance creation with type parameters
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=81141">81141</a>
+CCE in ProblemBinding when using annotations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80544">80544</a>
+[1.5][annot]error on @Override of abstract methods
 
 
-<a name="v_407"></a>
+<a name="v_528"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0M7 Build - 11th February 2004
-<br>Project org.eclipse.jdt.core v_407
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_407">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Fixed most of the API Java doc comments. 
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51659">51659</a>
-New Code Formatter: minor problem with "White spaces/Array Initializers" option
-
-
-<a name="v_406"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M7 Build - 10th February 2004
-<br>Project org.eclipse.jdt.core v_406
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_406">cvs</a>).
+Eclipse SDK 3.1M4 - 14th December 2004
+<br>Project org.eclipse.jdt.core v_528
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_528">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=51035">51035</a>
-[Formatter] endline comment in case of simple if-then statement
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80957">80957</a>
+NPE using code assist for unresolved type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80960">80960</a>
+[dom] NPE in ASTConverter#convert(...)
 
-
-<a name="v_405"></a>
+<a name="v_527"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0M7 Build - 9th February 2004
-<br>Project org.eclipse.jdt.core v_405
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_405">cvs</a>).
+Eclipse SDK 3.1M4 - 14th December 2004
+<br>Project org.eclipse.jdt.core v_527
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_527">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=51363">51363</a>
-Wrong comment positions inside the Scanner.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51201">51201</a>
-Code formatter missing 'between empty brackets' option in Whitespace Array allocation configuration
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50695">50695</a>
-Javadoc: package reference in @see tags is wrongly warned
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49994">49994</a>
-Strange matches with start=0, end=1 in type reference search
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51300">51300</a>
-VerifyError when using a array reference assigned to null
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51128">51128</a>
-[Code Formatter] Indent statements within blocks and methods
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51241">51241</a>
-IllegalArgumentException while creating a DOM/AST
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51249">51249</a>
-Performance problems in PackageFragment.getPath 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50276">50276</a>
-Function call line wrapping fails on chained calls
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51190">51190</a>
-comment after else block goes to next line
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51226">51226</a>
-Javadoc inside DOM AST does not support starting characters in unicode
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51104">51104</a>
-Comments are not recorded when inside a method body
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50858">50858</a>
-Javadoc IProblem constant not defined
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50898">50898</a>
-Javadoc AST: Missing binding for reference to non-visible type
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80918">80918</a>
+[1.5][search] ClassCastException when searching for references to binary type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80914">80914</a>
+[1.5][search] SearchPattern R_EQUIVALENT_MATCH matchRule does not work properly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80910">80910</a>
+[javadoc] Invalid missing reference warning on @see or @link tags
 
-<a name="v_404"></a>
+<a name="v_526"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0M7 Build - 3rd February 2004
-<br>Project org.eclipse.jdt.core v_404
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_404">cvs</a>).
+Eclipse SDK 3.1M4 - 13th December 2004
+<br>Project org.eclipse.jdt.core v_526
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_526">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=50938">50938</a>
-Javadoc AST: Still invalid range for embedded tag
-
-<a name="v_403"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M7 Build - 3rd February 2004
-<br>Project org.eclipse.jdt.core v_403
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_403">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Updated porting guide to introduce search participant story (see <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.jdt.core/notes/porting_guide.html">porting guide</a>)</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51089">51089</a>
-Java AST creation failure 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50571">50571</a>
-search sender in hierarchy hangs 
-
-<a name="v_402"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M7 Build - 30th January 2004
-<br>Project org.eclipse.jdt.core v_402
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_402">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=50883">50883</a>
-Javadoc AST node: Range problem with embedded tags
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50884">50884</a>
-Compiler crashes without a trace in the log leaving workspace in unhappy state
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50831">50831</a>
-DCR Javadoc AST: Offer well known tag names as constants 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50880">50880</a>
-JavadocAST Nodes: Wrong ranges on link
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50877">50877</a>
-Javadoc AST Nodes: Wrong ranges
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47396">47396</a>
-JAVA AST Creation failure
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50844">50844</a>
-AbortCompilation thrown from Name#resolveBinding() 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50746">50746</a>
-Searching for variable references can cause an internal error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50838">50838</a>
-Javadoc bindings: No bindings in constructor ref parameter
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50840">50840</a>
-Javadoc AST: wrong start position on MemberRef
-
-<a name="v_401"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M7 Build - 29th January 2004
-<br>Project org.eclipse.jdt.core v_401
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_401">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=46126">46126</a>
-[DCR] IBinding should have a method to check @since javadoc tag
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50785">50785</a>
-Javadoc bindings: No bindings member refs
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50784">50784</a>
-Javadoc bindings: No binding in {@link } and link disturbs other bindings
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50781">50781</a>
-Javadoc bindings: No bindings for qualified names
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50736">50736</a>
-Out of bounds exception while formatting
-
-<a name="v_400"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M7 Build - 28th January 2004
-<br>Project org.eclipse.jdt.core v_400
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_400">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=50694">50694</a>
-Javadoc: Cannot find DOM AST bindings for types in @see tags
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50692">50692</a>
-Javadoc: Cannot find DOM AST bindings for inline link tags references
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50719">50719</a>
-wrong formatting for java coding conventions
-
-<a name="v_399"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M7 Build - 27th January 2004
-<br>Project org.eclipse.jdt.core v_399
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_399">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Improve DOM/AST support for doc comments.
-<br>Following changes have been made to the DOM/AST API:
-<ul>
-<li>added Javadoc.tags() to represent structure of the doc comments</li>
-<li>deprecated Javadoc.get/setComment</li>
-<li>added 5 new node types that occur only within doc comments: TagElement, TextElement, MemberRef, MethodRef, MethodRefParameter</li>
-<li>tag elements like MemberRef, MethodRef, and Name can carry binding information (must be requested like elsewhere)</li>
-<li>added ASTVisitor(boolean) for controlling whether Javadoc.tags() are visited by default</li>
-<li>added ASTMatcher(boolean) for controlling whether Javadoc.tags() are compared vs. only Javadoc.getComment()</li>
-<li>AST.parse*(...) now returns structured doc comments (for compatibility, Javadoc.getComment() is also set as before)</li>
-</ul>
-See bugs <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50683">50683</a>.
+<li>
+Initial support for search on annotations has been implemented. Declarations or references to annotation types are now found by search engine.<br>
+However, it is not currently able to find annotation member (fields or methods). This should be done for next milestone.
 </li>
 <li>
-Improve DOM/AST support for locating all comments.
-<br>Following changes have been made to the DOM/AST API:
-<ul>
-<li>added CompilationUnit.getCommentTable() to record locations of all comments found in the source</li>
-<li>added 2 new node types, LineComment and BlockComment, to represent end-of-line and traditional comments respectively</li>
-<li>these new nodes are placeholders for comments</li>
-<li>these new node types only occur in the comment table (since they can occur anywhere (lexically), there is no way to properly parent them in the regular AST nodes that reflects their position)</li>
-<li>AST.parse*(...) now returns sets the comment table on the compilation unit to include all comments (including attached and free-floating doc comments)</li>
-</ul>
-See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50697">50697</a>.
-</li>
-<li> Added option to control whether diagnosis for unused thrown exceptions should be enabled when overriding another
-method. By default, it is disabled.
-<pre>
-* COMPILER / Reporting Unused Declared Thrown Exception in Overridind Method
-*    When disabled, the compiler will not include overriding methods in its diagnosis for unused declared
-*    thrown exceptions.
-*    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException".
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding"
-*     - possible values:   { "enabled", "disabled" }
-*     - default:           "disabled"
-</pre>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50644">50644</a>
-Deprecation check doesn't check that the @deprecated is at the beginning of the line
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27134">27134</a>
-Add a ASTNode for non-Javadoc comments
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50683">50683</a>
-Improve DOM/AST support for doc comments
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50697">50697</a>
-Improve DOM/AST support for locating all comments
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50667">50667</a>
-Deadlock on Refactor -> Extract method
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47430">47430</a>
-the immutable bit is copied from the original resource to the ouput directory
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50601">50601</a>
-Blank lines before package declaration is one fewer than specified
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48292">48292</a>
-[DCR] Need AST.parsePartialClassFile(....)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50320">50320</a>
-Java model operations should use IResourceRuleFactory 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50207">50207</a>
-Compile errors fixed by 'refresh' do not reset problem list or package explorer error states 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49691">49691</a>
-JavaProject looses property listeners on preferences
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50265">50265</a>
-Emulate old formatter with the new formatter
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50225">50225</a>
-Calling the default formatter with an empty string returns an invalid Edit 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44876">44876</a>
-"Unnecessary declaration of thrown exception" problems
-
-
-<a name="v_398"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M7 Build - 20th January 2004
-<br>Project org.eclipse.jdt.core v_398
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_398">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Major renaming of constants in the code formatter. See <code>org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants</code>. See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49908">49908</a>.
-The old constants have been deprecated and will be removed before M7. So we encourage you to save your code formatter preferences if
-you modified the default settings. The UI will provide an automatic conversion to the new options.
-</li>
-<li>Added API for alignment options in the code formatter.  See <code>org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants</code>. See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49968">49968</a>.
-</li>
-<li>Changed 3.0 APIs on <code>org.eclipse.jdt.core.dom.AST</code> to take an <code>IProgressMonitor</code>. This progress monitor is checked for the cancelation of the AST creation only.
-</li>
-<li>Added API on <code>org.eclipse.jdt.core.dom.AST</code> to parse an expression or statements or class body declarations without requiring the parsing
-of the whole compilation unit. This is still subject to change before 3.0.
+SearchPattern now accept two new flags for match rule: R_ERASURE_MATCH and R_EQUIVALENT_MATCH (see bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79790">79790</a>).<br>
 <pre>
 	/**
-	 * Parses the given source between the bounds specified by the given offset (inclusive)
-	 * and the given length and creates and returns a corresponding abstract syntax tree.
-	 * 
-	 * The root node of the new AST depends on the given kind.
-	 * - <code>org.eclipse.jdt.core.dom.AST.K_CLASS_BODY_DECLARATIONS</code>: The root node is an instance of
-	 * <code>org.eclipse.jdt.core.dom.TypeDeclaration</code>. The type declaration itself doesn't contain any information.
-	 * It is simply used to return all class body declarations inside the bodyDeclaratins() collection.
-	 * - <code>org.eclipse.jdt.core.dom.AST.K_STATEMENTS</code>: The root node is an instance of
-	 * <code>org.eclipse.jdt.core.dom.Block</code>. The block itself doesn't contain any information.
-	 * It is simply used to return all the statements.
-	 * - <code>org.eclipse.jdt.core.dom.AST.K_EXPRESSION</code>: The root node is an instance of a subclass of
-	 * <code>org.eclipse.jdt.core.dom.Expression</code>.
-	 *  
-	 * Each node in the subtree carries source range(s) information relating back
-	 * to positions in the given source (the given source itself
-	 * is not remembered with the AST). 
-	 * The source range usually begins at the first character of the first token 
-	 * corresponding to the node; leading whitespace and comments are <b>not</b>
-	 * included. The source range usually extends through the last character of
-	 * the last token corresponding to the node; trailing whitespace and
-	 * comments are <b>not</b> included. There are a handful of exceptions
-	 * (including compilation units and the various body declarations); the
-	 * specification for these node type spells out the details.
-	 * Source ranges nest properly: the source range for a child is always
-	 * within the source range of its parent, and the source ranges of sibling
-	 * nodes never overlap.
-	 * 
-	 * This method does not compute binding information; all <code>resolveBinding</code>
-	 * methods applied to nodes of the resulting AST return <code>null</code>.
-	 * 
-	 * <code>null</code> is returned:
-	 * 1. If a syntax error is detected while parsing,
-	 * 2. If the given source doesn't correspond to the given kind.
-	 *  
-	 * @param kind the given kind to parse
-	 * @param source the string to be parsed
-	 * @param offset the given offset
-	 * @param length the given length
-	 * @param options the given options. If null, <code>JavaCore.getOptions()</code> is used.
-	 * @param monitor the progress monitor used to check if the AST creation needs to be canceled
-	 * 
-	 * @return ASTNode
-	 * @see ASTNode#getStartPosition()
-	 * @see ASTNode#getLength()
-	 * @see AST#K_CLASS_BODY_DECLARATIONS
-	 * @see AST#K_EXPRESSION
-	 * @see AST#K_STATEMENTS
-	 * @see JavaCore#getOptions()
-	 * @since 3.0
+	 * Match rule: The search pattern matches search results as raw types or parameterized types with same erasure.
+	 * Example:
+	 *	- pattern: List&lt;Exception&gt;
+	 *	- match: List&lt;Object&gt;
+	 * Can be combined to all other match rules, e.g. {@link #R_CASE_SENSITIVE} | {@link #R_ERASURE_MATCH}
+	 * This rule is not activated by default, so raw types or parameterized types with same erasure will not be found
+	 * for pattern List&lt;String&gt;,
+	 * Note that with this pattern, the match selection will be only on the erasure even for parameterized types.
+	 * @since 3.1
 	 */
-	public static ASTNode parse(int kind, char[] source, int offset, int length, Map options, IProgressMonitor monitor);
-</pre>
-</li>
-<li>Added API on <code>org.eclipse.jdt.core.dom.AST</code> to parse a compilation unit and specify
-the set of options to use. This is still subject to change before 3.0. The previous API was directly
-using <code>JavaCore.getOptions()</code>. This could be problematic in case you want to parse assert
-statements.
-<pre>
+	public static final int R_ERASURE_MATCH = 16;
 	/**
-	 * Parses the given string as a Java compilation unit and creates and 
-	 * returns a corresponding abstract syntax tree.
-	 * 
-	 * The given options are used to find out the compiler options to use while parsing.
-	 * This could implies the settings for the assertion support. See the <code>JavaCore.getOptions()</code>
-	 * methods for further details.
-	 * 
-	 * 
-	 * The returned compilation unit node is the root node of a new AST.
-	 * Each node in the subtree carries source range(s) information relating back
-	 * to positions in the given source string (the given source string itself
-	 * is not remembered with the AST). 
-	 * The source range usually begins at the first character of the first token 
-	 * corresponding to the node; leading whitespace and comments are <b>not</b>
-	 * included. The source range usually extends through the last character of
-	 * the last token corresponding to the node; trailing whitespace and
-	 * comments are <b>not</b> included. There are a handful of exceptions
-	 * (including compilation units and the various body declarations); the
-	 * specification for these node type spells out the details.
-	 * Source ranges nest properly: the source range for a child is always
-	 * within the source range of its parent, and the source ranges of sibling
-	 * nodes never overlap.
-	 * If a syntax error is detected while parsing, the relevant node(s) of the
-	 * tree will be flagged as <code>MALFORMED</code>.
-	 * 
-	 * 
-	 * This method does not compute binding information; all <code>resolveBinding</code>
-	 * methods applied to nodes of the resulting AST return <code>null</code>.
-	 * 
-	 * 
-	 * @param source the string to be parsed as a Java compilation unit
-	 * @param options options to use while parsing the file. If null, <code>JavaCore.getOptions()</code> is used.
-	 * @param monitor the progress monitor used to check if the AST creation needs to be canceled
-	 * @return CompilationUnit
-	 * @see ASTNode#getFlags()
-	 * @see ASTNode#MALFORMED
-	 * @see ASTNode#getStartPosition()
-	 * @see ASTNode#getLength()
-	 * @see JavaCore#getOptions()
-	 * @since 3.0
+	 * Match rule: The search pattern matches search results as raw types or parameterized types with equivalent type parameters.
+	 * Example:
+	 *	- pattern: List&lt;Exception&gt;
+	 *	- match:
+	 * 		+ List&lt;? extends Throwable&gt;
+	 * 		+ List&lt;? super RuntimeException&gt;
+	 * 		+ List&lt;?&gt;
+	 * Can be combined to all other match rules, e.g. {@link #R_CASE_SENSITIVE} | {@link #R_EQUIVALENT_MATCH}
+	 * This rule is not activated by default, so raw types or equivalent parameterized types will not be found
+	 * for pattern List&lt;String&gt;,
+	 * This mode is overridden by {@link  #R_ERASURE_MATCH} as erasure matches obviously include equivalent ones.
+	 * That means that pattern with rule set to {@link #R_EQUIVALENT_MATCH} | {@link  #R_ERASURE_MATCH}
+	 * will return same results than rule only set with {@link  #R_ERASURE_MATCH}.
+	 * @since 3.1
 	 */
-	public static CompilationUnit parseCompilationUnit(char[] source, Map options, IProgressMonitor monitor);
+	public static final int R_EQUIVALENT_MATCH = 32;
+</pre>
+Added new API method to make this flag settable even while creating pattern using a IJavaElement:
+<ul>
+<li><code>SearchPattern#createPattern(IJavaElement element, int limitTo, int matchRule)</code></li>
+</ul>
+</li>
+<li>
+SearchMatch now has a rule field which shows the rule used while reporting the match (initial implementation for bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79866">79866</a>).<br>
+Added new API methods to access this field:
+<ul>
+<li><code>SearchMatch#getRule()</code><br></li>
+<li><code>SearchMatch#setRule(int)</code></li>
+</ul>
+</li>
+<li>Added API IType#getFullyQualifiedParameterizedName() that shows the type parameter/arguments if the type is generic/parameterized.</li>
+<li>Added support in Java model for annotation types and annotations.</li>
+<li>Support for indexing annotation types 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 compiler support for autoboxing </li>
+<li>Code Assist now works for annotations. When performing a completion inside an annotation name,
+ proposals are possibles types and annotations types are more relevant than other types</li>
+<li>Code Select now works for annotations and annotation methods in correct code.</li>
+<li>Recovery now works for annotation type declaration and annotation method declaration</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80338">80338</a>
+getReturnType() throws a NullArgumentException
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80788">80788</a>
+Interface and annotation member types are implicitiely static
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80780">80780</a>
+IncompatibleClassChangeError for Annotations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80714">80714</a>
+Strange syntax diagnosis with incorrect annotations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80699">80699</a>
+Code Select does not work for annotations inside class file
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79790">79790</a>
+[1.5][search] Need to distinguish between raw and restricted search in the case of instantiated types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80672">80672</a>
+[1.5] Annotation change does not trigger recompilation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80466">80466</a>
+ITypeBinding#getJavaElement() is null for declaration of java.util.List&lt;E&gt;
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80083">80083</a>
+VerifyError on String-Operator += when using generics
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77430">77430</a>
+[1.5] case statements with enum values not correctly supported
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80597">80597</a>
+[compiler] NPE while reporting array empty dimensions problem
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80126">80126</a>
+[assist] CompletionRequestor.setIgnored should allow POTENTIAL_METHOD_DECLARATION
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80602">80602</a>
+Javadoc of ASTNode#getStartPosition() contains dangling reference to ASTParser 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80455">80455</a>
+[5.0] ITypeBinding.canAssign not aware of type boxing
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80579">80579</a>
+NPE is ITypeBinding.isCastCompatible
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80328">80328</a>
+[annotation] annotation problem type should implements java,lang.annotation.Annotation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79953">79953</a>
+AST Creation Error while editing Java file
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78849">78849</a>
+[1.5][compiler] Java 1.5 Boxing and Character?
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79641">79641</a>
+boolean autoboxing does not work with Object varargs
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80384">80384</a>
+Cannot decode package signature from CompletionProposal
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79254">79254</a>
+autoboxing does not work in combination with downcasting
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80045">80045</a>
+NPE in MethodBinding.signature
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80378">80378</a>
+Javadoc of CompletionProposal#getFlags() needs polish
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80208">80208</a>
+[1.5][compiler] NPE trying to resolve single static import
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79803">79803</a>
+[1.5][search] Search for references to type A reports match for type variable A
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79860">79860</a>
+[1.5][search] Search doesn't find type reference in type parameter bound
+
+<a name="v_525"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M4 - 7th December 2004
+<br>Project org.eclipse.jdt.core v_525
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_525">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Compiler now checks annotation location according to @Target meta-annotation</li>
+<li> Compiler now checks method overriding according to @Override annotation</li>
+<!--
+<li> Added compiler support to flag inconsistent null checks (using interprocedural flow analysis)
+<pre>
+* COMPILER / Reporting Inconsistent null Checks
+*    When enabled, the compiler will issue an error or a warning whenever assumption were made on a variable
+*    with respect to holding null/non-null values, but the assumption is not followed in a consistent manner.
+*    Situations include:
+*         - if variable was assumed to be null and further used to access field or methods
+*         - if variable was assumed to be null or non-null and further tested for null cases.
+*         
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.inconsistentNullCheck"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "warning"
+</pre>
+</li>
+-->
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79891">79891</a>
+[GENERICS] Array of Inner Class creation works on eclipse, but fails to compile with sun jdk
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79809">79809</a>
+[1.5][dom][javadoc] Need better support for type parameter Javadoc tags
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79904">79904</a>
+[1.5][dom][javadoc] TagElement range not complete for type parameter tags
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80144">80144</a>
+[1.5] Mutually-recursive type bounds interfere with inheritance of generic type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76751">76751</a>
+[1.5][annot] Can't use annotation classes as argument to generic methods
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80014">80014</a>
+@Retention(RetentionPolicy.RUNTIME) is ignored for annotations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80114">80114</a>
+[1.5][Regression] Annotation type cannot have constructors
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80021">80021</a>
+[1.5] CCE in VariableBinding.getJavaElement()
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80041">80041</a>
+IVariableBinding#isEqualTo(..) doesn't tell parameters from different methods apart
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77463">77463</a>
+[1.5][annot] Wrong error marker text for type annotation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79967">79967</a>
+NPE in WildcardBinding.signature with Mark Occurrences in Collections.class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79974">79974</a>
+[1.5] Wrong javadoc for TypeDeclarationStatement 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79795">79795</a>
+Code formatter doesn't handle enums well.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79673">79673</a>
+[1.5] Wrong method binding
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79797">79797</a>
+[1.5] Inconsistent classfile - moving code around
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79847">79847</a>
+[1.5][annot] Array type cannot have two or more dimensions
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79844">79844</a>
+[1.5][annot] when int value can be contained in a short, the cast is not required
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79848">79848</a>
+[1.5][annot] Array of java.lang.Class is a legal value for the type of an annotation type member declaration
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79779">79779</a>
+Code Formatter fails with static imports
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79668">79668</a>
+[1.5][annot] implicit wrapping in array type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78915">78915</a>
+[1.5][compiler] enum cannot be explicitly abstract
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78916">78916</a>
+[1.5][compiler] abstract methods in an enum declaration must be implemented for each constant
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79690">79690</a>
+Find declaring node doesn't work for type variables
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79775">79775</a>
+[dom]ClassCastException inside ASTConverter when opening a java file
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79752">79752</a>
+Need access to type binding of anonymous enumerations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79772">79772</a>
+Internal compiler error with I20041123/24/30
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79136">79136</a>
+API clarification for *Binding#getErasure(): why not a "general back-link"?
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76318">76318</a>
+[tests] Cannot run ASTModelBridgeTests if workspace path segment count is 1
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78914">78914</a>
+[1.5][compiler] super() cannot be called in the constructor of an enum declaration
+
+<a name="v_524"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M4 - 30th November 2004
+<br>Project org.eclipse.jdt.core v_524
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_524">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Support for generic types search has been added to SearchEngine (see bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75641">75641</a>).<br>
+User can now search for declaration and/or references to generic types or parameterized types (like <code>public class List&lt;T&gt; {}</code> or <code>List&lt;String&gt;</code> for example).
+This search can of course be done either selecting a JavaElement (see following point) or using Java Search dialog.
+</li>
+<li>Support for generic types and generic methods selection has been added inside CodeSelect.
+When the result is a parameterized type reference, the returned JavaElement is a 
+<code>ParameterizedSourceType</code> or <code>ParameterizedBinaryType</code>.
+When the result is a parameterized method invocation, the returned JavaElement is a 
+<code>ParameterizedSourceMethod</code> or <code>ParameterizedBinaryMethod</code>.
+When the result is a field access to a generic type's field, the returned JavaElement is a 
+<code>ParameterizedSourceField</code> or <code>ParameterizedBinaryField</code>.
+</li>
+<li>The internal Java model cache now adapts to the number of elements in the workspace. For example if a project
+      has 1000 package fragment roots, the space limit of the cache of roots will increase to 1000. This size is reset to
+      its default when the project is closed.
+</li>
+<li>Added the following compatibility rules APIs:
+     <ul>
+     <li><code>ITypeBinding#isAssignmentCompatible(ITypeBinding)</code></li>
+     <li><code>ITypeBinding#isCastCompatible(ITypeBinding)</code></li>
+     <li><code>ITypeBinding#isSubTypeCompatible(ITypeBinding)</code></li>
+     <li><code>IMethodBinding#overrides(IMethodBinding)</code></li>
+     </ul>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79349">79349</a>
+[1.5] Annotation with default value
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79756">79756</a>
+Erroneous compile error "The local variable may not have been initialized"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79635">79635</a>
+NPE when asking an IMethodBinding whether it overrides itself
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79667">79667</a>
+[1.5][annot] value in member pair value must be a constant expression
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79666">79666</a>
+[1.5][annot] Default value of annotation type member declaration must be assignment compatible with return type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79663">79663</a>
+[1.5][annot] Modifiers for field declaration must be public  in an annotation type declaration
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79665">79665</a>
+[1.5][annot] Field declarations inside annotation type declaration must be constant
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79512">79512</a>
+[1.5] Extract Method must not generate return type with type variable [refactoring][1.5]
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79609">79609</a>
+ITypeBinding#isEqualTo(..) thinks independent method type parameters are equal
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79610">79610</a>
+IVariableBinding#getJavaElement() returns null for local variables
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75641">75641</a>
+[1.5][search] Types search does not work with generics
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79612">79612</a>
+ClassCastException on referenceTypeBinding.isEqualTo(primitiveTypeBinding)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79545">79545</a>
+Eclipse vs Sun JDK: different class files from the same source code
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78293">78293</a>
+[1.5][compiler] Should flag implementing twice generic interface with different arguments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79544">79544</a>
+ITypeBinding#isEqualTo(..) does not compare type arguments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79570">79570</a>
+[1.5][DOM] v4 type binding should not be parameterized
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78087">78087</a>
+[dom] TypeBinding#getJavaElement() throws IllegalArgumentException for parameterized or raw reference to binary type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78183">78183</a>
+TypeBinding#getQualifiedName() does not honor Javadocs
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79109">79109</a>
+[1.5][DOM] AnnotationTypeMemberDeclaration.resolveBinding() might return a IMethodBinding
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79395">79395</a>
+IllegalArgumentException in CompilationUnitResolver.parse (line 323)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77283">77283</a>
+Incremental and full builds produce different problem markers for same duplicate type error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79263">79263</a>
+ClassCastException in SourceElementParser
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79460">79460</a>
+IMethodBinding of non-generic method says isRawMethod()==true
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79390">79390</a>
+[1.5][compiler] ClassCastException creating a generic local class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77806">77806</a>
+[1.5][dom] SimpleType AST node of List in List&lt;String&gt; has no type binding
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79362">79362</a>
+IllegalArgumentException during "Java AST creation"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75785">75785</a>
+Missing binding on non-visible type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79163">79163</a>
+[compiler] Dependency on indirectly referenced types not correctly computed
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77272">77272</a>
+[builder] Delta compilation fails to notice errors when removing an interface
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79271">79271</a>
+ITypeBinding#isEqualTo(..) returns true when comparing ArrayList&lt;Integer&gt; to its erasure
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77388">77388</a>
+[compiler] Reference to constructor includes space after closing parenthesis
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78931">78931</a>
+[select] cannot select qualified type name without the qualified package name
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79267">79267</a>
+[search] Refactoring of static generic member fails partially
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72258">72258</a>
+[model] Should be able to dynamicaly set the size of Java model cache
+
+<a name="v_523"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M4 - 23rd November 2004
+<br>Project org.eclipse.jdt.core v_523
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_523">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Compiler is now able to parse 1.5 syntax in Javadoc comments (see bugs <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70891">70891</a>
+and <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70892">70892</a>).<br>
+Note: these changes only apply to <a href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/javadoc.html#@param">@param</a> and
+<a href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/javadoc.html#{@value}">{@value}</a> tags.
+</li>
+<li>Batch AST creation API was finalized. See <code>ASTParser#createASTs(ICompilationUnit[],String[],ASTRequestor,IProgressMonitor)</code>
+     and <code>ASTRequestor</code>.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79110">79110</a>
+[1.5] Missing attribute for local and anonymous classes
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78057">78057</a>
+[dom] Can IBinding#getKey() return null?
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78757">78757</a>
+MethodBinding.getJavaElement() returns null
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78930">78930</a>
+ITypeBinding#getJavaElement() throws NPE for type variable
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73675">73675</a>
+[dom] Need AST creation pipeline
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73971">73971</a>
+[1.5] Ambiguous method error with overloaded parameterized methods
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78581">78581</a>
+[search] NPE while searching
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79108">79108</a>
+[1.5][DOM] enumConstantDeclaration.resolveBinding() always returns null
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77645">77645</a>
+[1.5][dom] navigate from local var binding to declaring method binding
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79098">79098</a>
+[dom] [1.5] EnhancedForStatement#resolveBinding() is superfluous
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77562">77562</a>
+[1.5] overriding methods with more specific generic return types causes compile errors
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=79091">79091</a>
+[compiler] Should report invalid type only on the name
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77093">77093</a>
+[search] No references found to method with member type argument
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77184">77184</a>
+[1.5][select] Code select does not select enum declarations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78801">78801</a>
+[assist] NPE attempting to code assist for parameters
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78128">78128</a>
+Error deleting project with jar file referenced by other project
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78275">78275</a>
+[recovery] NPE in GoToNextPreviousMemberAction with syntax error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70891">70891</a>
+[1.5][javadoc] Compiler should accept new 1.5 syntax for @param
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78858">78858</a>
+[1.5] Internal compiler error: java.lang.NullPointerException at ParameterizedTypeBinding.getMethods
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78905">78905</a>
+[1.5][compiler] Wrong hex decimal floating point literal is not rejected
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77630">77630</a>
+[compiler] no error when importing package inside static import
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78075">78075</a>
+normal and static import of the same class doesn't work correctly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78056">78056</a>
+[1.5] static import of a static member of a non static member type must be allowed
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77955">77955</a>
+[1.5] member classes of super class are not allowed inside static import
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78082">78082</a>
+[1.5][search] FieldReferenceMatch in static import should not include qualifier
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78714">78714</a>
+"Convert local to field" should know about prefixes
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75814">75814</a>
+Inconsistent results when adding a breakpoint to class file with src attached
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78190">78190</a>
+[dom] Add ast creation performance tests
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78189">78189</a>
+[model] Add hierarchy performance tests
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78188">78188</a>
+[search] Add search performance test
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78740">78740</a>
+IDOMType.getFlags() fails to represent interface flags correctly.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78735">78735</a>
+IBinding#isEqualTo(..) fails with a field that hides another
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78232">78232</a>
+[1.5][generics]Erroneous warning implementing generic method from interface
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78140">78140</a>
+[1.5][compiler] Unchecked conversion warning when overriding a generic method
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77861">77861</a>
+[1.5] Illegal class file generated with duplicate methods
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77785">77785</a>
+[1.5][compiler] Generics: missing name clash error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77496">77496</a>
+[1.5] compiler doesn't detect illegal method overriding due to non-matching return type parameters
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74936">74936</a>
+[1.5] Compiler does not warn for missing implementation of Map.putAll abstract method
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74594">74594</a>
+[1.5] ClassFormat error when running this example
+
+
+<a name="v_522"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M4 - 16th November 2004
+<br>Project org.eclipse.jdt.core v_522
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_522">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>In 1.5 compliant mode, T[].clone() invocations are considered to be of type T[], as opposed to Object
+previously. </li>
+
+<li>New ComletionProposal kind <code>METHOD_NAME_REFERENCE</code>.
+This completion is a reference to a method name.
+<br>This kind of completion might occur in a context like
+<code>"import java.lang.Math.co^"</code> and complete it to
+<code>"import java.lang.Math.cos;"</code>.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77808">77808</a>
+[1.5][dom] type bindings for raw List and List&lt;E&gt; have same key
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78704">78704</a>
+[1.5][compiler]Internal compiler error in org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78663">78663</a>
+[1.5][compiler] Generics, assign error with equal types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78649">78649</a>
+[1.5] ITypeBinding.isUpperBound wrong
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77398">77398</a>
+[1.5] Organize imports does not honor enum types [code manipulation]
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78464">78464</a>
+[1.5][compiler] bad args_size attribute value for Enum constructor
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78104">78104</a>
+[1.5][compiler] java.lang.Object.clone() implicitely needs an implicit cast to receiver type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78321">78321</a>
+Problem with Enum.values in static initializer.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78310">78310</a>
+[dom] [1.5] improve tests for IBindings
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78015">78015</a>
+[1.5][compiler] AbstractMethodError
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78266">78266</a>
+[dom] [1.5] API of ITypeBinding: no isGenericType() query
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64310">64310</a>
+[1.5][model] Signature implementation does not fully support generic parameterized type names
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77968">77968</a>
+[compiler] ArrayIndexOutOfBoundsException from parser when using Java editor
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77573">77573</a>
+[1.5][assist] Code assist does not propose static fields
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78008">78008</a>
+[1.5][compiler] java.lang.VerifyError on shortcut if-else
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78018">78018</a>
+[1.5][javadoc] Missing Javadoc comments Problem for enums
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73784">73784</a>
+[search] java search internal error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77644">77644</a>
+[dom] AST node extended positions may be wrong while moving
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78160">78160</a>
+Invalid classfile for problem type
+
+<a name="v_521"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M4 - 9th November 2004
+<br>Project org.eclipse.jdt.core v_521
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_521">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li><code>ICompletionRequestor</code> was deprecated. Use <code>CompletionRequestor</code> instead.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77359">77359</a>
+[1.5][dom] Pull up of type declaration facilities
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76132">76132</a>
+[1.5][wildcards] Bound mismatch incorrectly diagnosed with type variable quantification
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78139">78139</a>
+[1.5][compiler] spurious type mismatch problems with generics.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77602">77602</a>
+[javadoc] "Only consider members as visible as" is does not work for syntax error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77510">77510</a>
+[javadoc] compiler wrongly report deprecation when option "process javadoc comments" is not set
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78027">78027</a>
+[1.5] Generics, bound mismatch
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78089">78089</a>
+[1.5] [compiler] Annotations are not accepted inside interfaces
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74119">74119</a>
+[1.5] Unexpected compile error with bound types with Eclipse 3.1M1.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=78049">78049</a>
+[1.5][compiler] Missed error for generic array creation.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73970">73970</a>
+[1.5][dom] overloaded parameterized methods have same method binding key
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77422">77422</a>
+[1.5][compiler] ArrayIndexOutOfBoundsException with vararg constructor of generic superclass
+
+<a name="v_520"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M3 - 4th November 2004 - 3.1 MILESTONE 3
+<br>Project org.eclipse.jdt.core v_520
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_520">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=77244">77244</a>
+[1.5][enum] final enum class crashes the compiler
+
+<a name="v_519"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M3 - 4th November 2004
+<br>Project org.eclipse.jdt.core v_519
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_519">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=76780">76780</a>
+[model] return type not recognized correctly on some generic methods
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77772">77772</a>
+[1.5] some enums failing to parse; internal error dialog pops up while typin
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77538">77538</a>
+[dom] AST rewrite fails to generate the modified code
+
+
+<a name="v_518"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M3 - 2nd November 2004
+<br>Project org.eclipse.jdt.core v_518
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_518">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added API that allows to batch the creation of DOM ASTs: <code>ASTParser#createASTs(ICompilationUnit[] compilationUnits, String[] bindingKeys, ASTRequestor requestor, IProgressMonitor monitor)</code>.
+      Note this API is still under development and subject to change without notice.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70056">70056</a>
+[1.5] Please support varargs
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77327">77327</a>
+[1.5] Contravariance of generic Type raises Error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=71612">71612</a>
+[1.5] ClassFormatError when running simple example
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76434">76434</a>
+[1.5]  Generics, assign error despite equal types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76720">76720</a>
+[1.5] Implementing generic bounded subinterface causes Bound mismatch error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76219">76219</a>
+[1.5][wildcards] Not-necessarily-unbounded wildcards in method formal parameter types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76601">76601</a>
+[1.5] parameterized types: eclipse incorrectly reports errors
+
+<a name="v_517"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M3 - 2nd November 2004
+<br>Project org.eclipse.jdt.core v_517
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_517">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Search engine is now able to find declarations and references to varargs methods. This 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>Default severity for access restriction violations got raised to "warning".
+<pre>
+* COMPILER / Reporting Forbidden Reference to Type with Restricted Access
+*    When enabled, the compiler will issue an error or a warning when referring to a type with restricted access, as defined according
+*    to the access restriction specifications.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.forbiddenReference"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "warning"
 </pre>
 </li>
 </ul>
 
 <h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50258">50258</a>
-AST.parseCompilationUnit(... IWorkingCopyOwner..) should allow null 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49937">49937</a>
-JavaDoc of ITypeBinding#isLocal() talks about local interfaces 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49845">49845</a>
-DCR: Allow to cancel the AST creation 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48489">48489</a>
-[DCR] AST support for a single expression (vs. CU)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49327">49327</a>
-formatter can return null TextEdit when parsing valid java
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49908">49908</a>
-Renaming of DefaultCodeFormatterConstants.java
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49968">49968</a>
-[formatter] Alignment API
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49953">49953</a>
-[Code Formatter] Cannot customize the spaces around brackets in array allocation expression
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50025">50025</a>
-uppercase ZIP and JAR classpath entries ignored
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45060">45060</a>
-Missing external jar prevents build, but jar still in Java model 
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77273">77273</a>
+[model] ArrayIndexOutOfBoundsException when creating type hierarchy with duplicate types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76359">76359</a>
+[1.5] Unsafe operation not reported while using member type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77235">77235</a>
+ArrayIndexOutOfBounds in Parser in reconciler
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68710">68710</a>
+Open Declaration opens wrong target
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77249">77249</a>
+Annotation on class cancels "public" modifier
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77212">77212</a>
+[1.5][enum] declared enum type .valueOf(String) throws ArrayIndexOutOfBoundsException
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75400">75400</a>
+[1.5] Wrong type mismatch error reported
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75156">75156</a>
+[1.5] wrong diagnosis for method override
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70695">70695</a>
+[1.5] warning for easily detectible incorrect bounds
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72643">72643</a>
+[1.5] parser doesn't recognize when generic methods aren't used
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77051">77051</a>
+[1.5] Type mismatch involving super
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77175">77175</a>
+[1.5] DefaultBindingResolver#resolveType(EnumDeclaration) always returns null
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75328">75328</a>
+[1.5][wildcards] Bound Mismatch for ? type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72886">72886</a>
+[search] references to endVisit(MethodInvocation) reports refs to endVisit(SuperMethodInvocation)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75329">75329</a>
+[classpath] Restrict visibility of Java Project content
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74285">74285</a>
+Code assist doesn't  suggest parameter names for methods of generic types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74588">74588</a>
+[1.5] missing enclosing instance is wrongly reported when accessing an enclosing instance variable.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76313">76313</a>
+[1.5] Error while using parametrized static factory
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77151">77151</a>
+[1.5] Enum constant cannot be qualified when used as a case label
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77118">77118</a>
+[1.5] Covariance: cannot override method returning Object with method returning an interface
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=77052">77052</a>
+[1.5] Type mismatch on embedded type parameters
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76620">76620</a>
+Selection bug (Open Declaration)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76874">76874</a>
+[1.5] Out of memory reconciling some invalid enum source
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76682">76682</a>
+Certain code prevents saving and copy operations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74669">74669</a>
+[1.5] NullPointerException during save and compile
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74032">74032</a>
+[1.5] Generics: bad method referenced when a type variable extends two types
 
-<a name="v_397"></a>
+<a name="v_516"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0M7 Build - 13th January 2004
-<br>Project org.eclipse.jdt.core v_397
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_397">cvs</a>).
+Eclipse SDK 3.1M3 - 26th October 2004
+<br>Project org.eclipse.jdt.core v_516
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_516">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
-<li>Added API to get the scheduling rule for a Java element:
+<li>Support for search on enum has been implemented. Declarations or references to enum type, fields, constructors and methods are correctly found by search engine.
+</li>
+<li>Support to compute type hierarchies on enum 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 support inside CompletionEngine to not propose completion when an access restriction is violated.
+Currently access restrictions are applied only to top level types.
+</li>
+<li>Added code assist option to not propose completion when an access restriction is violated.
 <pre>
-	/**
-	 * Returns the scheduling rule associated with this Java element.
-	 * This is a handle-only method.
-	 * 
-	 * @return the scheduling rule associated with this Java element
-	 * @since 3.0
-	 */
-	ISchedulingRule getSchedulingRule();
+	 * CODEASSIST / Activate Access Restrictions Sensitive Completion
+	 *    When active, completion doesn't show that is access restricted.
+	 *     - option id:         "org.eclipse.jdt.core.codeComplete.restrictionsCheck"
+	 *     - possible values:   { "enabled", "disabled" }
+	 *     - default:           "disabled"
 </pre>
 </li>
-<li>Code formatter: If you did change the value of the setting controlling the insertion of a white space between empty arguments of a method declaration,
-then you have to change it again. Indeed, a spelling mistake has been fixed in the constant name. See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49530">49530</a>.</li>
-<li>Inline tags are now supported in Javadoc comments:
-<ul><li>{@link} and {@linkplain} tags are now parsed using same rules as for @see tag. See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48385">48385</a>.
-<br>Because references declared in these tags should be now found during search operation,  the index format had to be changed. Indexes will be automatically regenerated upon subsequent search queries (accounting for indexing notification in search progress dialogs).</li>
-<li>{@inheritDoc} tag is now parsed. When this tag is present in a method javadoc comment, all missing tags errors are ignored.
-See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45782">45782</a>.</li>
+<li>Added first-cut of enumeration support into compiler. Requires some more work to properly
+diagnose error situations, and be leveraged in various JDT/Core functionalities.
+</li>
+<li>Improved problem descriptions to show ellipsis in varargs method signatures
+</li>
+<li>Added <code>org.eclipse.jdt.core.util.ClassFileBytesDisassembler#SYSTEM</code> field to support an extra-detailed output from the
+disassembler. It can show constant pool contents.
+</li>
+<li>In order to fix bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76440">76440</a>, two APIs on <code>org.eclipse.jdt.core.Signature</code> have been added to handle var args in the signature decoding.
+<ul>
+<li><code>Signature#toCharArray(char[],char[],char[][],boolean,boolean,boolean)</code>
+</li>
+<li><code>Signature#toString(String,String,String[],boolean,boolean,boolean)</code>
+</li>
 </ul>
 </li>
+<li>Added compiler option to diagnose need for cast of varargs argument. Matching problem IDs are 
+<code>IProblem.MethodVarargsArgumentNeedCast</code> &amp; <code>IProblem.ConstructorVarargsArgumentNeedCast</code>
+<pre>
+* COMPILER / Reporting Varargs Argument Needing a Cast in Method/Constructor Invocation
+*    When enabled, the compiler will issue an error or a warning whenever a varargs arguments should be cast
+*    when passed to a method/constructor invocation. (e.g. Class.getMethod(String name, Class ... args )  
+*    invoked with arguments ("foo", null)).
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "warning"
+</pre>
+</li>
 </ul>
 
 <h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49843">49843</a>
-Not reporting error on constructor with no body
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49491">49491</a>
-Add option to toggle warning for Javadoc multiple same name @throws tags
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49260">49260</a>
-Malformed Javadoc Compiler option sensitive to line breaks
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45782">45782</a>
-[DCR] Compiler should take into account {@inheritDoc} tag
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48385">48385</a>
-[DCR] Need Javadoc warning for {@link }
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49760">49760</a>
-Splitting up FORMATTER_INSERT_SPACE_WITHIN_MESSAGE_SEND
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49763">49763</a>
-New formatter: Problem with empty statement in while
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48701">48701</a>
-NPE evaluating watch expression 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49290">49290</a>
-NullpointerException in TypeBinding.getInterfaces(). 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49660">49660</a>
-Code formatter line wrapping indentation ignores whitespace settings
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48293">48293</a>
-[DCR] IJavaElement should implement ISchedulingRule 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48459">48459</a>
-NPE in Type hierarchy 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49653">49653</a>
-Unnecessary white space is added after last semicolon in for statement without increments
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49351">49351</a>
-New code formatter: left curly brace placement
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49530">49530</a>
-Spelling mistake in the FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_ARGUMENTS string constant
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49298">49298</a>
-Code formatter does not correctly space closing bracket on method calls
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48395">48395</a>
-Hierarchy on region misses local classes 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47743">47743</a>
-Open type hiearchy problems [type hierarchy] 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49571">49571</a>
-White space options for method and constructor declarations
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49577">49577</a>
-Add an option to specify the number of blank lines between two type declarations
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49551">49551</a>
-formatter fails on empty statement between package and imports
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39943">39943</a>
-[navigation] outliner auto-changes selection (multi-fields) 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49490">49490</a>
-New Code Formatter; Java Coding Conventions; Blank Lines; Before first declaration
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49561">49561</a>
-Commit should only lock parent's folder 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47699">47699</a>
-Make org.eclipse.core.runtime.compatibility non optional 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41444">41444</a>
-[navigation] error dialog on opening class file 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48350">48350</a>
-IType#resolveType(String) fails on local types 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49120">49120</a>
-search doesn't find references to anonymous inner methods 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49482">49482</a>
-New Code Formatter; if/else without curly braces; guardian clause (2)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49481">49481</a>
-New Code Formatter; if/else without curly braces; guardian clause (1)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49361">49361</a>
-FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_ARRAY_INITIALIZER
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49243">49243</a>
-New code formatter: missing feature
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49429">49429</a>
-error during build
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48404">48404</a>
-formatter: no edit returned
-
-<a name="v_396"></a>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74851">74851</a>
+[1.5] enum errors in 3.1M1
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75134">75134</a>
+[1.5] Type mismatch error generated
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76880">76880</a>
+Unable to resolve enum type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76766">76766</a>
+[1.5] Option to format empty enum declaration or empty enum constant body has no effect
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76642">76642</a>
+Inner Enum Declarations not formatted
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76093">76093</a>
+Varargs support should define a subtype of ArrayTypeReference
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76472">76472</a>
+Duplicate entries in the constant pool for some methods
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76440">76440</a>
+[1.5] Disassembler doesn't render 1.5 constructs correctly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76524">76524</a>
+need a isVarargs() method on IMethodBinding
+	 
+<a name="v_515"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0M6 Build - 18th December 2003 - 3.0 MILESTONE-6
-<br>Project org.eclipse.jdt.core v_396
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_396">cvs</a>).
+Eclipse SDK 3.1M3 - 19th October 2004
+<br>Project org.eclipse.jdt.core v_515
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_515">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49081">49081</a>
-JDT is no more using the tab character by default for indentation 
-
-<a name="v_395"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M6 Build - 17th December 2003
-<br>Project org.eclipse.jdt.core v_395
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_395">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48706">48706</a>
-NPE in move refactoring 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48965">48965</a>
-Javadoc problem preference settings: Use 'include' instead of 'ignore'
-
-<a name="v_394"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M6 Build - 16th December 2003
-<br>Project org.eclipse.jdt.core v_394
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_394">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47209">47209</a>
-Javadoc: Type references are not found in @see tag inside a method reference
-
-<a name="v_393"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M6 Build - 16th December 2003
-<br>Project org.eclipse.jdt.core v_393
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_393">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48818">48818</a>
-NPE in delta processor 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48711">48711</a>
-javadoc-warning if derived exception in @throws clause
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46040">46040</a>
-NPE in Eclipse console 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48725">48725</a>
-Cannot search for local vars in jars. 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48749">48749</a>
-[Compiler] deprecation check in initializer fooled by trailing deprecated field decl
-
-
-<a name="v_392"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M6 Build - 15th December 2003
-<br>Project org.eclipse.jdt.core v_392
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_392">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li> Added option to avoid reporting a warning when overriding a deprecated method. By default, such
-warnings are no longer reported.
-<pre>
- * COMPILER / Reporting Deprecation When Overriding Deprecated Method
- *    When enabled, the compiler will signal the declaration of a method overriding a deprecated one.
- *    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.deprecation".
- *     - option id:        "org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod"
- *     - possible values:   { "enabled", "disabled" }
- *     - default:           "disabled"
-</pre>	 
-<li>Compiler options to signal problems with javadoc comments have been improved. User can now decide to report
-independently problems on invalid tags (syntax and references), missing tags and missing comments.
-Invalid references, missing tags or missing comments problem can be now ignored below a specific visibility level.
-Finally, user will also have the possibility to ignore missing tags and missing comments on overriding methods
-(assuming that complete Javadoc comments is done in superclass or interface declaration).
+<li>Code assist use static imports to propose completions.
+</li>
+<li>2 new Javadoc compiler options have been added (see bugs <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53977">53977</a>
+and <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75701">75701</a>).<br>
+While reporting problems on invalid Javadoc tags, user can now decide not to report deprecation and/or visibility warnings on references used in @see, @link or @values tags.
 <br>
-Here's the complete list of these options:
+Here's the description of these new options:
 <pre>
-	 * COMPILER / Reporting Invalid Javadoc Comment
-	 *    This is the generic control for the severity of Javadoc problems.
-	 *    When enabled, the compiler will issue an error or a warning for a problem in Javadoc.
-	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadoc"
-	 *     - possible values:   { "error", "warning", "ignore" }
-	 *     - default:           "ignore"
-	 *
-	 * COMPILER / Visibility Level For Invalid Javadoc Tags
-	 *    Set the minimum visibility level for Javadoc tag problems. Below this level problems will be ignored.
-	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility"
-	 *     - possible values:   { "public", "protected", "default", "private" }
-	 *     - default:           "private"
-	 * 
-	 * COMPILER / Reporting Invalid Javadoc Tags
-	 *    When enabled, the compiler will signal unbound or unexpected reference tags in Javadoc.
-	 *    A 'throws' tag referencing an undeclared exception would be considered as unexpected.
-	 *    <br>Note that this diagnosis can be enabled based on the visibility of the construct associated with the Javadoc;
+	 * COMPILER / Reporting Invalid Javadoc Tags with Deprecated References
+	 *    Specify whether the compiler will report deprecated references used in Javadoc tags.
+	 *    Note that this diagnosis can be enabled based on the visibility of the construct associated with the Javadoc;
 	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility".
-	 *    <br>
-	 *    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.invalidJavadoc".
-	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadocTags"
-	 *     - possible values:   { "disabled", "enabled" }
-	 *     - default:           "enabled"
-	 * 
-	 * COMPILER / Reporting Missing Javadoc Tags
-	 *    This is the generic control for the severity of Javadoc missing tag problems.
-	 *    When enabled, the compiler will issue an error or a warning when tags are missing in Javadoc comments.
-	 *    <br>Note that this diagnosis can be enabled based on the visibility of the construct associated with the Javadoc;
-	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility".
-	 *    <br>
-	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocTags"
-	 *     - possible values:   { "error", "warning", "ignore" }
-	 *     - default:           "ignore"
-	 * 
-	 * COMPILER / Visibility Level For Missing Javadoc Tags
-	 *    Set the minimum visibility level for Javadoc missing tag problems. Below this level problems will be ignored.
-	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility"
-	 *     - possible values:   { "public", "protected", "default", "private" }
-	 *     - default:           "private"
-	 * 
-	 * COMPILER / Reporting Missing Javadoc Tags on Overriding Methods
-	 *    Specify whether the compiler will verify overriding methods in order to report Javadoc missing tag problems.
-	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding"
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef"
 	 *     - possible values:   { "enabled", "disabled" }
 	 *     - default:           "enabled"
 	 * 
-	 * COMPILER / Reporting Missing Javadoc Comments
-	 *    This is the generic control for the severity of missing Javadoc comment problems.
-	 *    When enabled, the compiler will issue an error or a warning when Javadoc comments are missing.
-	 *    <br>Note that this diagnosis can be enabled based on the visibility of the construct associated with the expected Javadoc;
-	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility".
-	 *    <br>
-	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocComments"
-	 *     - possible values:   { "error", "warning", "ignore" }
-	 *     - default:           "ignore"
-	 * 
-	 * COMPILER / Visibility Level For Missing Javadoc Comments
-	 *    Set the minimum visibility level for missing Javadoc problems. Below this level problems will be ignored.
-	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility"
-	 *     - possible values:   { "public", "protected", "default", "private" }
-	 *     - default:           "public"
-	 * 
-	 * COMPILER / Reporting Missing Javadoc Comments on Overriding Methods
-	 *    Specify whether the compiler will verify overriding methods in order to report missing Javadoc comment problems.
-	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding"
+	 * COMPILER / Reporting Invalid Javadoc Tags with Not Visible References
+	 *    Specify whether the compiler will report non-visible references used in Javadoc tags.
+	 *    Note that this diagnosis can be enabled based on the visibility of the construct associated with the Javadoc;
+	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility".
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef"
 	 *     - possible values:   { "enabled", "disabled" }
 	 *     - default:           "enabled"
 	 * 
 </pre>
-Note that backward compatibility with previous options IDs: <code>"org.eclipse.jdt.core.compiler.problem.missingJavadoc"</code>
-will be supported until 3.0M7 build and removed after.
 </li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47214">47214</a>
-Cannot open declaration on a selected method of an anonymous class 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47795">47795</a>
-NPE selecting method in anonymous 2 level deep 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48335">48335</a>
-[Compiler] Need option to not report deprecation in override scenarii
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48523">48523</a>
-@throws reference incorrectly warned as not declared
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47940">47940</a>
-Unable to control level  of JavaDoc errors
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47319">47319</a>
-Compiler warns on missing Javadoc tags for private methods.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46976">46976</a>
-Do not warn about 'Missing Javadoc'  for overriding methods
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46854">46854</a>
-[DCR] Javadoc configuration setting needs more flexibility
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48617">48617</a>
-Error range for unresolved names in qualified references
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48333">48333</a>
-[Compiler] Implicit deprecation isn't propagated to anonymous type
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46084">46084</a>
-ArrayIndexOutOfBoundsException in compiler after feeding with non-real java code 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43354">43354</a>
-CodeAssist relevance should privilege package completion over type name 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48422">48422</a>
-Calling isStructureKnown() on ILocalVaraible throws JavaModelExceptions 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48261">48261</a>
-Search does not show results 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47213">47213</a>
-Inefficient recursion while initializing classpath container 
-
-<a name="v_391"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M6 Build - 10th December 2003
-<br>Project org.eclipse.jdt.core v_391
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_391">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>We reverted back the behavior when using the class literal. See bugs <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=37565">37565</a> and
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48086">48086</a>. As long as javac doesn't clarify this case, we keep
-the old behavior.</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48086">48086</a>
-Compiler does not resolve references in static init blocks correctly
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48353">48353</a>
-Indexes deleted on shutdown 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42579">42579</a>
-Eclipse allows setting a source folder's parent as output folder, which wipes out source code
-
-<a name="v_390"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M6 Build - 9th December 2003
-<br>Project org.eclipse.jdt.core v_390
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_390">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>The classpath validation rules now allow an excluded directory to be used as an output location. 
-Remember that a source folder can be associated with exclusion rules so as to eliminate portions of the
-source tree. Nested source/library entries were already allowed given proper exclusion rules were specified,
-now we also enable nesting an output folder as well under the same restrictions.
+<li>Changed build state format to record access restrictions. As a consequence, a full rebuild will be
+required when reusing existing workspaces.
 </li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47338">47338</a>
-CCE in CompletionParser
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45589">45589</a>
-Too many Util classes in JDTCore 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39539">39539</a>
-Cannot select excluded directory as output folder for class files
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48070">48070</a>
-[CodeAssist] ArrayIndexOutOfBoundsException in AssistParster
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48167">48167</a>
-Indentation/line wrapping problems with array initializers
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32022">32022</a>
-Indirect static proposal: Wrong compiler positions
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48141">48141</a>
-Formatter: Java Conventions/WS/Expressions/Operators 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45157">45157</a>
-Source Formatter: Clear all Blank lines needs to have the ability to set a number of lines to keep.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44673">44673</a>
-Formatting
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38523">38523</a>
-so add "Insert new line after each parameter if line is too long" checkbox to Preferences > Java > Code Formatter > New Lines
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34897">34897</a>
-Code Formatter feature request
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46937">46937</a>
-[Compiler] Marking a field deprecated still report deprecated usage
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47989">47989</a>
-Exception when searching for IPackageFragment "java.util.zip"
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47997">47997</a>
-No empty line after opening brace [formatter]
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48064">48064</a>
-Javadoc: NPE during build process
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44815">44815</a>
-Continuation indent for array initializer should be customizable
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44813">44813</a>
-Option "Insert new line before an open brace" should work also for array initializers
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43212">43212</a>
-catch variable not recognized by code-completion 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46060">46060</a>
-regression - content assist fails to present proposal 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47918">47918</a>
-New code Formatter 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47968">47968</a>
-Cannot find @see references in Class javadoc comment
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47909">47909</a>
-Javadoc: NPE while searching a constructor references in jdt-core
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47986">47986</a>
-Formatting of 'for' initializers
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47976">47976</a>
-Implementation of IField.getConstant() fails for some constants
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47886">47886</a>
-[Compiler] ACC_SUPER bit sets for interfaces
-
-<a name="v_389"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M6 Build - 2nd December 2003
-<br>Project org.eclipse.jdt.core v_389
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_389">cvs</a>).
-<h2>
-What's new in this drop</h2>
+<li>Added tracing (org.eclipse.jdt.core/debug/resolution) to show the number of packages, roots and working copies used during name resolution.</li>
+<li>New API <code>org.eclipse.jdt.core.dom.EnumDeclaration#enumConstants()</code>. The enum constants are now in a separate list
+from the body declarations. The  <code>org.eclipse.jdt.core.dom.EnumDeclaration#getEnumConstants()</code> method has been deprecated and
+will be removed after M3. See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76190">76190</a> for further details.
+</li>
+<li>New requestor API <code>CompletionRequestor</code> is implemented inside code assist engine.
+</li>
+<li>Added missing API to <code>IType</code> for new completion requestor support:
 <ul>
-<li>Spec and implementation for <code>ITypeBinding.getBinaryName()</code> was changed to be '.' separated:
+  <li><code>IType#codeComplete(char[],int,int,char[][],char[][],int[],boolean,CompletionRequestor,WorkingCopyOwner)</code></li>
+  <li><code>IType#codeComplete(char[],int,int,char[][],char[][],int[],boolean,CompletionRequestor)</code></li>
+</ul>
+</li>
+<li>Added missing API to <code>IEvaluationContext</code> for new completion requestor support:
+<ul>
+  <li><code>IEvaluationContext#codeComplete(String,int,CompletionRequestor, WorkingCopyOwner)</code></li>
+  <li><code>IEvaluationContext#codeComplete(String,int,CompletionRequestor)</code></li>
+</ul>
+</li>
+<li>Added new API inside <code>Signature</code> to extract package name part or type name part of a type signature:
+<ul>
+  <li><code>Signature#getSignatureQualifier(char[])</code></li>
+  <li><code>Signature#getSignatureQualifier(String)</code></li>
+  <li><code>Signature#getSignatureSimpleName(char[])</code></li>
+  <li><code>Signature#getSignatureSimpleName(String)</code></li>
+</ul>
+</li>
+<li>Added support in Java model for varargs methods:
+     <ul>
+     <li><code>Flags.isVarargs(method.getFlags())</code> now returns whether the method is a varargs method.</li>
+     <li>Operations that resolve (like reconcile, search, etc.) now convert varargs source methods into varargs MethodDeclarations.</li>
+     </ul>
+</li>
+<li> Introduced access restrictions so as to better enforce API contracts across components.
+<p>
+<i>Problem:</i> Libraries are usually packaged to contain both API for compile-time and implementation for runtime;
+and thus expose a superset of the API contract to client programs, allowing them to make forbidden
+assumptions on internals (a typical restriction for Eclipse developpers is to not use internal classes 
+from prerequisite plug-ins). 
+One solution for solving this issue is to separate the API from its implementation into 2 distinct libraries 
+(compile-time/runtime) and then use the classpath rules to only include the API portion on the classpath
+for compiling. However, this usually proves to be unrealistic, since the API is often mixed with some implementation
+aspects (not officially part of the API) which are carrying references to its internals 
+(supertype hierarchy, field or method signatures). When it happens, then the compiler needs the implementation
+also to be on the classpath in order to resolve all signatures appropriately; which goes back to the original
+problem of exposing too much to unaware clients.
+<p>
+Instead, we allowed classpath rules to be associated with some import restrictions so as to select portions 
+of prerequisite projects or libraries which are legal to use inside this project. 
+Access restrictions are expressed as inclusion/exclusion rules on classpath entries (using Ant fileset notation
+for discriminating on package and/or file names, e.g. <code>excluding='**/internal/'</code> would exclude 
+all types defined any <code>internal</code> package),
+and can be associated to project, library, classpath variable or classpath container classpath entries. 
+Note that restrictions are automatically combined along a classpath chain. For instance, if a classpath container entry is
+associated with some restrictions, then when resolved to a set of entries, these will automatically inherit the
+container restrictions (and could still provide further custom restrictions on a per entry basis).
+<p>
+When a forbidden reference to a restricted type is detected, the compiler will issue a problem which severity
+can be controlled by JavaCore preference "org.eclipse.jdt.core.compiler.problem.forbiddenReference". 
+Corresponding problem marker ID is <code>IProblem.ForbiddenReference</code>.
 <pre>
- /**
- * Returns the binary name of this type binding.
- * The binary name of a class is defined in the Java Language 
- * Specification 2nd edition, section 13.1.
- *
- * Note that in some cases, the binary name may be unavailable.
- * This may happen, for example, for a local type declared in 
- * unreachable code.
- *
- * @return the binary name of this type, or null 
- * if the binary name is unknown
- * @since 3.0
- */
-public String getBinaryName();
+* COMPILER / Reporting Forbidden Reference to Type with Restricted Access
+*    When enabled, the compiler will issue an error or a warning when referring to a type with restricted access, as defined according
+*    to the access restriction specifications.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.forbiddenReference"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>
+
+<p>
+In order to challenge this new functionality before leveraged in UI or PDE, Eclipse developpers need to perform
+the following two actions:
+<ol>
+<li> edit some .classpath file to exclude all types located in "**/internal/" packages from prerequisites;
+i.e. replace line
+<pre>
+	&lt;classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/&gt;
+</pre>
+with
+<pre>
+	&lt;classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins" excluding="**/internal/"/&gt;
+</pre>
+</li>
+<li> enable compiler warning for forbidden references, i.e. add the following line to the workspace 
+default preferences located in: <code>&lt;workspace&gt;\.metadata\.plugins\org.eclipse.core.runtime\.settings\org.eclipse.jdt.core.prefs</code>
+<pre>
+	org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+</pre>
+Note: alternatively, it could be specified on a per project basis, by adding line to <code>&lt;project&gt;/.settings/org.eclipse.jdt.core.prefs</code>.
+</li>
+</ol>
+</li>
+<li>Static imports are now supported:
+<pre>
+<b><font color="#0000ff">import static</font></b> <i><font color="#A0A0A0">type</font></i>.*;
+<b><font color="#0000ff">import static</font></b> <i><font color="#A0A0A0">type</font></i>.<i><font color="#A0A0A0">identifier</font></i>;
+</pre>
+Java Search is also able to find referenced type, field and/or member in static imports but required the index version to be incremented.<br>
+Indexes will be automatically regenerated upon subsequent search queries (accounting for indexing notification in search progress dialogs).
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76324">76324</a>
+[Javadoc] Wrongly reports invalid link format in @see and @link
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74369">74369</a>
+[Javadoc] incorrect javadoc in local class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75701">75701</a>
+[Javadoc] References in Javadoc to deprecated members
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53977">53977</a>
+[DCR] [Javadoc] Add a Javadoc option not to report errors on non-visible references
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76360">76360</a>
+[1.5] NPE when using static import
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76174">76174</a>
+[1.5] missing error when using static import
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76159">76159</a>
+Missing type in hierarchy
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76328">76328</a>
+Using latest, NPE in codeassist
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66296">66296</a>
+Slow closing editor after startup
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76277">76277</a>
+IllegalArgumentException: Invalid string literal : &gt;("i" + "ib2")&lt;
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76190">76190</a>
+DCR AST: EnumDeclaration: Separate field and body statement lists
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76244">76244</a>
+[1.5] No error on invalid static import declaration
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76181">76181</a>
+Formatter fails on EnumDeclaration
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74776">74776</a>
+[Search] Wrong search results for almost identical method
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70827">70827</a>
+[Search] wrong reference match to private method of supertype
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29865">29865</a>
+Source visibility in project dependency
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76181">76181</a>
+Formatter fails on EnumDeclaration
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76100">76100</a>
+AST: Javadoc node not available on AnnotationTypeDeclaration
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76103">76103</a>
+[1.5] Inner AnnotationTypeDeclaration not parsed
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=76027">76027</a>
+Optimization of code assist in debugger
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75090">75090</a>
+source positions calculated wrongly
+
+
+<a name="v_514"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M3 - 12th October 2004
+<br>Project org.eclipse.jdt.core v_514
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_514">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Type search works with generic (only for string pattern, see bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75641#c4">75641</a>).<br>
+For example, user can enter <i><code>List&lt;String&gt;</code></i> in Java Search text and search for type references.<br>
+Match(es) will be found if this parameterized type is used in the search scope.<br>
+Note that some API changes still need to be done to make generic type search work while selecting a parameterized type from Java editor.
+</li>
+<li>Field search works with generic (see bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73277">73277</a>).<br>
+For example, user can search for references to a field declared as <pre>List&lt;String&gt; ls;</pre>
+Match(es) will be found if this field is used in the search scope.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75649">75649</a>
+[1.5] completion inside a wildcard does not work
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52379">52379</a>
+JavaElement.getElementInfo no longer works
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74753">74753</a>
+[1.5] codeassist failing on type parameter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73277">73277</a>
+[1.5][Search] Fields search does not work with generics
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73671">73671</a>
+[1.5] Signature.getTypeArguments should also tolerate normal types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73078">73078</a>
+ISourceManipulation.delete() tries to run in WorkspaceRoot scheduling rule
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75561">75561</a>
+Rename package results in I/O exception
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75644">75644</a>
+Array index out of bounds doing code assist
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74286">74286</a>
+IllegalArgumentException during codeselect
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75720">75720</a>
+[1.5] Formatter cannot format code that contains varargs
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75112">75112</a>
+[Search] Cannot find reference to a member type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75632">75632</a>
+Infinite loop in DefaultCommentMapper#storeLeadingComments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75658">75658</a>
+[1.5] SourceElementParser do not compute correctly bounds of type parameter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75488">75488</a>
+Incorrect code formatting
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70602">70602</a>
+Why is equals(..) method of IBindings not implemented?
+
+<a name="v_513"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M3 - 5th October 2004
+<br>Project org.eclipse.jdt.core v_513
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_513">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>The batch compiler now support 5 as a valid version number for -target and -source options.
+5 is equivalent to 1.5.</li>
+<li>Added support for static imports. Can now import all static members of a type, such as <code>java.lang.Math</code>.</li>
+<li>Added new API <code>IBinding#getJavaElement()</code> to get the Java element corresponding to a 
+     <code>org.eclipse.jdt.core.dom.IBinding</code>.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75466">75466</a>
+[1.5] IAE in JavaElement.exists() for Collection&lt;E&gt;#containsAll(Collection&lt;?&gt;)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75455">75455</a>
+[1.5] IAE on Content Assist for variable of type List&lt;? extends Number&gt;
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75489">75489</a>
+Batch compiler should support -target 5 or -source 5
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73963">73963</a>
+[1.5] Wrong errors in widening reference conversion to parameterized class type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=75221">75221</a>
+Failure in test for build I200409281200 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74126">74126</a>
+Compiler should support new hexadecimal floating-point literals
+
+<a name="v_512"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M3 - 28th September 2004
+<br>Project org.eclipse.jdt.core v_512
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_512">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=74761">74761</a>
+[1.5] Invalid compiler binding for qualified raw type reference
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68927">68927</a>
+'non-static access to static member' problem not reported for super field access
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74938">74938</a>
+Syntax error for annotation in 1.4 has unknown source range
+
+<a name="v_511"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M2 - 24th September 2004 - 3.1 MILESTONE 2
+<br>Project org.eclipse.jdt.core v_511
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_511">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=74934">74934</a>
+ArrayIndexOutOfBoundsException with float literal
+
+<a name="v_510"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M2 - 23rd September 2004
+<br>Project org.eclipse.jdt.core v_510
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_510">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Support for hexadecimal floating-point literals has been added. This is available in 1.5 mode only.</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72583">72583</a>
+[1.5] NPE in Scope.minimalErasedCandidate
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74096">74096</a>
+[1.5] visibility check ignores type bounds?
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74592">74592</a>
+[1.5] Invalid cycle diagnosis
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74420">74420</a>
+[1.5] Unexpected "Illegal forward reference to type parameter T"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74519">74519</a>
+Can declare @interface in 1.4
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74544">74544</a>
+[1.5] Invalid compiler binding for parameterized qualified type reference
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74514">74514</a>
+NPE in AST creation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74014">74014</a>
+prefix path for source attachements - automatic detection does not seem to work 
+
+<a name="v_509"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M2 - 21st September 2004
+<br>Project org.eclipse.jdt.core v_509
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_509">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=74355">74355</a>
+-source 1.4 and -1.5 leads to an error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74320">74320</a>
+[1.5] Unused private member diagnosis fooled by generics
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74289">74289</a>
+AIOOB Exception in WeakHashSet.cleanupGarbageCollectedValues 
+
+
+<a name="v_508"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M2 - 20th September 2004
+<br>Project org.eclipse.jdt.core v_508
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_508">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=73740">73740</a>
+Diagnosis for serialization should not render j2me development impossible
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=74244">74244</a>
+[1.5] boolean.class == Boolean.TYPE should be true
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73995">73995</a>
+[Javadoc] Wrong warning for missing return type description for @return {@inheritDoc}
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72644">72644</a>
+[1.5] Problems with generic maps
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73356">73356</a>
+Index not updated after adding a source folder 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73961">73961</a>
+IPackageBinding#getName() should return "" for default package
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73933">73933</a>
+Clarifications of the DOM/AST API for VariableDeclarationExpression and VariableDeclarationStatement
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73891">73891</a>
+Should not use String#intern() 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73837">73837</a>
+Java 1.5 generics problem (Eclipse 3.1M1)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73336">73336</a>
+[1.5][search] Search Engine does not find type references of actual generic type parameters
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73762">73762</a>
+Line ends not reset when setting a different source 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73884">73884</a>
+[1.5] Unexpected error for class implementing generic interface
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73896">73896</a>
+StackOverflowError resolving bindings of java.util.Collections
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73678">73678</a>
+[1.5] NPE when saving an editor which contains genric type
+
+<a name="v_507"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M2 - 14th September 2004
+<br>Project org.eclipse.jdt.core v_507
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_507">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=72683">72683</a>
+Slow code assist in Display view 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73696">73696</a>
+searching only works for IJavaSearchConstants.TYPE, but not CLASS or INTERFACE
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73479">73479</a>
+[Javadoc] Improve error message for invalid link in @see tags
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73551">73551</a>
+[Search] NPE while searching package declaration
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73112">73112</a>
+[Search] SearchEngine doesn't find all fields multiple field declarations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=71267">71267</a>
+[Search][Javadoc] SearchMatch in class javadoc reported with element of type IImportDeclaration
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73348">73348</a>
+[Javadoc] Missing description for return tag is not always warned
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73573">73573</a>
+[1.5] - CodeAssist - ArrayIndexOutOfBoundsException with genric type completion
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=67976">67976</a>
+Exceptions in log when Opening type while checking out 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72684">72684</a>
+MemberElementInfo#name should be removed 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73530">73530</a>
+[1.5] VerifyError using generics and direct array access
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73286">73286</a>
+NPE on save
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73497 ">73497</a>
+Problem methods don't point to the right position in source
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73561">73561</a>
+AST: Enum constant source range too small
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=71279">71279</a>
+[Search] NPE in TypeReferenceLocator when moving CU with unresolved type reference
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=67981">67981</a>
+Add Java Exception Breakpoint is broken 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72859">72859</a>
+NPE in ASTConverter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72214">72214</a>
+[Prefs] IllegalStateException when importing preferences
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62472">62472</a>
+[1.5] Suspicious syntax errors for missing semicolon
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72889">72889</a>
+same key different types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68555">68555</a>
+SearchEngine errors when package and class named the same
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72891">72891</a>
+missing type parameters for IMethodBindings
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72882">72882</a>
+ITypeBinding.getQualifiedName for type variables wrong
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73371">73371</a>
+[1.5] Code formatter doesn't seem to accept enum declarations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73048">73048</a>
+Stackoverflow on AST creation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69002">69002</a>
+CompilationUnit#destroy contains e.printStackTrace 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70787">70787</a>
+Compilation warning for IndexManager 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73245">73245</a>
+Error source range of 'class cannot be superinterface'
+
+<a name="v_506"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1M2 - 7th September 2004
+<br>Project org.eclipse.jdt.core v_506
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_506">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li><code>ITypeParameter</code>s are no longer children of their <code>IType</code> or <code>IMethod</code>.
+     To get the type parameters of a type or a method use <code>IType/IMethod#getTypeParameters()</code>.</li>
+<li>The temporary field <code>TypeParameter#ENABLED</code> has been removed.</li>
+<li>Code select (<code>ICodeAssist#codeSelect()</code>) return a <code>ITypeParameter</code> when a type
+    parameter is selected.</li>
+<li>Added optional compiler diagnosis for usage of 'enum' as an identifier.
+Corresponding problem ID is IProblem.UseEnumAsAnIdentifier.
+</li>
+<pre>
+* COMPILER / Reporting Usage of 'enum' Identifier
+*    When enabled, the compiler will issue an error or a warning whenever 'enum' is 
+*    used as an identifier (reserved keyword in 1.5)
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.enumIdentifier"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "warning"
 </pre>
 </li>
 </ul>
 
 <h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47881">47881</a>
-[Compiler] x && false evaluates to "true"
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47802">47802</a>
-New Code Formatter: NEXT_PER_LINE_SPLIT
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47811">47811</a>
-New Code Formatter: doesn't handle several classes per CU
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47801">47801</a>
-New Code Formatter: INSERT_SPACE_AFTER_PREFIX_OPERATOR
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47800">47800</a>
-New Code Formatter: BINARY_EXPRESSION_ALIGNMENT
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47799">47799</a>
-New Code Formatter: PUT_EMPTY_STATEMENT_ON_NEW_LINE
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47776">47776</a>
-java.lang.VerifyError / Illegal target of jump or branch compiling with 3.0 M5
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47341">47341</a>
-Javadoc problem for @see to protected method
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47339">47339</a>
-Javadoc problem while using @see tag
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47132">47132</a>
-Javadoc for method in anonymous type should not be mark as missing
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47215">47215</a>
-Javadoc: type reference in @see tag ignore the following text
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46761">46761</a>
-Search for references: misses match in Javadoc
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46675">46675</a>
-[Compiler] NullPointerException with ? operator
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35220">35220</a>
-CodeAssist - method of anonymous type should not be proposed
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47631">47631</a>
-PerThreadObject (JavaModelManager.deltaState) leaks Threads.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46470">46470</a>
-Wrong completion after a switch
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35232">35232</a>
-CodeAssist - wrong completion for static method in anonymous type
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47401">47401</a>
-Wrong code assist proposals in anonymous class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47443">47443</a>
-All projects touched on startup
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44493">44493</a>
-Improve formatting of throws clauses
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44765">44765</a>
-New formatter not properly formatting long method invocation
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44653">44653</a>
-// $NON-NLS-1$ comments not kept on same line of the string while formatting
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46699">46699</a>
-IBinding.isSynthetic() returns false for compiler-generated constructor
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47415">47415</a>
-[Search] package references confused with multiple fragments
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38679">38679</a>
-Search for class ref shows local class containing a match on an import [search]
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47049">47049</a>
-[Builder] Build output folder not getting flushed because files are not marked as derived
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46613">46613</a>
-AST nodes and string buffers
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47396">47396</a>
-JAVA AST Creation failure
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66533">66533</a>
+[1.5] add a warning for 'enum' used as identifier
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70892">70892</a>
+[1.5][Javadoc] Compiler should parse reference for inline tag @value
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73255">73255</a>
+[1.5][reconciling] ClassCastException in SourceTypeElementInfo#getTypeParameterBounds 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72946">72946</a>
+Refactoring context menu does not show inline action on local variables [refactoring] [inline temp]
 
-<a name="v_388"></a>
+<a name="v_505"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0M6 Build - 25th November 2003
-<br>Project org.eclipse.jdt.core v_388
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_388">cvs</a>).
+Eclipse SDK 3.1M2 - 31st August 2004
+<br>Project org.eclipse.jdt.core v_505
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_505">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
+<li>Added empty "performance" target to test.xml files.
 </ul>
 
 <h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47082">47082</a>
-[Compiler] Problem with final variable initialization
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47180">47180</a>
-Merge different type declarations into one class
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72772">72772</a>
+[1.5][Search Engine] ClassCastException: org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding
 
-
-<a name="v_387"></a>
+<a name="v_504"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0M5 Build - 21st November 2003 - 3.0 MILESTONE-5
-<br>Project org.eclipse.jdt.core v_387
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_387">cvs</a>).
+Eclipse SDK 3.1M2 - 31st August 2004
+<br>Project org.eclipse.jdt.core v_504
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_504">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
+<li>Added new Java element <code>ITypeParameter</code> that represents a formal type parameter in a generic type or method.
+     Note types and methods should have type parameters as children, but this is currently disabled as JDT UI doesn't support
+     this kind of element yet.
+     To enable set <code>org.eclipse.jdt.internal.core.TypeParameter#ENABLED</code> to <code>true</code>.</li>
 </ul>
 
 <h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44397">44397</a>
-Search doesn't find references to local types
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46571">46571</a>
-Searching for all occurrences for method declarated in local types doesn't wor
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46943">46943</a>
-refactoring: encapsulate field of local type: references from enclosing type are not replaced by setter 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47180">47180</a>
-NPE in Delta Processor 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46788">46788</a>
-Export scripts: shouldn't use variable name version
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47160">47160</a>
-ArrayIndexOutOfBoundsException from CodeSnippetParser
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47177">47177</a>
-ClassCastException during hover
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47079">47079</a>
-[Builder] suspicious side-effects during incremental compile
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72942">72942</a>
+[1.5] 'AT' is visible inside syntax error messages 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68343">68343</a>
+IDOMType.setSuperInterfaces() with empty array has no impact on Interfaces 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72083">72083</a>
+[1.5] NPE while compiling FindBugs
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=71080">71080</a>
+[1.5] Type parameter bound &lt;E extends Enum&lt;E&gt;&gt; should be allowed
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62070">62070</a>
+Should revisit reference recording
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36397">36397</a>
+Compiling source which indirectly references unavailable classes
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62822">62822</a>
+[1.5] Bound mismatch: The type X is not a valid substitute for the bounded parameter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72094">72094</a>
+NPE inside qualified type reference resolution
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72468">72468</a>
+"hierarchy of ... type is inconsistent" error message
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59082">59082</a>
+[1.5] Should not offer argument completion for non generic type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72501">72501</a>
+[1.5] CodeAssist - ArrayIndexOutOfBoundsException with ParameterizedQualifiedTypeReference
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72640">72640</a>
+Codestream target level is initialized with source level
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72560">72560</a>
+[1.5] VerifyError in nested generics loop
 
-<a name="v_386"></a>
+<a name="v_503"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0M5 Build - 20th November 2003
-<br>Project org.eclipse.jdt.core v_386
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_386">cvs</a>).
+Eclipse SDK 3.1M2 - 24th August 2004
+<br>Project org.eclipse.jdt.core v_503
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_503">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
-<li>Removed APIs that create an <code>ICompilationUnit</code> handle given a <code>WorkingCopyOwner</code>
-	 as these can be replaced with <code>ICompilationUnit.findWorkingCopy(WorkingCopyOwner)</code>:
-	 <ul>
-	 <li><code>IPackageFragment.getCompilationUnit(String, WorkingCopyOwner)</code></li>
-	 <li><code>JavaCore.create(IFile, WorkingCopyOwner)</code></li>
-	 <li><code>JavaCore.create(IResource, WorkingCopyOwner)</code></li>
-	 <li><code>JavaCore.createCompilationUnitFrom(IFile, WorkingCopyOwner)</code></li>
-	 <li><code>IDOMCompilationUnit.getCompilationUnit(IPackageFragment, WorkingCopyOwner)</code></li>
-	 </ul>
-	 <br>
-</li>
-<li>Added API on <code>ICompilationUnit</code> to find an existing working copy given a working
-	 copy owner (it replaces <code>IWorkingCopy.findSharedWorkingCopy(IBufferFactory)</code>):
-<pre>
-/**
- * Finds the working copy for this compilation unit, given a <code>WorkingCopyOwner</code>. 
- * If no working copy has been created for this compilation unit associated with this
- * working copy owner, returns <code>null</code>.
- *
- * Users of this method must not destroy the resulting working copy. 
- * 
- * @param owner the given <code>WorkingCopyOwner</code>
- * @return the found working copy for this compilation unit, <code>null</code> if none
- * @see WorkingCopyOwner
- * @since 3.0
- */
-ICompilationUnit findWorkingCopy(WorkingCopyOwner owner);
-</pre>
-</li>
-<li>Added API on <code>IClassFile</code> to create a working copy on a class file (it replaces 
-	 <code>IClassFile.getWorkingCopy(IProgressMonitor, IBufferFactory)</code>):
-<pre>
-/**
- * Returns a working copy on the source associated with this class file using the given 
- * owner to create the buffer, or <code>null</code> if there is no source associated
- * with the class file.
- * 
- * The buffer will be automatically initialized with the source of the class file
- * upon creation.
- * 
- * The only valid operations on this working copy are <code>getBuffer()</code> or <code>getPrimary()</code>.
- *
- * @param owner the owner that creates a buffer that is used to get the content of the working copy
- *                 or <code>null</code> if the primary owner should be used
- * @param monitor a progress monitor used to report progress while opening this compilation unit
- *                 or <code>null</code> if no progress should be reported 
- * @return a  a working copy on the source associated with this class file
- * @exception JavaModelException if the source of this class file can
- *   not be determined. Reasons include:
- *   - This class file does not exist (ELEMENT_DOES_NOT_EXIST)
- * @since 3.0
- */
-ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException;
-</pre>
-</li>
-<li>Added API on <code>ITypeBinding</code> to get the binary name of a type binding:
-<pre>
-/**
- * Returns the binary name (as defined in the Java Language 
- * Specification Chapter 13 Section 1) of this type binding.
- * It is however slash ('/') separated instead of dot ('.') separated as said
- * in the specification.
- * Returns <code>null</code> if the type is defined in code that is unreachable.
- *
- * @return the binary name of this type or <code>null</code> if this type is unreachable
- */
-String getBinaryName();
-</pre>
-</li>
+<li>All resource change listeners/builder now react to new encoding change notification.</li>
 </ul>
 
 <h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46012">46012</a>
-IllegalArgumentException in StringLiteral
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46769">46769</a>
-NPE in PatternLocator.qualifiedSourceName
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70193">70193</a>
+DBCS - The GB18030 character cannot be correctly generated into ".classpath" file when new a source folder named with GB18030 character. 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70997">70997</a>
+Debugger doesn't stop in finally block
 <br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47074">47074</a>
 inability to detect invalid cast between interfaces
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46057">46057</a>
-need mechanism for retrieving the name of anonymous and local classes 
-
-<a name="v_385"></a>
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=71910">71910</a>
+Weird exception handlers ranges with any exception handlers
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72352">72352</a>
+"No completion available" after cast to "String[]"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=71702">71702</a>
+code completion doesn't work anymore after Array cast. 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68847">68847</a>
+[1.5] DCR Signature: API to separate raw type and type parameters 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72348">72348</a>
+[1.5][Type Hierarchy] Super type hierarchy of class extending generic type is empty 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72105">72105</a>
+[1.5] NPE in SelectionEngine.selectFrom 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72230">72230</a>
+[1.5][Type Signature] IAE in createCharArrayTypeSignature 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68506">68506</a>
+Java code formatter strips newline, leaving final line unterminated!
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59052">59052</a>
+[1.5][reconciling] DOM conversion incomplete for generics
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72248">72248</a>
+[1.5] StackOverflowError caused by methods type variable
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72233">72233</a>
+IAE creating AST for java.lang.SuppressWarnings
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57585">57585</a>
+memory optimization in JavaModelCache 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=72238">72238</a>
+[1.5] CodeAssist - Wrong completion inside parameterized type 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68585">68585</a>
+index is out of date after encoding change 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68594">68594</a>
+[1.5] NPE after code assist
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70995">70995</a>
+[1.5] Add 1.5 constructs in the code formatter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68842">68842</a>
+[1.5] AST: parameter type binding: getKey seems wrong
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=71852">71852</a>
+ClassCastException in HandleFactory.createElement(...)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69066">69066</a>
+[1.5] getTypeArguments incorrect (?) when type argument is a type variable
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68838">68838</a>
+[1.5] AST: Missing bindings in type parameters
+	  	
+<a name="v_502"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0M5 Build - 19th November 2003
-<br>Project org.eclipse.jdt.core v_385
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_385">cvs</a>).
+Eclipse SDK 3.1M1 - 10th August 2004 - 3.1 MILESTONE 1
+<br>Project org.eclipse.jdt.core v_502
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_502">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
 </ul>
 
 <h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46964">46964</a>
-Can not set Javadoc compiler setting
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46901">46901</a>
-Strange compile error in javadoc
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66908">66908</a>
+Code assist javadoc confused by duplicate java.lang.String
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66570">66570</a>
+Code assist fails due to capitalization
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=71705">71705</a>
+[1.5] CodeAssist failure with simple test case
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69598">69598</a>
+[1.5] Auto Completion not available in new for-loop
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=71672">71672</a>
+[1.5] MethodInvocation has no type arguments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=67790">67790</a>
+[1.5] AST: ConstructorInvocation type arguments not in source range
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70292">70292</a>
+[1.5] enum makes Copy, Cut commands fail
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=71241">71241</a>
+[1.5] different methods with same erasure should not override
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69901">69901</a>
+[1.5] Interface / Generic: unchecked conversion should throw a warning
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=71467">71467</a>
+JavaConventions.ValidatePackageName() does not return ERROR
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=71113">71113</a>
+[1.5] improve DOM/AST specs for bindings for JLS3 constructs
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=71079">71079</a>
+[1.5] ClassCastException resolving Javadoc
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70969">70969</a>
+[1.5] compile error with conditional operator and wildcards
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70611">70611</a>
+[1.5] Specific generic class declaration breaks save and load
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69931">69931</a>
+JDTCompilerAdapter prevents use of Cheetah
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=71007">71007</a>
+[1.5] Qualified name not supported as member value
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70984">70984</a>
+[1.5] Invalid syntax error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70986">70986</a>
+[Prefs] Old Java project prefs are not all stored while migrating to new API
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70975">70975</a>
+[1.5] Type mismatch when compiling against binary generic method
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70656">70656</a>
+[1.5] StackOverflow when resolving Enum&lt;FormattedFloatingDecimal$Form&gt; 
 
-<a name="v_384"></a>
+
+<a name="v_501"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0M5 Build - 19th November 2003
-<br>Project org.eclipse.jdt.core v_384
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_384">cvs</a>).
+Eclipse SDK 3.1M1 - 27th July 2004 - Codename "Cheetah"
+<br>Project org.eclipse.jdt.core v_501
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_501">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
-<li>Added API on <code>ICompilationUnit</code> to query whether the working copy's resource has changed 
-	 (it replaces <code>IWorkingCopy.isBasedOn(IResource)</code>):
+<li>Plugin version ID got incremented to 3.1.0. </li>
+<li>Added support for method return type covariance</li>
+<li>Added optional compiler diagnosis for serializabe classes missing a declaration of serialVersionUID field.
+Corresponding problem ID is IProblem.MissingSerialVersion.
+</li>
 <pre>
-/**
- * Returns whether the resource of this working copy has changed since the
- * inception of this working copy.
- * Returns <code>false</code> if this compilation unit is not in working copy mode.
- * 
- * @return whether the resource has changed
- * @since 3.0
- */
-public boolean hasResourceChanged();
+* COMPILER / Reporting Missing Declaration of serialVersionUID Field on Serializable Class
+*    When enabled, the compiler will issue an error or a warning whenever a serializable class is missing a local declaration 
+*    of a serialVersionUID field. This field must be declared as static final and be of type long.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.missingSerialVersion"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "warning"
 </pre>
+<li>Added <code>isConstructor()</code> and <code>isSynthetic()</code> getters to MethodReferenceMatch.
+<br>
+When a search requestor (<code>SearchRequestor</code>) accepts this kind of match,
+it can now distinguish between method and constructor reference matches. It can also know
+if a constructor reference match is a default constructor or use an implicit super call.
+<br>
+Note that synthetic method reference match is not supported yet.
 </li>
-<li>Added APIs on <code>IType</code> to create hierarchies using <code>ICompilationUnits</code> instead of
-     <code>IWorkingCopies</code>:
-<pre>
-/**
- * Creates and returns a type hierarchy for this type containing
- * this type and all of its supertypes, considering types in the given 
- * working copies. In other words, the list of working copies will take 
- * precedence over their original compilation units in the workspace.
- *
- * Note that passing an empty working copy will be as if the original compilation
- * unit had been deleted.
- *
- * @param workingCopies the working copies that take precedence over their original compilation units
- * @param monitor the given progress monitor
- * @return a type hierarchy for this type containing this type and all of its supertypes
- * @exception JavaModelException if this element does not exist or if an
- *		exception occurs while accessing its corresponding resource.
- * @since 3.0
- */
-ITypeHierarchy newSupertypeHierarchy(ICompilationUnit[] workingCopies, IProgressMonitor monitor) throws JavaModelException;
-
-/**
- * Creates and returns a type hierarchy for this type containing
- * this type, all of its supertypes, and all its subtypes in the workspace, 
- * considering types in the given working copies. In other words, the list of working 
- * copies that will take precedence over their original compilation units in the workspace.
- * 
- * Note that passing an empty working copy will be as if the original compilation
- * unit had been deleted.
- *
- * @param workingCopies the working copies that take precedence over their original compilation units
- * @param monitor the given progress monitor
- * @return a type hierarchy for this type containing
- * this type, all of its supertypes, and all its subtypes in the workspace
- * @exception JavaModelException if this element does not exist or if an
- *		exception occurs while accessing its corresponding resource.
- * @since 3.0
- */
-ITypeHierarchy newTypeHierarchy(ICompilationUnit[] workingCopies, IProgressMonitor monitor) throws JavaModelException;
-</pre>
-<li>Added API on <code>SearchEngine</code> to create a search engine using 
-	 <code>ICompilationUnits</code> instead of <code>IWorkingCopies</code>:
-<pre>
-/**
- * Creates a new search engine with a list of working copies that will take precedence over 
- * their original compilation units in the subsequent search operations.
- *
- * Note that passing an empty working copy will be as if the original compilation
- * unit had been deleted.
- *
- * Since 3.0 the given working copies take precedence over primary working copies (if any).
- * 
- * @param workingCopies the working copies that take precedence over their original compilation units
- * @since 3.0
- */
-public SearchEngine(ICompilationUnit[] workingCopies) {...}
-</pre>
+<li>Once 1.5 source compliance is enabled, the typecheck rules for conditional operator (a ? b : c) 
+allows scenario where 'b' and 'c' have a common supertype (i.e. it is no longer required for
+one to be assignable to the other as in the past). This is required by JLS 3rd edition.
 </li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-
-<a name="v_383"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M5 Build - 18th November 2003
-<br>Project org.eclipse.jdt.core v_383
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_383">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>To avoid confusion with annotations introduced in JDK 1.5 grammar, all internal references to "annotation" (added to handle Javadoc comments) 
-got renamed into "Javadoc". As a consequence of this is that IDs for optional Javadoc problems have been updated accordingly:
-<pre>
-	 * COMPILER / Reporting Invalid Javadoc Comment
-	 *    When enabled, the compiler will issue an error or a warning when a javadoc comment is inconsistent,
-	 *    misses a tag entry or contains invalid references.
-	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadoc"
-	 *     - possible values:   { "error", "warning", "ignore" }
-	 *     - default:           "ignore"
-	 * COMPILER / Reporting Missing Javadoc Comment
-	 *    When enabled, the compiler will signal cases where public class, interface, method, constructor or field
-	 *    (considered as part of the API) has no javadoc comment.
-	 *    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.invalidJavadoc".
-	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadoc"
-	 *     - possible values:   { "enabled", "disabled" }
-	 *     - default:           "disabled"
-</pre>
-Note that backward compatibility with previous options IDs: <code>"org.eclipse.jdt.core.compiler.problem.invalidAnnotation"</code> and <code>"org.eclipse.jdt.core.compiler.problem.missingAnnotation"</code>
-will be supported until 3.0M6 build and removed after.
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46717">46717</a>
-The code formatter does not insert a new line before /** Javadoc
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45958">45958</a>
-Compiler wrongly complains against valid @see constructor reference
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45112">45112</a>
-Use Javadoc instead of Annotation for comment compiler parsing
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46052">46052</a>
-result of ITypeHierarchy.getAllSuperTypes() does not include Object 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46192">46192</a>
-ILocalVariable.exists() always returns false 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=14103">14103</a>
-[Builder] Too many dependents found when incrementally recompiling
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39601">39601</a>
-[DOM/AST] clarify documentation of source ranges
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39739">39739</a>
-[DOM/AST] VariableDeclarationStatements aren't full statements
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46690">46690</a>
-Code formatter always inserts space after comma in multiple locals or field declarations
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46689">46689</a>
-Code formatter always inserts a space in front of the '-' unary operator
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46686">46686</a>
-Code formatter doesn't indent properly statements following a switch statement
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46356">46356</a>
-[Builder] simple/qualified names list for indicting dependents should be hashed collections
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46612">46612</a>
-[DOM/AST] BodyDeclaration should provide a method getModifiers
-
-<a name="v_382"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M5 Build - 10th November 2003
-<br>Project org.eclipse.jdt.core v_382
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_382">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46276">46276</a>
-Search for package declarations incorrectly finds matches in clone project
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46099">46099</a>
-Batch compiler doesn't print stats if errors and not proceeding on errors
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40950">40950</a>
-[infrastructure] NPE from indexer
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46150">46150</a>
-formatter failed to format
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46013">46013</a>
-IBinding.getKey() for local shouldn't return null 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46033">46033</a>
-New formatter not formatting nested constructor/methods properly
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46093">46093</a>
-[Builder] Unoptimal pre-check for not writing class files
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45847">45847</a>
-[Builder] Reading build state is slow
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45982">45982</a>
-Array out of bounds error while editing Java file
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41611">41611</a>
-CreateCompilationUnitOperation.executeOperation() should probably force creation more agressively 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45113">45113</a>
-No hierarchy refresh when on region 
-
-
-<a name="v_381"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M5 Build - 4th November 2003
-<br>Project org.eclipse.jdt.core v_381
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_381">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45968">45968</a>
-[new formatter] Formatter introduces empty lines inside line comments
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44450">44450</a>
-Strange name range for anonymous classes. 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43139">43139</a>
-Delete member in Outliner not working 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45944">45944</a>
-Stack trace attempting to find markers on a closed project 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44884">44884</a>
-Wrong list displayed while code completion 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45661">45661</a>
-Search for references of default package fails
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45671">45671</a>
-Need source range and getTypeSignature() for local variables 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45575">45575</a>
-Failure in nightly build of formatter tests (test325)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45783">45783</a>
-NPE in MatchLocator
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22073">22073</a>
-Each "format" adds one more level of indentation.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23709">23709</a>
-for (/*comment*/; causes indentation to misbehave 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27249">27249</a>
-incorrect formatting of empty array initialization blocks 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29473">29473</a>
-wrong formatting of if...try... catch... else 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45786">45786</a>
-No selection on method declaration in field initializer 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45721">45721</a>
-Getting wrong deltas 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45674">45674</a>
-Compiler should allow compound assignment to final in unreachable code
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43984">43984</a>
-NPE in background search
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45707">45707</a>
-Autobuild does not kick in when using classpath containers
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45655">45655</a>
-exception while editing java file 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42287">42287</a>
-Should consider qualified name token positions
-
-<a name="v_380"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M5 Build - 28th October 2003
-<br>Project org.eclipse.jdt.core v_380
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_380">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Search is now able to find local variable references and declarations. In order to trigger such a search, the search engine must
-	be fed with an <code>ILocalVariable</code> element. Searching a local variable by its name is not supported.
-</li>
-<li>Search is now finding references in Javadoc comments. Found references are method parameters declared in <code>@param</code> tags, 
-	types of exceptions declared in <code>@throws</code>/<code>@exception</code> tags and all instance variables, methods, types or 
-	packages declared in <code>@see</code> tags.
-	<br>Note that only valid references in Javadoc comments will be reported during search. In order to ensure the integrity of your Javadoc comments,
-	you may want to enable the compiler check for Javadoc (Preferences>Java>Compiler>Style>Problem in Javadoc tags).
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45641">45641</a>
-CCE when using declarations view 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45596">45596</a>
-Wrongly complains about missing parameter javadoc entry in anonymous class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45592">45592</a>
-NPE while searching a method references in jdt-core
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45520">45520</a>
-Potential NPE
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45518">45518</a>
-Search has to find references put in javadoc comments
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45436">45436</a>
-Javadoc warnings: wrong errors in AST
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45198">45198</a>
-NPE from AnnotationParser
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45459">45459</a>
-JDT compiler more restrictive than javac
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35899">35899</a>
-"hierarchy of type ... inconsistent" error message wrong
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43967">43967</a>
-Search for references on local variable finds all occurances of variables of that type not just that variable. 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37509">37509</a>
-Open Declaration opens class declaration for local variables 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45433">45433</a>
-Bug7 (and counting ;-): hundretAssignmentsToFinalVariable()
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45357">45357</a>
-Compiler-Bug: "The local variable oResult may not have been initialized".txt
-
-<a name="v_379"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M5 Build - 21st October 2003
-<br>Project org.eclipse.jdt.core v_379
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_379">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li> Compiler options for controlling the severity of problems for invalid imports or unreachable code got discontinued. Indeed, allowing this kind of problems to be ignored
-or treated as a warning would violate the language spec. As a consequence, <code>JavaCore#COMPILER_PB_INVALID_IMPORT</code> and
-<code>JavaCore#COMPILER_PB_UNREACHABLE_CODE</code> got deprecated, 
-further attempts to set these preferences are now ignored and import problems or unreachable code are always reported as errors.
-<li> The warning level of the batch compiler can now be configured more easily using <code>-warn:+...</code> or <code>-warn:-...</code> command line
-argument (as opposed to only existing <code>-warn:...</code> command line argument). 
-<code>-warn:+...</code> will not override the default warning level, but simply enable
-a few more specific warnings. Similarily, <code>-warn:-...</code> will only disable specific warnings.
-<br>Note, by default the batch compiler is reporting the following warnings:
-	<ul>
-	<li>'assert' used as identifier</li>
-	<li>char[] in String concat</li>
-	<li>method with constructor name</li>
-	<li>deprecation outside deprecated code</li>
-	<li>finally block not completing normally</li>
-	<li>interface non-inherited method compatibility</li>
-	<li>hidden catch block</li>
-	<li>assignment without effect</li>
-	<li>attempt to override package-default method</li>
-	<li>unused import declaration</li>
-	<li>non-static reference to static member</li>
-	</ul>
-</li>
-<li>Code select (i.e. <code>ICodeAssit.codeSelect(...)</code>) now returns an <code>ILocalVariable</code>
-     element when a local variable or an argument is selected. 
-     <br>Note that <code>ILocalVariable</code>s are pseudo-elements:
-     they are not part of the Java model (<code>exists()</code> always returns <code>false</code>), 
-     they are not returned when asking for the children of a method, and there is no other way to create such
-     an element. One can only ask for the source range (<code>ISourceReference.getSourceRange()</code>) or
-     for the name range (<code>ILocalVariable.getNameRange()</code>) of the local variable.
-     <br>Searching a local variable is not yet implemented, but it is on the plan.
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35389">35389</a>
-Compiler settings can violate JLS [build path]
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44869">44869</a>
-Search: no refs found to overridden method in binary subclass
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45110">45110</a>
-No constant for '..compiler.problem.missingAnnotation'
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45100">45100</a>
-[formatter] test144 fails
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45036">45036</a>
-[formatter] New formatter fails formatting multiple field declarations using K_CLASSBODY_DECLARATION kind
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45037">45037</a>
-[formatter] New formatter doesn't insert a new line before the while in a do/while
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45014">45014</a>
-Formatter misplaces semicolon
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44757">44757</a>
-New code formatter does not format switch statements correctly
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44647">44647</a>
-NPE code completion
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43754">43754</a>
-How to position this comment?
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44839">44839</a>
-New formater fails with out of memory error
-
-<a name="v_378"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M5 Build - 15th October 2003
-<br>Project org.eclipse.jdt.core v_378
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_378">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li> Removed dependency on Xerces.
-</li>
-<li> Remove deprecated previously added API <code>IJavaProject#forceClasspathReload(IProgressMonitor)</code>
-(see comment of <a href="#v_368">v_368</a> drop below).
-</li>
-<li>Added optional compiler problem to signal problems with javadoc annotation.
-<pre>
-	 * COMPILER / Reporting Invalid Javadoc Annotation
-	 *    When enabled, the compiler will issue an error or a warning when a javadoc annotation is inconsistent,
-	 *    misses a tag entry or contains invalid references.
-	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidAnnotation"
-	 *     - possible values:   { "error", "warning", "ignore" }
-	 *     - default:           "ignore"
-	 * COMPILER / Reporting Missing Javadoc Annotation
-	 *    When enabled, the compiler will signal cases where public class, interface, method, constructor or field
-	 *    (considered as part of the API) has no javadoc annotation.
-	 *    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.invalidAnnotation".
-	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingAnnotation"
-	 *     - possible values:   { "enabled", "disabled" }
-	 *     - default:           "disabled"
-	 * 
-</pre>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44715">44715</a>
-NullPointerException compiling Java file
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44697">44697</a>
-Bug when i search reference of 'String' in 3.0M4
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38091">38091</a>
-DCR - Generate warnings for JavaDoc missing entries
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44637">44637</a>
-NPE in Initializer.getPrimaryElement() 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42762">42762</a>
-Compiler tests should run both in 1.3 and 1.4 mode 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44580">44580</a>
-No outline when unit name is not valid
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44651">44651</a>
-Wrong formatting of multiple local variables declarations
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44643">44643</a>
-Remove dependancy to xerces
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44662">44662</a>
-Should not validate unit/classfile handles upon creation
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44400">44400</a>
-Unnecessary cast not being picked up
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44143">44143</a>
-[JSR202] Remove usage of jsr bytecodes in 1.5 mode
-
-<a name="v_377"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M4 Build - 9th October 2003 - 3.0 MILESTONE-4
-<br>Project org.eclipse.jdt.core v_377
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_377">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44576">44576</a>
-Code formatter option "Insert a new line before an opening brace" has no effect for single else
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44570">44570</a>
-Code formatter option "Insert a new line inside an empty block" has no effect
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44503">44503</a>
-Unoptimal formatting for long constructor argument
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44546">44546</a>
-New formatter unable to format
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44506">44506</a>
-Type hierarchy is missing anonymous type
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44481">44481</a>
-"Insert new line between else and if" is not working as expected
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44480">44480</a>
-Formatting the formatted string should not produce edits
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44444">44444</a>
-jdt.core in trouble when project has no JRE
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44437">44437</a>
-Typo in plugin.properties
-
-<a name="v_376"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M4 Build - 8th October 2003
-<br>Project org.eclipse.jdt.core v_376
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_376">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Fix for bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44289">44289</a>
-     requires the index format to be changed. Indexes will be automatically regenerated upon
+<li>Fix for bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69028">69028</a>
+     requires the index version to be incremented. Indexes will be automatically regenerated upon
      subsequent search queries (accounting for indexing notification in search progress dialogs).
 </li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44308">44308</a>
-NullPointerException when searching jars
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44341">44341</a>
-NPE from  delta processor
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44119">44119</a>
-NPE while searching for references to Action#run() 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44331">44331</a>
-Need indication that removal/add was targeted to a primary working copy 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32639">32639</a>
-Missing empty fine-grain delta when reconciling 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44292">44292</a>
-IDOMType.setFlags(Flag.AccPublic) when applied to an interface having default visibility produces uncompilable code
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44293">44293</a>
-DOMFactory.createInitializer() always creates a static intializer
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44289">44289</a>
-Search broken 
-
-<a name="v_374"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M4 Build - 7th October 2003
-<br>Project org.eclipse.jdt.core v_374
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_374">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>The new code formatter can be activated in the ui. See the work in progress section. This first release doesn't expose
-yet all the preferences of the new code formatter. This will be done after M4. However the old formatter options should be honored by 
-the new code formatter. This is a work in progress and all problems should be reported against JDT/Core.
+<li>The spec for MethodDeclaration.typeParameters was changed to remove the
+clause that said that type parameters were not meaningful for
+constructors. According to the latest JLS3, both constructors and methods
+are allowed to have type parameters.
+(bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70665">70665</a>).
 </li>
 </ul>
 
 <h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44242">44242</a>
-Deadlock during jdt/debug test 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44066">44066</a>
-Package Explorer doesn't show new file 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44219">44219</a>
-NPE while creating TypeHierarchy for binary type "Group" 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44073">44073</a>
-Override methods action does not work for local types [code manipulation] 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=16231">16231</a>
-formatter creates ugly array initializer expressions
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=6284">6284</a>
-Java formatter enhancements
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=6268">6268</a>
-Code formatting
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44036">44036</a>
-Java code formatter wraps line too much.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43651">43651</a>
-Linewrapping of throws declarations (if many)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43545">43545</a>
-Code Formatter: Don't separate long "import" clause.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43272">43272</a>
-feature request : extend the code formatter to support blanks between method / class name and bracket.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43050">43050</a>
-Formatting long arguments not very readable
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40777">40777</a>
-Incorrect formatting for anonymous inner class with comment
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39607">39607</a>
-Incorrect formatting of anonymous inner class inside if statement
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39603">39603</a>
-for-Statement not correctly formatted by Codeformatter
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39357">39357</a>
-Better code formatting
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38151">38151</a>
-Code formatter adds an unwanted blank line after an abstract method with a "throws" clause.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37106">37106</a>
-Code Formatter: Option to double indent wrapped lines in if statments, etc.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37057">37057</a>
-Code Formatter: Reduce number of blank lines to 1
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36832">36832</a>
-wrong indent on Code Format of anonymous class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36455">36455</a>
-[Formatting] Too long lines look ugly
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36108">36108</a>
-Code Formatter Clear Blank Lines Doesn't Work
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35799">35799</a>
-code formatter: missing space after last array initializer
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35433">35433</a>
-Simple Feature Request - Code Formatter Enhancement
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35173">35173</a>
-Code formatter incorrectly formats this case:
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29110">29110</a>
-RFE: Disable line splitting in the code formatter
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28098">28098</a>
-Code Formatter doesn't format JavaDoc indentation
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27196">27196</a>
-Code Formatter Won't Indent Braces
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25559">25559</a>
-more code formatter options
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24200">24200</a>
-"Space inside parens & brackets" option in Code Formatter
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23144">23144</a>
-formatter issues
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22528">22528</a>
-Code formatter incorrectly indents lines
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22313">22313</a>
-Formatter doesn't like some comment
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21943">21943</a>
-Formatter should allow removing space after for/while/if
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20721">20721</a>
-Code formatter bug
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=19999">19999</a>
-Code Formatter always clears blank lines to 1
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=19811">19811</a>
-Code formatter bugs
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=17349">17349</a>
-Code Formatter incorrectly formats static initializer
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=16233">16233</a>
-formatter problem with constructor, array and line-end comments
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=15286">15286</a>
-Code formatter: long param lists and line wrapping
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=14659">14659</a>
-Align method arguments on line break
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=12456">12456</a>
-Add formatter options for controlling spaces
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=12321">12321</a>
-Code formatter and comments
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=10052">10052</a>
-CodeFormatter - line splitting enhancement.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=7439">7439</a>
-incorrect formatting: empty inner class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=7224">7224</a>
-Formatting splits package names in ugly ways
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=6747">6747</a>
-Code Formatter exchange several blank lines w/ one
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=5824">5824</a>
-Code Formatter needs to be more customizable to be useful
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3327">3327</a>
-Formatter - should ensure one empty line before a method declaration (1GHOJWD)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3276">3276</a>
-DCR: (LOW) Formatter option to not indent methods (1GE39ZO)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3181">3181</a>
-Does not format nicely anonymous type (1FRLTO1)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44085">44085</a>
-becomeWorkingCopy() should add the working copy in the model 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44052">44052</a>
-Deadlock on startup
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44092">44092</a>
-Methods to generate parser files are not correct 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44084">44084</a>
-No refresh when deleting edited unit 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41643">41643</a>
-Code assist doesn't propose all valid types
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44065">44065</a>
-NPE during hot code replace 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43897">43897</a>
-No completion in cast expression
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44061">44061</a>
-CodeAssist - no completion after class literal access
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44018">44018</a>
-Change superfluous semicolon error message
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43872">43872</a>
-Hierarchy does not update properly when local class eliminated [type hierarchy] 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43294">43294</a>
-Primary working copy: No updates when changed in working copy mode 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43907">43907</a>
-Too many warnings reported by the jdt compiler adapter
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43847">43847</a>
-IPackageFragment not updated after CUs have moved 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43879">43879</a>
-working copy commit outside classpath doesn't save buffer
-
-<a name="v_373"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M4 Build - 30th September 2003
-<br>Project org.eclipse.jdt.core v_373
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_373">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43728">43728</a>
-Optimize CompilerOptions(Map....)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43842">43842</a>
-JDTCompilerAdapter doesn't find bootclasspath 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40782">40782</a>
-Primary working copies: unnecessary deltas on save 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43300">43300</a>
-SearchEngine(IWorkingCopy[] workingCopies) not backward compatible 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43670">43670</a>
-No classpath refresh when replacing binary project with source form
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43600">43600</a>
-NPE from JDTCompilerAdapter
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43636">43636</a>
-Compiler complain that class cannot be resolved when it should be only not visible
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43208">43208</a>
-ICompilation.move not supported when in workingCopyMode 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40793">40793</a>
-Primary working copies: Type search does not find type in modified CU 
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48336">48336</a>
+[Search] Participants should surface in search progress
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70598">70598</a>
+[Encoding] ArrayIndexOutOfBoundsException while testing BOM on *.txt files
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70767">70767</a>
+[1.5] NPE compiling code with explicit constructor invocation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70717">70717</a>
+Batch compiler should report compilation errors to console
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70665">70665</a>
+[DOM/AST] missing type parameters for constructor declaration in JLS3
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70618">70618</a>
+[1.5] Variable T should be allowed as argument of supertype
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70616">70616</a>
+[1.5] Unable to bind type variable in binary from Enum&lt;E&gt;
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70609">70609</a>
+[1.5] NPE compiling Container
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70606">70606</a>
+[1.5] ClassCastException compiling DefaultTreeCellEditor
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69351">69351</a>
+[1.5] Error should be issued if generic type is extending Throwable
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62822">62822</a>
+[1.5] Bound mismatch: The type X is not a valid substitute for the bounded parameter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69626">69626</a>
+[1.5] The return type is incompatible
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41018">41018</a>
+Method reference with member type parameter(s) not found
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70053">70053</a>
+[1.5] VerifyError - incompatible argument to function
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69942">69942</a>
+compiler warning for serializable classes that do not explicitly declare serialVersionUID
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70398">70398</a>
+Java AST creation error due to NullPointerException in IF statement test block.
 <br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43587">43587</a>
 Searching for references to default constructors reports questionable results
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36143">36143</a>
-Type hierarchy doesn't include anonymous subclasses 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=8613">8613</a>
-Outline should show anonymous inner classes 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70243">70243</a>
+[1.5] no warning for unsafe cast
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69799">69799</a>
+[1.5] NPE when saving File with forEach loop
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69320">69320</a>
+[1.5] generic parameter type compiles by eclipse, not by javac
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69800">69800</a>
+[1.5] eclipse fails to report incompatible types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70295">70295</a>
+[1.5] method(Class<?>) is not applicable for Class<? extends Object>
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=70247">70247</a>
+[1.5] NPE in TypeVariableBinding
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68726">68726</a>
+[Javadoc] Target attribute in @see link triggers warning
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68993">68993</a>
+IllegalArgumentException when opening project preferences
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69806">69806</a>
+formatter doesn't handle strictfp correctly.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69776">69776</a>
+[1.5] VerifyError: Incompatible object argument for function call
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69713">69713</a>
+[1.5] Cannot save java document, throws nullpointer
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69542">69542</a>
+[1.5] ByteCode differs from javac ByteCode in behaviour
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69554">69554</a>
+Eclipse Java compiler is not completely compliant to Javac
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69658">69658</a>
+typo in javadoc of ClassInstanceCreation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69308">69308</a>
+All ASTNodes that deal with modifiers should offer a method setModifiers(List modifiers)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69302">69302</a>
+[Javadoc] Invalid reference warning inconsistent with javadoc tool
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69275">69275</a>
+[Javadoc] Invalid warning on @see link
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69272">69272</a>
+[Javadoc] Invalid malformed reference (missing separator)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68087">68087</a>
+[Javadoc] '-' character should be accepted in tag names
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68025">68025</a>
+Javadoc processing does not detect some wrong links
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68017">68017</a>
+Javadoc processing does not detect missing argument to @return
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69573">69573</a>
+[1.5] Missing Message for Compiler
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69028">69028</a>
+Anonymous type in argument of super() is not in type hierarchy 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69375">69375</a>
+[1.5] wildcards: no error for incorrect assignment
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68698">68698</a>
+Bug in inner class emulation:compiler doesn't reject illegal code.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69359">69359</a>
+[1.5] Trouble with "unnecassary cast" warnings
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69271">69271</a>
+decimal integer literals should not consist of FULL WIDTH Unicode digits
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69349">69349</a>
+[DOM/AST] Wrong end position for method declaration
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69152">69152</a>
+[NPE] An internal error occurred during: "Override indicator installation job". 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68010">68010</a>
+[1.5] Return type of bridge method is not correct inside outliner 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69170">69170</a>
+[1.5] no error for new T[0]
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69353">69353</a>
+[1.5] Should reject usage of type parameter in catch block
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69288">69288</a>
+[1.5] Unsafe type operations should be reported against individual expressions
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64305">64305</a>
+[1.5] Bad "return type is incompatible" error for array values
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69251">69251</a>
+[1.5] can't instantiate bounded wildcard
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69141">69141</a>
+[1.5] Wildcards with lower bound do not work
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=69276">69276</a>
+[1.5] NPE in ReturnStatement
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64154">64154</a>
+[1.5] incorrect 'constructor not visible'
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65943">65943</a>
+Closing/opening a project doesn't have the correct delta 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68998">68998</a>
+[1.5] NPE in java compiler
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68146">68146</a>
+Search should not populate Java model cache 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=67789">67789</a>
+Java element delta from refresh contains excluded package 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68845">68845</a>
+[1.5] AST: AbstractTypeDeclaration should have resolveBinding
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66512">66512</a>
+Invalid classpath entry not rejected 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=67643">67643</a>
+[1.5] Incompatible conditional operand types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68981">68981</a>
+[1.5] NPE in code assist
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68891">68891</a>
+[1.5] TypeVariableBinding does not know his declaring type or method
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68862">68862</a>
+[1.5] ClassCastException when moving a a java file 
 
-
-<a name="v_372"></a>
+<a name="v_500"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0M4 Build - 24th September 2003
-<br>Project org.eclipse.jdt.core v_372
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_372">cvs</a>).
+Eclipse SDK 3.1M1 - 29th June 2004 - Codename "Cheetah"
+<br>Project org.eclipse.jdt.core v_500 (Cheetah06)
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_500">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
+<li>From target 1.5 on, the JSR bytecode instruction is no longer generated. As a consequence, the 
+    corresponding compiler option status will be ignored as soon as -target 1.5 is specified.
+</li>
+<li>Batch compiler defaults to 1.5 source and target, when toggled in 1.5 compliant mode ("-1.5").
+</li>
+<li>Added support for generics to JavaModel, thus enabling editor problem reconciling, outliner, type hierarchies. </li>
+<li>Improved codeassist and codeselect handling of generics </li>
 </ul>
 
 <h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42692">42692</a>
-JavaCC files cause VerifyError when compiled with Eclipse
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43437">43437</a>
-Scanner does not like string literals
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43485">43485</a>
-NPE in SearchEngine
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37659">37659</a>
-[plan item] Improve shared working copies 
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68837">68837</a>
+[1.5] AST: Missing source range in parameterized type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68133">68133</a>
+[1.5] VerifyError: Code segment has wrong length in class file
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68863">68863</a>
+Missing entry in local variable attribute
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68440">68440</a>
+[1.5] VerifyError with new for loop
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64159">64159</a>
+[1.5] call to addAll(Collection<? extends T>) incorrectly dissalowed
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68602">68602</a>
+[1.5] AST converter fails on local types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66424">66424</a>
+[1.5] Collections in new style for loop
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64417">64417</a>
+[1.5] NPE in SourceTypeBinding.resolveTypesFor
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68730">68730</a>
+[1.5] No completion
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65953">65953</a>
+[1.5] Internal Compiler Error: ArrayIndexOutOfBoundsException
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58470">58470</a>
+[1.5] Source mapper fooled by generics 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64336">64336</a>
+[1.5] Signature does allow to create parameterized type signatures
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68557">68557</a>
+[1.5] ArrayIndexOutOfBoundsException in SourceTypeConverter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=68006">68006</a>
+[1.5] Invalid modifier after parse
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65503">65503</a>
+[1.5] "new" for-loop inside "old" for-loop gives error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65870">65870</a>
+[1.5] AST creation fails when created with comments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64301">64301</a>
+[1.5] Cast required where no cast should be required
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63556">63556</a>
+[1.5] Error when creating generic classes specializing distant generic parameters
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63590">63590</a>
+[1.5] Cheetah allows generic throws clause
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63555">63555</a>
+[1.5] Cannot put generic type fields inside static inner class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58722">58722</a>
+[1.5] cannot extend interfaces
 
 
-<a name="v_371"></a>
+<a name="v_429_Cheetah05"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0M4 Build - 22nd September 2003
-<br>Project org.eclipse.jdt.core v_371
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_371">cvs</a>).
+Eclipse Platform Build Notes&nbsp;<br>
+Eclipse SDK 3.1M1 - 15th May 2004
+<br>Project org.eclipse.jdt.core v_429_Cheetah05
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_429_Cheetah05">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
-<li> As a consequence of migrating to background autobuild, the JavaModel will no longer broadcast deltas
-during PRE_AUTO_BUILD event notification. These were somewhat inconsistent in so far as the model wasn't
-totally up to date anyway. Now the model will only fire deltas during POST_CHANGE, or working copy reconcile
-operations.
+<li>
+Cast/instanceof operations are now fully supported, along with extra diagnosis for unsafe type operations.
 </li>
-<li>Part of the new support for local and anonymous types in the Java model has been released. 
-	<p>
-	This includes:
-	<ul>
-	<li>local and anonymous types are shown in the Outline view and the Package Explorer view</li>
-	<li>Java element deltas for these types are notified</li>
-	<li>handles on these types can be created (see <code>IMember.getType(String, int)</code>)</li>
-	<li><code>getChildren()</code> on a method, a field or an initializer returns the local or anonymous types defined in this element</li>
-	<li>mementos for these handles are supported</li>
-	<li>open on selection (F3) in a Java editor goes to the local type definition</li>
-	<li>type hierarchies contain anonymous and local types</li>
-	</ul>
-	<p>
-	This doesn't yet include:
-	<ul>
-	<li>search on these types</li>
-	<li>anonymous/local binary types</li>
-	</ul>
+<li>
+Explicit parameterizations of message sends and constructor calls are also supported.
 </li>
 </ul>
 
 <h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42832">42832</a>
-Cannot get rid of this error even if the compiler settings is ignore for incompatible required binaries
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41583">41583</a>
-[misc] Eclipse cannot save or compile files in non-Java project anymore
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43274">43274</a>
-Type hierarchy broken 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38931">38931</a>
-Migrate delta processor to comply to new notification scheme in 3.0
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42281">42281</a>
-"Resource *.java does not exist"
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38931">38931</a>
-org.eclipse.jdt.internal.corext.dom.NodeFinder needed in API 
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62416">62416</a>
+[1.5] An error has occurred when creating this (Java) editor
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62292">62292</a>
+[1.5] Missing receiver in parameterized message send
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61507">61507</a>
+[1.5] NPE in computeCompatibleMethod
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60681">60681</a>
+[1.5] Return type not strict enough
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60563">60563</a>
+[1.5] VerifyError when using generics and arrays
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59258">59258</a>
+Possibility to share compiler preferences for a shared project
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60556">60556</a>
+[1.5] Collections.unmodifiableList(List&lt;A&gt;)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58978">58978</a>
+[1.5] Generic method needs better error reporting
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59983">59983</a>
+[1.5] Internal compiler error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58903">58903</a>
+[1.5] Implementing inherited generic methods
 
 
-<a name="v_370"></a>
+<a name="v_422_Cheetah04"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0M4 Build - 16th September 2003
-<br>Project org.eclipse.jdt.core v_370 
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_370">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43026">43026</a>
-Running jdt/core tests on Linux is failing
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43045">43045</a>
-Copy/move of package fragments with read-only subpackages fails on Linux
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43116">43116</a>
-NPE copy and pasting a method
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43089">43089</a>
-Search engine doesn't report all matches
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43080">43080</a>
-NPE when searching in CU with incomplete method declaration 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42856">42856</a>
-CodeAssist - Does not work after an inner type reference
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42839">42839</a>
-Incorrect position in org.eclipse.jdt.core.dom.ArrayType
-
-<a name="v_369"></a>
-<p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M4 Build - 9th September 2003
-<br>Project org.eclipse.jdt.core v_369 
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_369">cvs</a>).
+Eclipse SDK 3.1M1 - 23th April 2004
+<br>Project org.eclipse.jdt.core v_422_Cheetah04
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_422_Cheetah04">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
-<li>Default compiler compliance setting got raised to 1.4 level. Default source level is 1.3, and default target level is 1.2.
-To ease the 1.4 migration, the default severity for optional problem 'assert used as identifier' got raised to warning.
+<li>
+Wildcard type compatibilities got reworked quite significantly. In
+particular, it now diagnoses
+usage of methods which parameters are of wildcard type (see 59641).
+</li>
+<li>
+Covariance is still not supported, but the Cheetah can now issue synthetic
+bridge methods for allowing overriding to parameterized methods.
 </li>
 </ul>
 
 <h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42760">42760</a>
-NullPointerException in JobManager when searching 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42629">42629</a>
-javac error message with missing classpath entry when claims entry dropped from path 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42614">42614</a>
-1.3 compliant mode should select default enclosing instance
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42588">42588</a>
-Incorrect selection of current enclosing instance
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35567">35567</a>
-Classpath validation error messages should contain project name
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42443">42443</a>
-Error when inner class name has the same name than another class, but with not the same case sensitive
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42459">42459</a>
-DebugEvaluationTests don't run if target is 1.2
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39887">39887</a>
-Resource exception while indexing
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42366">42366</a>
-Classpath validation error message removed while rebuilding a project.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41680">41680</a>
-Unnecessary cast  wrongly reported
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59723">59723</a>
+[1.5] Compiler rejects usage of ArrayList.toArray(char[][])
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59628">59628</a>
+[1.5] Erroneous diagnosis for missing abstract method implementation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59641">59641</a>
+[1.5] Compiler should refuse usage of wildcard argument values
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59147">59147</a>
+[1.5] Compiler rejects correct code with wildcards and raw types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58979">58979</a>
+[1.5] NullPointerException in compiler
 
-<a name="v_368"></a>
+
+<a name="v_421_Cheetah03"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.0M4 Build - 1st September 2003
-<br>Project org.eclipse.jdt.core v_368 
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_368">cvs</a>).
+Eclipse Platform Build Notes&nbsp;<br>
+Eclipse SDK 3.1M1 - 16th April 2004
+<br>Project org.eclipse.jdt.core v_421_Cheetah03
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_421_Cheetah03">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
-<li>Added optional compiler problem to signal unqualified access to a non-static field. In order to improve
-code readability, qualifying field accesses is a simple way to syntactically distinguish a field access from 
-a local variable access, and thus avoid resorting to a special naming convention for fields (such as "fField").
+<li>
+The Cheetah is now able to digest generic methods and perform type inference.
+It also recognizes the Object.getClass() method and perform adequate
+substitutions (see <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57784">57784</a>).
+</li>
+<li>
+Generic types completion is available and type parameters are proposed
+as possible completions.
+Currently type parameter proposals are given by
+ICompletionRequestor#acceptClass().
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58715">58715</a>
+[1.5] The return type is incompatible
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58631">58631</a>
+[1.5] Cycle in hierarchy no longer detected
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58666">58666</a>
+[1.5] Object.getClass() need to be treated special ?
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57784">57784</a>
+[1.5] Errors using Arrays.asList(T [])
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58461">58461</a>
+[1.5] java.lang.VerifyError from enhanced for loop
+
+
+<a name="v_421_Cheetah02"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Eclipse SDK 3.1M1 - 13th April 2004
+<br>Project org.eclipse.jdt.core v_421_Cheetah02
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_421_Cheetah02">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>
+Properly decode signatures of parameterized member types which are flourishing in 1.5 class libs,
+ and were reported as bogus inconsistencies with Cheetah01.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53036">53036</a>
+Incorrect highlighting for type problem in qualified type name
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57716">57716</a>
+[1.5] NPE compiling SelectionParser in source 1.5
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57397">57397</a>
+[1.5] Unable to save unit
+
+<a name="v_420_Cheetah01"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Eclipse SDK 3.1M1 - 4th April 2004
+<br>Project org.eclipse.jdt.core v_420_Cheetah01
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_420_Cheetah01">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> JDK 1.5 support.
+<li> JavaCore 1.5 specific options. Either augmented to consider 1.5 or added.
 <pre>
-* COMPILER / Reporting Unqualified Access to Field
-*    When enabled, the compiler will issue an error or a warning when a field is access without any qualification.
-*    In order to improve code readability, it should be qualified, e.g. 'x' should rather be written 'this.x'.
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess"
-*     - possible values:   { "error", "warning", "ignore" }
-*     - default:           "ignore"
-</pre>
-</li>
-<li>Added optional compiler problem to signal method/constructor declared thrown checked exception which
-aren't actually raised inside the method/constructor body.
-<pre>
-* COMPILER / Reporting Unused Declared Thrown Exception
-*    When enabled, the compiler will issue an error or a warning when a method or a constructor is declaring a
-*    thrown checked exception, but never actually raises it in its body.
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException"
-*     - possible values:   { "error", "warning", "ignore" }
-*     - default:           "ignore"
-</pre>
-</li>
-<li>Added optional compiler problem to flag situations where a finally block does not complete normally.
-<pre>
-* COMPILER / Reporting Finally Blocks Not Completing Normally
-*    When enabled, the compiler will issue an error or a warning when a finally block does not complete normally.
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally"
-*     - possible values:   { "error", "warning", "ignore" }
-*     - default:           "warning"
-</pre>
-</li>
-<li>Improved problem description for unreachable catch block problems. Message will now mention the exception type 
-name and better diagnose the cause of the problem. Also changed problem source range 
-to rather highlight the caught exception type instead of entire catch block. 
-<pre></pre>
-</li>
-<li>Added two new API methods <code>readRawClasspath()</code> and <code>readOutputLocation()</code> on <code>IJavaProject</code>
-interface so as to allow user to read classpath directly from disk (<code>.classpath</code> file contents). This is useful to configure
-a Java project before it is associated with the Java nature, or before the automatic classpath reconciliation mechanism has performed (within
-a resource modifying operation, and prior to the change notification). Note that these API additions are obsoleting the previously
-added API <code>IJavaProject#forceClasspathReload(IProgressMonitor)</code> (also see bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20931">20931</a>)
-which has thus been deprecated. Forcing the classpath reload can simply be achieved by: <code>p.setRawClasspath(p.readRawClasspath(), p.readOutputLocation(), ...)</code>.
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40383">40383</a>
-Search - should only special treat unsaved working copies 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40658">40658</a>
-IJavaProject.getOutputLocation/getRawClasspath require Java nature
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42196">42196</a>
-Method popup extremely slow for JOGL code 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41534">41534</a>
-incorrect shadowing reported by rename [refactoring] 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40937">40937</a>
-ISourceReference.getSource throws ArrayIndexOutOfBoundsException 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41373">41373</a>
-SourceField.getConstant() returns null for final fields set in initializer
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41604">41604</a>
-Possible Compiler Bug 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22976">22976</a>
-DCR - warning for unused declarations of thrown exceptions
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40736">40736</a>
-JDT compiler fails to compile legitimate Java code.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40020">40020</a>
-Exceptions in console 
-
-<a name="v_367"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M3 Build - 22nd August 2003 - 3.0 MILESTONE-3
-<br>Project org.eclipse.jdt.core v_367
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_367">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40464">40464</a>
-Index states not saved
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41805">41805</a>
-ArrayIndexOutOfBoundsException while creating AST
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39831">39831</a>
-Search finds only "inexact" matches 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35980">35980</a>
-illegal code completion suggested (abstract methods) 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40779">40779</a>
-Primary working copies: no deltas on destroy 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36271">36271</a>
-CodeAssist should treat array.clone() as visible
-<br<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40681">40681</a>
-no warnings for some externalized strings
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40584">40584</a>
-Test suite configuration should be more flexible
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41674">41674</a>
-ToolFactory.createDefaultClassFileReader does not close zipfile
-	  	
-<a name="v_366"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M3 Build - 19th August 2003
-<br>Project org.eclipse.jdt.core v_366 
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_366">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>In 1.4 mode, the compiler is now JCK 1.4a compliant (previously was passing JCK1.4).
-</li>
-<li>To reduce the memory consumption and improve performance, the following new APIs were added:
-<ul>
-<li>AST.parsePartialCompilationUnit(ICompilationUnit unit, int position, boolean resolveBindings)</li>
-<li>AST.parsePartialCompilationUnit(ICompilationUnit unit, int position, boolean resolveBindings, WorkingCopyOwner owner)</li>
-</ul>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41602">41602</a>
-missing @exception in javadoc of IPackageFragment.getNonJavaResources 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38635">38635</a>
-Refactor / Rename Package doesn't allow rename to same name with different case [refactoring]
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40476">40476</a>
-refactor change method signature reports erroneous non-constant case statements
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40995">40995</a>
-NPE in ast.ExplicitConstructorCall.analyseCode
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40880">40880</a>
-Wrong error range for 'indirect static access'
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40174">40174</a>
-Performance issues with builder
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39108">39108</a>
-Numerous single type imports can slow compiler down significantly
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41019">41019</a>
-org.eclipse.jdt.core.Signature cannot resolve complex type that has package name starting with letters as any primitive type
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38633">38633</a>
-Search should not open requested types with match locator parser
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40954">40954</a>
-ArrayIndexOutOfBoundsException during sort members
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40804">40804</a>
-NPE in MethodBinding.sourceMethod()
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40474">40474</a>
-DOM/AST: Add API to parse only part of a compilation
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40839">40839</a>
-Deprecation is reported even if there is an empty member declaration prior to the field declaration
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40606">40606</a>
-Unable to discard empty package if containing .class files 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39174">39174</a>
-NPE in type hierarchy when opening type 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40082">40082</a>
-NPE in TypeHierarchy.packageRegionContainsSamePackageFragment(TypeHierarchy.java:1314) 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40090">40090</a>
-No need to close Java model on shutdown 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42589">42589</a>
-jck1.4a failures
-
-<a name="v_365a"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M3 Build - 24th July 2003
-<br>Project org.eclipse.jdt.core v_365a 
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_365a">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40752">40752</a>
-internal compiler error: java.lang.ClassCastException: org.eclipse.jdt.internal.compiler.lookup.ArrayBinding
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40594">40594</a>
-wrong location set for org.apache.ant when building jdt component with baseLocation
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40715">40715</a>
-getWorkingCopy(...) should always return a new working copy for primary cus 
-
-<a name="v_365"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M3 Build - 22nd July 2003
-<br>Project org.eclipse.jdt.core v_365 
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_365">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li> Added optional diagnosis for undocumented empty blocks
-<pre>
-* COMPILER / Reporting Undocumented Empty Block
-*    When enabled, the compiler will issue an error or a warning when an empty block is detected and it is not
-*    documented with any comment.
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock"
-*     - possible values:   { "error", "warning", "ignore" }
-*     - default:           "ignore"
-</pre>
-</li>
-<li> Removed optional diagnosis for boolean methods throwing exception, since it proved to be useless as is.
-</li>
-<li>Fix for bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40116">40116</a>
-     requires the index format to be changed. Indexes will be automatically regenerated upon
-     subsequent search queries (accounting for indexing notification in search progress dialogs).
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40382">40382</a>
-JavaModelException#printStackTrace should be improved 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40572">40572</a>
-Unnecessary cast warning for necessary cast
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40322">40322</a>
-Error creating new Java projects 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40421">40421</a>
-Unnecessary cast warning...true but...
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32285">32285</a>
-DCR - extra java compiler markers
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40514">40514</a>
-ArrayIndexOutOfBoundsException during detection of unnecessary casts
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40442">40442</a>
-Abstract class fails to invoke interface-defined method in 1.4 compliance mode.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40116">40116</a>
-Search for references to nested class doesn't find anything 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40334">40334</a>
-Model should be more tolerant for possible compiler failures
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36479">36479</a>
-Rename operation during refactoring fails 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39865">39865</a>
-Misleading error diagnosis on broken method signatures
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=12800">12800</a>
-suboptimal error messages on mistyped 'throw/throws' keywords 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38568">38568</a>
-Search for method declarations fooled by array types 
-
-<a name="v_364b"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M2 Build - 18th July 2003 - 3.0 MILESTONE-2
-<br>Project org.eclipse.jdt.core v_364b 
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_364b">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40495">40495</a>
-VerifyError with return statements containing a cast expression
-
-<a name="v_364a"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M2 Build - 17th July 2003
-<br>Project org.eclipse.jdt.core v_364a 
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_364a">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40423">40423</a>
-NPE Saving a file
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40288">40288</a>
-NPE while building
-
-<a name="v_364"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M2 Build - 16th July 2003
-<br>Project org.eclipse.jdt.core v_364 
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_364">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40210">40210</a>
-ICompilationUnit#isWorkingCopy() misbehaving for discarded working copies
-
-<a name="v_363"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M2 Build - 15th July 2003
-<br>Project org.eclipse.jdt.core v_363 
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_363">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Added flag <code>IJavaElementDelta.F_PRIMARY_WORKING_COPY</code> that signals that a compilation unit has become a
-     primary working copy, or that a primary working copy has reverted to a compilation unit (i.e. primary working copies are not notified
-     as being added/removed like other working copies, since the primary unit is only changing mode, also see bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40028">40028</a>).
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40028">40028</a>
-Deltas and deleted working copies 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39823">39823</a>
-AST: Would like to have binding of Serializable and Clonable
-	  	
-<a name="v_362"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M2 Build - 14th July 2003 
-<br>Project org.eclipse.jdt.core v_362
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_362">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li> Added optional diagnosis for unnecessary cast or instanceof operations (matching problem IDs are
-<code>IProblem.UnnecessaryCast</code>, <code>IProblem.UnnecessaryArgumentCast</code>, <code>IProblem.UnnecessaryInstanceof</code>).
-<pre>
-* COMPILER / Reporting Unnecessary Type Check
-*    When enabled, the compiler will issue an error or a warning when a cast or an instanceof operation 
-*    is unnecessary.
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck"
-*     - possible values:   { "error", "warning", "ignore" }
-*     - default:           "ignore"
-</pre>	 
-</li>
-<li> Changed Java element delta processing to be thread-safe.
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39926">39926</a>
-deleting default package (not in source folder) does nothing 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39877">39877</a>
-Rebuild All generates extra "Unable to read classpath" entry. 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39925">39925</a>
-Unnecessary instanceof checking leads to a NullPointerException
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35442">35442</a>
-flag unnecessary casts
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39841">39841</a>
-Give better explanation of why abstract class can't be instantiated
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39467">39467</a>
-Classes not implementing abstract methods compile without error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39763">39763</a>
-Non NLS string is reported and it should not
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39779">39779</a>
-End position of IType exceeds the size of CompilationUnit 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39766">39766</a>
-compilation unit cannot be saved 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39664">39664</a>
-setSuperInterfaces(String[] interfaceNames) API of org.eclipse.jdt.core.jdom.IDOMType interface does not work for an empty array parameter as Input
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39663">39663</a>
-setSuperclass(String superclassName) API of org.eclipse.jdt.core.jdom.IDOMType interface does not work for null as Input
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39736">39736</a>
-JavaModelException on copying read-only CompilationUnits 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39009">39009</a>
-NPE in Delta processor while executing JDT/UI tests 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35739">35739</a>
-Stack dump on console 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35632">35632</a>
-NPE in DeltaProcessor 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39281">39281</a>
-Unable Refacter (renaming) an inner class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38450">38450</a>
-Delete: Removing default package removes source folder 
-
-<a name="v_361"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M2 Build - 7th July 2003 
-<br>Project org.eclipse.jdt.core v_361
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_361">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li> Added optional compiler diagnosis for boolean method declaring thrown exceptions
-(matching problem ID is <code>IProblem.BooleanMethodThrowingException</code>)
-<pre>
-* COMPILER / Reporting Boolean Method Declaring Thrown Exceptions
-*    When enabled, the compiler will issue an error or a warning when a boolean method declaration 
-*    is specifying a clause for thrown exceptions. Some of them are predicates, and these should only 
-*    return a boolean value and not raise exceptions.
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.booleanMethodThrowingException"
-*     - possible values:   { "error", "warning", "ignore" }
-*     - default:           "ignore"
-</pre>
-<li> Added optional compiler diagnosis for indirect references to static members (matching problem IDs are:
-<code>IProblem.IndirectAccessToStaticField</code>, <code>IProblem.IndirectAccessToStaticMethod</code>, <code>IProblem.IndirectAccessToStaticType</code>).
-<pre>
-* COMPILER / Reporting Indirect Reference to a Static Member
-*    When enabled, the compiler will issue an error or a warning whenever a static field
-*    or method is accessed in an indirect way. A reference to a static member should
-*    preferably be qualified with its declaring type name.
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.indirectStaticAccess"
-*     - possible values:   { "error", "warning", "ignore" }
-*     - default:           "ignore"
-</pre>
-</li>
-<li> Removed method <code>Parser#grammar()</code>, which was hosting the Java grammar as a massive comment. 
-From now on, the grammar is defined in its own separate file: <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/grammar/java_1_4.g"><code>java_1_4.g</code></a>.
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39624">39624</a>
-Should warn about predicate throwing exceptions
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39168">39168</a>
-Could remove JavaElement.fLEType field 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36989">36989</a>
-Incorrect error for "super must be first statement in constructor"
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3319">3319</a>
-wrong compile-time error message (1GG1LDK)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39268">39268</a>
-Optional warning for indirect static references
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39533">39533</a>
-Working copy with no corresponding file not considered by NameLookup 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39502">39502</a>
-No completion in message send
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39475">39475</a>
-Extra error diagnosis in editor from siblings
-
-<a name="v_360"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M2 Build - 1st July 2003 
-<br>Project org.eclipse.jdt.core v_360
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_360">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li> Plugin version ID got incremented to 3.0.0. 
-</li>
-<li> Removed tolerance for relative source attachments in <code>JavaCore.newLibraryEntry(...)</code>. Only
-allowing relative empty pathes so as to permit using classpath variables to denote the absence of a source attachment.
-<li>To finish closing the gap between compilation units and working copies 
-(see <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36888">bug 36888</a>), new APIs were added to generalize
-the usage of a working copy owner (entire JavaModel is now aware of owned working copies). These new APIs are copies of existing APIs augmented with
-a <code>WorkingCopyOwner</code> parameter, that defines the working copies to consider in the operation. 
-When specifying an owner parameter, all working copies belonging to this owner will implicitly take precedence over primary ones
-(without requiring the owner to remember all its working copies, as in 2.1 era). Note that when no owned working copy is found, a primary
-unit will be considered instead, and since primary units have a built-in working copy (see <code>ICompilationUnit.becomeWorkingCopy(...)</code>),
-the primary unit may already be in working copy mode (very likely since an editor got opened on it). This means that an owner will already 
-transparently see unsaved editor contents for all units for which it has no better working copy to contribute.
-The following new APIs were added:
-	<ul>
-	<li><code>AST.parseCompilationUnit(char[] source, String unitName, IJavaProject project, WorkingCopyOwner owner)</code></li>
-	<li><code>AST.parseCompilationUnit(IClassFile classFile, boolean resolveBindings, WorkingCopyOwner owner)</code></li>
-	<li><code>AST.parseCompilationUnit(ICompilationUnit unit, boolean resolveBindings, WorkingCopyOwner owner)</code></li>
-	<li><code>IEvaluationContext.codeComplete(String codeSnippet, int position, ICompletionRequestor requestor, WorkingCopyOwner owner)</code></li>
-	<li><code>IEvaluationContext.codeSelect(String codeSnippet, int offset, int length, WorkingCopyOwner owner)</code></li>
-	<li><code>IDOMCompilationUnit.getCompilationUnit(IPackageFragment parent, WorkingCopyOwner owner)</code></li>
-	<li><code>ICodeAssist.codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner owner)</code></li>
-	<li><code>ICodeAssist.codeSelect(int offset, int length, WorkingCopyOwner owner)</code></li>
-	<li><code>ICompilationUnit.reconcile(boolean forceProblemDetection, WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
-	<li><code>IJavaProject.findElement(IPath path, WorkingCopyOwner owner)</code></li>
-	<li><code>IJavaProject.findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner)</code></li>
-	<li><code>IJavaProject.findType(String fullyQualifiedName, WorkingCopyOwner owner)</code></li>
-	<li><code>IJavaProject.newTypeHierarchy(IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
-	<li><code>IJavaProject.newTypeHierarchy(IType type, IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
-	<li><code>IPackageFragment.getCompilationUnit(String name, WorkingCopyOwner owner)</code></li>
-	<li><code>IPackageFragment.getCompilationUnits(WorkingCopyOwner owner)</code></li>
-	<li><code>IType.codeComplete(char[] snippet, int insertion, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic, ICompletionRequestor requestor, WorkingCopyOwner owner)</code></li>
-	<li><code>IType.newSupertypeHierarchy(WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
-	<li><code>IType.newTypeHierarchy(IJavaProject project, WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
-	<li><code>IType.newTypeHierarchy(WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
-	<li><code>IType.resolveType(String typeName, WorkingCopyOwner owner)</code></li>
-	<li><code>JavaCore.create(IFile file, WorkingCopyOwner owner)</code></li>
-	<li><code>JavaCore.create(IResource resource, WorkingCopyOwner owner)</code></li>
-	<li><code>JavaCore.create(String handleIdentifier, WorkingCopyOwner owner)</code></li>
-	<li><code>JavaCore.createCompilationUnitFrom(IFile file, WorkingCopyOwner owner)</code></li>
-	<li><code>JavaCore.getWorkingCopies(WorkingCopyOwner owner)</code></li>
-	<li><code>SearchEngine.SearchEngine(WorkingCopyOwner workingCopyOwner)</code></li>
-	<li><code>SearchEngine.createHierarchyScope(IType type, WorkingCopyOwner owner)</code></li>
-	</ul>
-</li>
-<li> Added optional problem to signal superfluous semicolons (matching problem ID is <code>IProblem.SuperfluousSemicolon</code>).
-<pre>
-* COMPILER / Reporting Superfluous Semicolon
-*    When enabled, the compiler will issue an error or a warning if a superfluous semicolon is met.
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.superfluousSemicolon"
-*     - possible values:   { "error", "warning", "ignore" }
-*     - default:           "ignore"</pre>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26281">26281</a>
-error hover text indicates wrong problem
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23166">23166</a>
-Syntax error message from Java compiler is confusing. 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33213">33213</a>
-Same error reported more than once? 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36214">36214</a>
-TODOs reported twice when located at the end of the method declaration 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36232">36232</a>
-binding do not fully consider working copies 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36888">36888</a>
-Close the gap between original and working copies 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39311">39311</a>
-Outliner did not refresh after method rename (refactor) 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39259">39259</a>
-While statement has wrong source position
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39007">39007</a>
-Infinite loop trying to index a non-existing external jar
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39172">39172</a>
-Incorrect error reported if extra semi-colon exists on a return statement
-
-
-<a name="v_359"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M2 Build - 23rd June 2003 
-<br>Project org.eclipse.jdt.core v_359
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_359">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Added API on <code>ICompilationUnit</code> to get the primary compilation unit of a working copy 
-	 (it replaces <code>IWorkingCopy.getOriginalElement()</code>):
-<pre>
-/**
- * Returns the primary compilation unit (whose owner is the primary owner)
- * this working copy was created from, or this compilation unit if this a primary
- * compilation unit.
- * Note that the returned primary compilation unit can be in working copy mode.
- * 
- * @return the primary compilation unit this working copy was created from,
- * or this compilation unit if it is primary
- * @since 3.0
- */
-ICompilationUnit getPrimary();
-</pre>
-</li>
-<li>Added API on <code>IJavaElement</code> to get the primary element of a working copy 
-	 element (it replaces <code>IWorkingCopy.getOriginalElement(IJavaElement)</code>):
-<pre>
-/**
- * Returns the primary element (whose compilation unit is the primary compilation unit)
- * this working copy element was created from, or this element if it is a descendant of a
- * primary compilation unit or if it is not a descendant of a working copy (e.g. it is a
- * binary member).
- * The returned element may or may not exist.
- * 
- * @return the primary element this working copy element was created from, or this
- * 	element.
- * @since 3.0
- */
-IJavaElement getPrimaryElement();
-</pre>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38678">38678</a>
-workspace did not shutdown
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37006">37006</a>
-2 tasks in the tasks view instead of one
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38759">38759</a>
-Task Tags: should not consider text in substrings/parts of text
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36066">36066</a>
-Outliner did not refresh after field rename 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38951">38951</a>
-NPE in editor while saving contents 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35877">35877</a>
-Stack overflow in code assist
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35409">35409</a>
-RC2 Compiler produces bogus error messages
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38838">38838</a>
-SyntaxError- unoptimal syntax error message
-
-
-<a name="v_357b"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M2 Build - 18th June 2003 
-<br>Project org.eclipse.jdt.core v_357b
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_357b">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Backported index manager deadlock fix on top of v_357</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38901">38901</a>
-IndexManager hangs in end-less loop
-
-
-<a name="v_358"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M2 Build - 16th June 2003 
-<br>Project org.eclipse.jdt.core v_358
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_358">cvs</a>).
-
-<p><b>NOTE:</b> This version got backed out due to severe regression
-(see <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38951">38951</a> NPE in editor while saving contents).
-Until subsequent version is made available (see above), integration builds will revert to previous version (v_357).
-
-<h2>
-What's new in this drop</h2>
-<ul>
-<li><code>JavaCore.newLibraryEntry(...)</code> will now allow an empty source attachment (<code>new Path("")</code>) to
-be equivalent to no source attachment (i.e. <code>null</code>). This adjustment is made necessary for
-library entries generated from classpath variables which cannot be set to <code>null</code>. Also see 
-bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38531">38531</a>.
-<pre>
-* @param sourceAttachmentPath the absolute path of the corresponding source archive or folder, 
-*    or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
-*   and will be automatically converted to <code>null</code>.
-</pre>
-</li>
-<li>Added API <code>IJavaProject#forceClasspathReload(IProgressMonitor)</code> to force reload of <code>.classpath</code> file
-before next automatic update occurs.
-<pre>
-/**
- * Force the project to reload its <code>.classpath</code> file from disk and update the classpath accordingly.
- * Usually, a change to the <code>.classpath</code> file is automatically noticed and reconciled at the next 
- * resource change notification event. If required to consider such a change prior to the next automatic
- * refresh, then this functionnality should be used to trigger a refresh. In particular, if a change to the file is performed,
- * during an operation where this change needs to be reflected before the operation ends, then an explicit refresh is
- * necessary.
- * 
- * @param monitor a progress monitor for reporting operation progress
- * @exception JavaModelException if the classpath could not be updated. Reasons
- * include:
- *  - This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
- *  - Two or more entries specify source roots with the same or overlapping paths (NAME_COLLISION)
- *  - A entry of kind <code>CPE_PROJECT</code> refers to this project (INVALID_PATH)
- *  - This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
- *  - The output location path refers to a location not contained in this project (<code>PATH_OUTSIDE_PROJECT</code>)
- *  - The output location path is not an absolute path (<code>RELATIVE_PATH</code>)
- *  - The output location path is nested inside a package fragment root of this project (<code>INVALID_PATH</code>)
- *  - The classpath is being modified during resource change event notification (CORE_EXCEPTION)
- * @since 3.0
- */
-</pre>
-</li>
-<li>In the process of closing the gap between compilation units and working copies 
-(see <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36888 ">bug 36888 </a>), the following new APIs 
-are added to <code>ICompilationUnit</code>:
-	<ul>
-	<li><pre>
-/**
- * Changes this compilation unit handle into a working copy. A new IBuffer is
- * created using this compilation unit handle's owner. Uses the primary owner is none was
- * specified when this compilation unit handle was created.
- *
- * When switching to working copy mode, problems are reported to given 
- * IProblemRequestor.
- *
- * Once in working copy mode, changes to this compilation unit or its children are done in memory.
- * Only the new buffer is affected. Using commitWorkingCopy(boolean, IProgressMonitor)
- * will bring the underlying resource in sync with this compilation unit.
- *
- * If this compilation unit was already in working copy mode, an internal counter is incremented and no
- * other action is taken on this compilation unit. To bring this compilation unit back into the original mode 
- * (where it reflects the underlying resource), discardWorkingCopy must be call as many 
- * times as becomeWorkingCopy.
- * 
- * @param problemRequestor a requestor which will get notified of problems detected during
- * 	reconciling as they are discovered. The requestor can be set to null indicating
- * 	that the client is not interested in problems.
- * @param monitor a progress monitor used to report progress while opening this compilation unit
- * 	or null if no progress should be reported 
- * @exception JavaModelException if this compilation unit could not become a working copy.
- * @see discardWorkingCopy
- * @since 3.0
- */
-void becomeWorkingCopy(IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException;	
-	</pre></li>
-	<li><pre>
-/**
- * Commits the contents of this working copy to its underlying resource.
- *
- * It is possible that the contents of the original resource have changed
- * since this working copy was created, in which case there is an update conflict.
- * The value of the force parameter effects the resolution of
- * such a conflict:
- * - true - in this case the contents of this working copy are applied to
- * 	the underlying resource even though this working copy was created 
- * 	before a subsequent change in the resource
- * - false - in this case a JavaModelException is thrown
- * 
- * Since 2.1, a working copy can be created on a not-yet existing compilation
- * unit. In particular, such a working copy can then be committed in order to create
- * the corresponding compilation unit.
- * 
- * @param force a flag to handle the cases when the contents of the original resource have changed
- * since this working copy was created
- * @param monitor the given progress monitor
- * @exception JavaModelException if this working copy could not commit. Reasons include:
- * - A CoreException occurred while updating an underlying resource
- * - This element is not a working copy (INVALID_ELEMENT_TYPES)
- * - A update conflict (described above) (UPDATE_CONFLICT)
- * @since 3.0
- */
-void commitWorkingCopy(boolean force, IProgressMonitor monitor) throws JavaModelException;	
-	</pre></li>
-	<li><pre>
-/**
- * Changes this compilation unit in working copy mode back to its original mode.
- *
- * This has no effect if this compilation unit was not in working copy mode.
- * 
- * If becomeWorkingCopy was called several times on this
- * compilation unit, discardWorkingCopy must be called as 
- * many times before it switches back to the original mode.
- * 
- * @see becomeWorkingCopy
- * @exception JavaModelException if this working copy could not return in its original mode.
- * @since 3.0
- */
-void discardWorkingCopy() throws JavaModelException;
-	</pre></li>
-	<li><pre>
-/**
- * Returns the working copy owner of this working copy.
- * Returns null if it is not a working copy or if it has no owner.
- * 
- * @return WorkingCopyOwner the owner of this working copy or null
- * @since 3.0
- */
-WorkingCopyOwner getOwner();
-	</pre></li>	
-	<li><pre>
-/**
- * Returns a new working copy of this element if this element is not
- * a working copy, or this element if this element is already a working copy.
- * 
- * Note: if intending to share a working copy amongst several clients, then 
- * getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor) 
- * should be used instead.
- * 
- * When the working copy instance is created, an ADDED IJavaElementDelta is 
- * reported on this working copy.
- * 
- * Since 2.1, a working copy can be created on a not-yet existing compilation
- * unit. In particular, such a working copy can then be committed in order to create
- * the corresponding compilation unit.
- * 
-* @param monitor a progress monitor used to report progress while opening this compilation unit
- * 	or null if no progress should be reported 
- * @exception JavaModelException if the contents of this element can
- * 	not be determined. 
- * @return a new working copy of this element if this element is not
- * 	a working copy, or this element if this element is already a working copy
- * @since 3.0
- */
-ICompilationUnit getWorkingCopy(IProgressMonitor monitor) throws JavaModelException;
-	</pre></li>	
-	<li><pre>
-/**
- * Returns a shared working copy on this element using the given working copy owner to create
- * the buffer, or this element if this element is already a working copy.
- * This API can only answer an already existing working copy if it is based on the same
- * original compilation unit AND was using the same working copy owner (that is, as defined by Object.equals).	 
- * 
- * The life time of a shared working copy is as follows:
- * - The first call to getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)
- *   creates a new working copy for this element
- * - Subsequent calls increment an internal counter.
- * - A call to discardWorkingCopy() decrements the internal counter.
- * - When this counter is 0, the working copy is discarded.
- * 
- * So users of this method must discard exactly once the working copy.
- *
- * Note that the working copy owner will be used for the life time of this working copy, that is if the 
- * working copy is closed then reopened, this owner will be used.
- * The buffer will be automatically initialized with the original's compilation unit content
- * upon creation.
- * 
- * When the shared working copy instance is created, an ADDED IJavaElementDelta is reported on this
- * working copy.
- * 
- * Since 2.1, a working copy can be created on a not-yet existing compilation
- * unit. In particular, such a working copy can then be committed in order to create
- * the corresponding compilation unit.
- * 
- * @param owner the working copy owner that creates a buffer that is used to get the content 
- *  	of the working copy
- * @param problemRequestor a requestor which will get notified of problems detected during
- * 	reconciling as they are discovered. The requestor can be set to null indicating
- * 	that the client is not interested in problems.
- * @param monitor a progress monitor used to report progress while opening this compilation unit
- * 	or null if no progress should be reported 
- * @exception JavaModelException if the contents of this element can
- *  	not be determined. 
- * @return a new working copy of this element using the given factory to create
- * the buffer, or this element if this element is already a working copy
- * @since 3.0
- */
-ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException;	
-	</pre></li>
-	</ul>
-And the following abstract class replaces <code>IBufferFactory</code>:
-	<pre>
-/**
- * The owner of an ICompilationUnit handle in working copy mode. 
- * An owner is used to identify a working copy and to create its buffer.
- * 
- * @see ICompilationUnit#becomeWorkingCopy
- * @see ICompilationUnit#discardWorkingCopy
- * @since 3.0
- */
-public abstract class WorkingCopyOwner {
-	/**
-	 * Creates a buffer for the given working copy.
-	 * The new buffer will be initialized with the contents of the underlying file
-	 * if and only if it was not already initialized by the compilation owner (a buffer is 
-	 * uninitialized if its content is null).
-	 * 
-	 * @param workingCopy the working copy of the buffer
-	 * @return IBuffer the created buffer for the given working copy
-	 * @see IBuffer
-	 */
-	public IBuffer createBuffer(ICompilationUnit workingCopy) {
-		...
-	}
-}
-	</pre>
-	The intent for the primary owner is to use a buffer factory that would be
-	provided by the org.eclipse.text infractructure. This infrastructure not being
-	ready yet, in the meantime one can change the primary owner's 
-	<code>IBufferFactory</code> using the following internal API:
-	<pre>
-org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner.PRIMARY.factory = ...;
-	</pre>
-
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38901">38901</a>
-IndexManager hangs in end-less loop
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38908">38908</a>
-Ant script reports that the bootclasspath cannot be infer
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38531">38531</a>
-IllegalArgumentException "Source attachment path should be absolute"
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38424">38424</a>
-Mistake on Web site
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38732">38732</a>
-organize imports does not work with assert in source code
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38447">38447</a>
-AST: Source ranges with missing bracket
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36854">36854</a>
-NPE opening type hierarchy 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33530">33530</a>
-JavaModel synchronization model should be more optimistic 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20931">20931</a>
-Need an API to reload the classpath from the file
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38393">38393</a>
-bytecode generated for evaluation with parentheses is wrong
-
-<a name="v_357"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M1 Build - 5th June 2003 - 3.0 MILESTONE-1
-<br>Project org.eclipse.jdt.core v_357
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_357">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37274">37274</a>
-Deadlock on plugin import
-
-
-<a name="v_356"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M1 Build - 4th June 2003
-<br>Project org.eclipse.jdt.core v_356
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_356">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38362">38362</a>
-Inconsistent output when using comparrisson operators
-
-
-<a name="v_355"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M1 Build - 3rd June 2003
-<br>Project org.eclipse.jdt.core v_355
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_355">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Fix for bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37111">37111</a> may issue some outgoing changes
-to .classpath file since the source attachment will be shortened into a project relative path when applicable. The .classpath file
-is still backward compatible, and will continue to accept non relative source attachments as well. </li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37111">37111</a>
-classpath file - java source attachment shouldn't hardcode project name
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38143">38143</a>
-this = null; should raise compile time error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38124">38124</a>
-Brackets around cast accepted by Eclipse but not javac
-
-
-<a name="v_354"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M1 Build - 26th May 2003
-<br>Project org.eclipse.jdt.core v_354
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_354">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Added <code>JavaCore</code> optional problem to detect incompatible required binaries, so as to flag situations where
-some prerequisite binaries are required a JRE level higher than the project target platform; i.e. compiling against 1.4 libraries 
-when deploying for 1.1 platform is likely unwanted.
-<pre>
-* JAVACORE / Reporting Incompatible JDK Level for Required Binaries
-*    Indicate the severity of the problem reported when a project prerequisites another project 
-*    or library with an incompatible target JDK level (e.g. project targeting 1.1 vm, but compiled against 1.4 libraries).
-*     - option id:         "org.eclipse.jdt.core.incompatibleJDKLevel"
-*     - possible values:   { "error", "warning", "ignore" }
-*     - default:           "ignore"
-</pre>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37750">37750</a>
-incorrect handle identifier for IImportContainer
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36674">36674</a>
-compiler can generate Java 1.4-only bytecode regardless of compatibility settings
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37962">37962</a>
-Unexpected transient problem during reconcile 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37166">37166</a>
-NPE in SearchEngine when matching type against ProblemReferenceBinding 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37438">37438</a>
-searchenging NPE in searchDeclarationsOfReferencedTypes 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37779">37779</a>
-ExceptionInInitializerError when using JDTCompilerAdapter
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36307">36307</a>
-JDK1.4.2: Wrong declaring class for clone method on array class
-
-
-<a name="v_353"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M1 Build - 19th May 2003
-<br>Project org.eclipse.jdt.core v_353
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_353">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37621">37621</a>
-java compiler creates class with internal inconsistency
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37646">37646</a>
-Help for JDTCompilerAdapter is dated
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36894">36894</a>
-JobManager could wait when idle
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37541">37541</a>
-Unoptimal deprecation diagnosis
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37565">37565</a>
-JACKS: Class literal should not cause class initialization
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37503">37503</a>
-Compiler does not take care of exclusion filter
-
-
-<a name="v_352"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M1 Build - 13th May 2003
-<br>Project org.eclipse.jdt.core v_352
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_352">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Lowered default severity of field/local variable hiding optional diagnosis to <code>"ignore"</code>.
-</li>
-<li>Lowered default severity of accidental boolean assignment optional diagnosis to <code>"ignore"</code>.
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37501">37501</a>
-VerifyError with assert when optimizing out unused local variables
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37387">37387</a>
-Compiler generates unnecessary byte codes
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37381">37381</a>
-AST: Wrong source ranges on VariableDeclExpression
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37200">37200</a>
-"Source->Generate Delegate Methods..." fails
-
-<a name="v_351"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M1 Build - 29th April 2003
-<br>Project org.eclipse.jdt.core v_351
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_351">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37040">37040</a>
-VerifyError "Illegal target of jump or branch"
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36490">36490</a>
-Java compiler misses dependency on 'static final' class variables
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36814">36814</a>
-NaiveASTFlattener does not serialize try-finally statements correctly
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36772">36772</a>
-AST: CompilationUnit.findDeclaringNode: Spec/Impl not same
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36711">36711</a>
-Resource duplication message should list location of duplicate
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36718">36718</a>
-Compiler should not generate references to classes not on the classpath
-
-<a name="v_350"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 3.0M1 Build - 22nd April 2003
-<br>Project org.eclipse.jdt.core v_350
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_350">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Added new compiler optional problem to signal cases where a boolean variable is assigned
-in a condition expression. It is likely an accidental situation, where a comparison was actually meant.
-<pre>
-* COMPILER / Reporting Possible Accidental Boolean Assignment
-*    When enabled, the compiler will issue an error or a warning if a boolean assignment is acting as the condition
-*    of a control statement  (where it probably was meant to be a boolean comparison).
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment"
-*     - possible values:   { "error", "warning", "ignore" }
-*     - default:           "warning"
-</pre>
-</li>
-<li>Added new compiler settings to control the diagnosis of variable hiding other ones.
-<pre>
-* COMPILER / Reporting Local Variable Declaration Hiding another Variable
-*    When enabled, the compiler will issue an error or a warning whenever a local variable
-*    declaration is hiding some field or local variable (either locally, inherited or defined in enclosing type).
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.localVariableHiding"
+* COMPILER / Setting Compliance Level
+*    Select the compliance level for the compiler. In "1.3" mode, source and target settings
+*    should not go beyond "1.3" level.
+*     - option id:         "org.eclipse.jdt.core.compiler.compliance"
+*     - possible values:   { "1.3", "1.4", "1.5" }
+*     - default:           "1.4"
+* 
+* COMPILER / Setting Source Compatibility Mode
+*    Specify whether which source level compatibility is used. From 1.4 on, 'assert' is a keyword
+*    reserved for assertion support. Also note, than when toggling to 1.4 mode, the target VM
+*   level should be set to "1.4" and the compliance mode should be "1.4".
+*   Source level 1.5 is necessary to enable generics, autoboxing, covariance, annotations, enumerations
+*   enhanced for loop, static imports and varargs. Once toggled, the target VM level should be set to "1.5"
+*   and the compliance mode should be "1.5".
+*     - option id:         "org.eclipse.jdt.core.compiler.source"
+*     - possible values:   { "1.3", "1.4", "1.5" }
+*     - default:           "1.3"
+* 
+* COMPILER / Defining Target Java Platform
+*    For binary compatibility reason, .class files can be tagged to with certain VM versions and later.
+*    Note that "1.4" target require to toggle compliance mode to "1.4" too. Similarily, "1.5" target require
+*    to toggle compliance mode to "1.5".
+*     - option id:         "org.eclipse.jdt.core.compiler.codegen.targetPlatform"
+*     - possible values:   { "1.1", "1.2", "1.3", "1.4", "1.5" }
+*     - default:           "1.2"
+* 
+* COMPILER / Reporting Unsafe Type Operation
+*    When enabled, the compiler will issue an error or a warning whenever an operation involves generic types, and potentially
+*    invalidates type safety since involving raw types (e.g. invoking #foo(X&lt;String&gt;) with arguments  (X)).
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation"
 *     - possible values:   { "error", "warning", "ignore" }
 *     - default:           "warning"
 *
-* COMPILER / Reporting Field Declaration Hiding another Variable
-*    When enabled, the compiler will issue an error or a warning whenever a field
-*    declaration is hiding some field or local variable (either locally, inherited or defined in enclosing type).
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.fieldHiding"
+* COMPILER / Reporting final Bound for Type Parameter
+*    When enabled, the compiler will issue an error or a warning whenever a generic type parameter is associated with a 
+*    bound corresponding to a final type; since final types cannot be further extended, the parameter is pretty useless.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.finalParameterBound"
 *     - possible values:   { "error", "warning", "ignore" }
-*     - default:           "warning"
-*
-* COMPILER / Reporting Special Parameter Hiding another Field
-*    When enabled, the compiler will signal cases where a constructor or setter method parameter declaration 
-*    is hiding some field (either locally, inherited or defined in enclosing type).
-*    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.localVariableHiding".
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.specialParameterHidingField"
-*     - possible values:   { "enabled", "disabled" }
-*     - default:           "disabled"
+*     - default:           "ignore"
 </pre>
 </li>
 </ul>
 
 <h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36510">36510</a>
-Automatically attach source for source files located in a class folder 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36499">36499</a>
-exists() returns true for a source file inside a classfolder 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36438">36438</a>
-null == null causes java.lang.VerifyError
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35755">35755</a>
-Search in hierarchy misses dependent projects 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36465">36465</a>
-Unable to create multiple source folders when not using bin for output
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36339">36339</a>
-Try codegen issues slightly incorrect ANY exception handler
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35965">35965</a>
-Source not found in source attachment 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36447">36447</a>
-Unoptimal wide conditional branch bytecode sequence
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=19286">19286</a>
-Suspicious synchronized operations 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36213">36213</a>
-ArrayIndex out of bounds
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36244">36244</a>
-JDK1.4.2: Add -cp as a batch option 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35528">35528</a>
-When I check out a project from CVS, Updating takes a very long time
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36058">36058</a>
-Unknown NPE in log
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21661">21661</a>
-Compile dependency problems
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28937">28937</a>
-Compiler Problem Marker: Accidental Boolean Assignment
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33831">33831</a>
-ast API: add FieldAccess.resolveFieldBinding
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35649">35649</a>
-The SourceMapper instances could share the fileNamefilter 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34896">34896</a>
-compiler setting "unused private fields"
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33751">33751</a>
-The numbering of anonymous could be optimized
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35849">35849</a>
-Incremental compilation ignores linked folders
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35926">35926</a>
-Batch compiler compile should return false when the command line is incorrect
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35421">35421</a>
-[nls] Inconsistencies between properties files and nls strings
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34173">34173</a>
-Create a compiler warning when an instance variable is "re-declared" as a local variable.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21140">21140</a>
-Warning/error on shadowing definition of data member?
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35490">35490</a>
-Search doesn't work for reference of 'cursorLocation'
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35338">35338</a>
-Cannot save file, "Save failed:null" error message received
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35438">35438</a>
-CastExpression resolution departs from JLS section 6.5.1
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36165">36165</a>
-[DOM/AST] Incorrect grammar rule in TypeDeclaration
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=56731">56731</a>
+[1.5] NPE inside ClassFileStruct when compiling with jre 1.5.0
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51262">51262</a>
+[1.5] Handling of additional bounds in type parameters
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52673">52673</a>
+[1.5] ArrayStoreException in 1.5 parser
 
 
-<a name="v_312"></a>
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build (before 3.0/2.1.1 branching) - 31st March 2003
-<br>Project org.eclipse.jdt.core v_312
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_312">cvs</a>).
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35831">35831</a>
-NPE navigating references using links
-
 <p><hr>
-For earlier build notes, also see <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.jdt.core/notes/R21_buildnotes_jdt-core.html">build notes up to Release 2.1</a>.
+For earlier build notes, also see <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.jdt.core/notes/R30_buildnotes_jdt-core.html">build notes up to Release 3.0</a>.
 
 <br>&nbsp;
 </body>
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
index b2e7ccb..b74eb7b 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
@@ -13,10 +13,13 @@
 import java.util.Locale;
 import java.util.Map;
 
-import org.eclipse.jdt.core.ICompletionRequestor;
+import org.eclipse.jdt.core.CompletionProposal;
+import org.eclipse.jdt.core.CompletionRequestor;
+import org.eclipse.jdt.core.Flags;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.IProblem;
 
@@ -30,6 +33,7 @@
 import org.eclipse.jdt.internal.compiler.env.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
@@ -37,9 +41,12 @@
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
-import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.BasicCompilationUnit;
-import org.eclipse.jdt.internal.core.TypeConverter;
+import org.eclipse.jdt.internal.core.INamingRequestor;
+import org.eclipse.jdt.internal.core.InternalNamingConventions;
+import org.eclipse.jdt.internal.core.SourceType;
+import org.eclipse.jdt.internal.core.BinaryTypeConverter;
+import org.eclipse.jdt.internal.core.SearchableEnvironment;
 
 /**
  * This class is the entry point for source completions.
@@ -58,6 +65,11 @@
 	private final static char[] EXCEPTION_PATTERN = "*exception*".toCharArray();  //$NON-NLS-1$
 	private final static char[] SEMICOLON = new char[] { ';' };
 	
+	private final static char[] CLASS = "Class".toCharArray();  //$NON-NLS-1$
+	private final static char[] VOID = "void".toCharArray();  //$NON-NLS-1$
+	private final static char[] INT = "int".toCharArray();  //$NON-NLS-1$
+	private final static char[] INT_SIGNATURE = new char[]{Signature.C_INT};
+	
 	private final static int SUPERTYPE = 1;
 	private final static int SUBTYPE = 2;
 	
@@ -74,10 +86,11 @@
 	boolean assistNodeIsClass;
 	boolean assistNodeIsException;
 	boolean assistNodeIsInterface;
+	boolean assistNodeIsAnnotation;
 	
 	IJavaProject javaProject;
 	CompletionParser parser;
-	ICompletionRequestor requestor;
+	CompletionRequestor requestor;
 	ProblemReporter problemReporter;
 	char[] source;
 	char[] completionToken;
@@ -135,6 +148,7 @@
 	static final char[] THROWS = "throws".toCharArray();  //$NON-NLS-1$
 	
 	static InvocationSite FakeInvocationSite = new InvocationSite(){
+		public TypeBinding[] genericTypeArguments() { return null; }
 		public boolean isSuperAccess(){ return false; }
 		public boolean isTypeAccess(){ return false; }
 		public void setActualReceiverType(ReferenceBinding receiverType) {}
@@ -162,18 +176,17 @@
 	 *		set of options used to configure the code assist engine.
 	 */
 	public CompletionEngine(
-		ISearchableNameEnvironment nameEnvironment,
-		ICompletionRequestor requestor,
-		Map settings,
-		IJavaProject javaProject) {
-
+			SearchableEnvironment nameEnvironment,
+			CompletionRequestor requestor,
+			Map settings,
+			IJavaProject javaProject) {
 		super(settings);
 		this.javaProject = javaProject;
 		this.requestor = requestor;
 		this.nameEnvironment = nameEnvironment;
 		this.typeCache = new HashtableOfObject(5);
 
-		problemReporter = new ProblemReporter(
+		this.problemReporter = new ProblemReporter(
 				DefaultErrorHandlingPolicies.proceedWithAllProblems(),
 				this.compilerOptions,
 				new DefaultProblemFactory(Locale.getDefault()) {
@@ -199,13 +212,13 @@
 							end,
 							lineNumber);
 						// TODO (david) problems could be detected in other units which got requested (see CompilationUnitProblemFinder)
-						if(actualCompletionPosition > start
-							&& lastErrorStart < start
+						if(CompletionEngine.this.actualCompletionPosition > start
+							&& this.lastErrorStart < start
 							&& pb.isError()
 							&& (pb.getID() & IProblem.Syntax) == 0) {
 								
 							CompletionEngine.this.problem = pb;
-							lastErrorStart = start;
+							this.lastErrorStart = start;
 						}
 						
 						return pb;
@@ -213,9 +226,9 @@
 
 				});
 		this.lookupEnvironment =
-			new LookupEnvironment(this, this.compilerOptions, problemReporter, nameEnvironment);
+			new LookupEnvironment(this, this.compilerOptions, this.problemReporter, nameEnvironment);
 		this.parser =
-			new CompletionParser(problemReporter);
+			new CompletionParser(this.problemReporter);
 		this.nameScanner =
 			new Scanner(
 				false /*comment*/, 
@@ -228,6 +241,69 @@
 	}
 
 	/**
+	 * One result of the search consists of a new annotation.
+	 *
+	 * NOTE - All package and type names are presented in their readable form:
+	 *    Package names are in the form "a.b.c".
+	 *    Nested type names are in the qualified form "A.I".
+	 *    The default package is represented by an empty array.
+	 */
+	public void acceptAnnotation(
+		char[] packageName,
+		char[] annotationName,
+		int modifiers,
+		AccessRestriction accessRestriction) {
+
+		char[] fullyQualifiedName = CharOperation.concat(packageName, annotationName, '.');
+		char[] completionName = fullyQualifiedName;
+
+		if (this.knownTypes.containsKey(completionName)) return;
+
+		this.knownTypes.put(completionName, this);
+
+		if(this.options.checkRestrictions && accessRestriction != null) return;
+		
+		boolean isQualified = true;
+		int relevance = computeBaseRelevance();
+		relevance += computeRelevanceForInterestingProposal();
+		relevance += computeRelevanceForRestrictions(accessRestriction != null);
+		if (this.resolvingImports) {
+			completionName = CharOperation.concat(completionName, new char[] { ';' });
+			relevance += computeRelevanceForCaseMatching(this.completionToken, fullyQualifiedName);
+		} else {
+			if (mustQualifyType(packageName, annotationName)) {
+				if (packageName == null || packageName.length == 0)
+					if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
+						return; // ignore types from the default package from outside it
+			} else {
+				completionName = annotationName;
+				isQualified = false;
+			}
+			relevance += computeRelevanceForCaseMatching(this.completionToken, annotationName);
+			relevance += computeRelevanceForExpectingType(packageName, annotationName);
+			relevance += computeRelevanceForAnnotation();
+			relevance += computeRelevanceForQualification(isQualified);
+		}
+		
+		this.noProposal = false;
+		if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+			CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+			proposal.setDeclarationSignature(packageName);
+			proposal.setSignature(createNonGenericTypeSignature(packageName, annotationName));
+			proposal.setPackageName(packageName);
+			proposal.setTypeName(annotationName);
+			proposal.setCompletion(completionName);
+			proposal.setFlags(modifiers | Flags.AccInterface | Flags.AccAnnotation);
+			proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+			proposal.setRelevance(relevance);
+			this.requestor.accept(proposal);
+			if(DEBUG) {
+				this.printDebug(proposal);
+			}
+		}
+	}
+	
+	/**
 	 * One result of the search consists of a new class.
 	 *
 	 * NOTE - All package and type names are presented in their readable form:
@@ -235,7 +311,7 @@
 	 *    Nested type names are in the qualified form "A.M".
 	 *    The default package is represented by an empty array.
 	 */
-	public void acceptClass(char[] packageName, char[] className, int modifiers) {
+	public void acceptClass(char[] packageName, char[] className, int modifiers, AccessRestriction accessRestriction) {
 
 		char[] fullyQualifiedName = CharOperation.concat(packageName, className, '.');
 		char[] completionName = fullyQualifiedName;
@@ -244,37 +320,107 @@
 
 		this.knownTypes.put(completionName, this);
 		
+		if(this.options.checkRestrictions && accessRestriction != null) return;
+		
 		boolean isQualified = true;
 		int relevance = computeBaseRelevance();
 		relevance += computeRelevanceForInterestingProposal();
-		if (resolvingImports) {
+		relevance += computeRelevanceForRestrictions(accessRestriction != null);
+		if (this.resolvingImports) {
 			completionName = CharOperation.concat(completionName, SEMICOLON);
-			relevance += computeRelevanceForCaseMatching(completionToken, fullyQualifiedName);
+			relevance += computeRelevanceForCaseMatching(this.completionToken, fullyQualifiedName);
 		} else {
 			if (mustQualifyType(packageName, className)) {
 				if (packageName == null || packageName.length == 0)
-					if (unitScope != null && unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
+					if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
 						return; // ignore types from the default package from outside it
 			} else {
 				completionName = className;
 				isQualified = false;
 			}
-			relevance += computeRelevanceForCaseMatching(completionToken, className);
+			relevance += computeRelevanceForCaseMatching(this.completionToken, className);
 			relevance += computeRelevanceForExpectingType(packageName, className);
 			relevance += computeRelevanceForClass();
 			relevance += computeRelevanceForException(className);
 			relevance += computeRelevanceForQualification(isQualified);
 		}
 
-		noProposal = false;
-		requestor.acceptClass(
-			packageName,
-			className,
-			completionName,
-			modifiers,
-			startPosition - offset,
-			endPosition - offset,
-			relevance);
+		this.noProposal = false;
+		if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+			CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+			proposal.setDeclarationSignature(packageName);
+			proposal.setSignature(createNonGenericTypeSignature(packageName, className));
+			proposal.setPackageName(packageName);
+			proposal.setTypeName(className);
+			proposal.setCompletion(completionName);
+			proposal.setFlags(modifiers);
+			proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+			proposal.setRelevance(relevance);
+			this.requestor.accept(proposal);
+			if(DEBUG) {
+				this.printDebug(proposal);
+			}
+		}
+	}
+	
+	/**
+	 * One result of the search consists of a new enum.
+	 *
+	 * NOTE - All package and type names are presented in their readable form:
+	 *    Package names are in the form "a.b.c".
+	 *    Nested type names are in the qualified form "A.M".
+	 *    The default package is represented by an empty array.
+	 */
+	public void acceptEnum(char[] packageName, char[] enumName, int modifiers, AccessRestriction accessRestriction) {
+
+		char[] fullyQualifiedName = CharOperation.concat(packageName, enumName, '.');
+		char[] completionName = fullyQualifiedName;
+		
+		if (this.knownTypes.containsKey(completionName)) return;
+
+		this.knownTypes.put(completionName, this);
+		
+		if(this.options.checkRestrictions && accessRestriction != null) return;
+		
+		boolean isQualified = true;
+		int relevance = computeBaseRelevance();
+		relevance += computeRelevanceForInterestingProposal();
+		relevance += computeRelevanceForRestrictions(accessRestriction != null);
+		if (this.resolvingImports) {
+			completionName = CharOperation.concat(completionName, SEMICOLON);
+			relevance += computeRelevanceForCaseMatching(this.completionToken, fullyQualifiedName);
+		} else {
+			if (mustQualifyType(packageName, enumName)) {
+				if (packageName == null || packageName.length == 0)
+					if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
+						return; // ignore types from the default package from outside it
+			} else {
+				completionName = enumName;
+				isQualified = false;
+			}
+			relevance += computeRelevanceForCaseMatching(this.completionToken, enumName);
+			relevance += computeRelevanceForExpectingType(packageName, enumName);
+			relevance += computeRelevanceForClass();
+			relevance += computeRelevanceForException(enumName);
+			relevance += computeRelevanceForQualification(isQualified);
+		}
+
+		this.noProposal = false;
+		if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+			CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+			proposal.setDeclarationSignature(packageName);
+			proposal.setSignature(createNonGenericTypeSignature(packageName, enumName));
+			proposal.setPackageName(packageName);
+			proposal.setTypeName(enumName);
+			proposal.setCompletion(completionName);
+			proposal.setFlags(modifiers | Flags.AccEnum);
+			proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+			proposal.setRelevance(relevance);
+			this.requestor.accept(proposal);
+			if(DEBUG) {
+				this.printDebug(proposal);
+			}
+		}
 	}
 	
 	/**
@@ -288,7 +434,8 @@
 	public void acceptInterface(
 		char[] packageName,
 		char[] interfaceName,
-		int modifiers) {
+		int modifiers,
+		AccessRestriction accessRestriction) {
 
 		char[] fullyQualifiedName = CharOperation.concat(packageName, interfaceName, '.');
 		char[] completionName = fullyQualifiedName;
@@ -297,36 +444,46 @@
 
 		this.knownTypes.put(completionName, this);
 
+		if(this.options.checkRestrictions && accessRestriction != null) return;
+		
 		boolean isQualified = true;
 		int relevance = computeBaseRelevance();
 		relevance += computeRelevanceForInterestingProposal();
-		if (resolvingImports) {
+		relevance += computeRelevanceForRestrictions(accessRestriction != null);
+		if (this.resolvingImports) {
 			completionName = CharOperation.concat(completionName, new char[] { ';' });
-			relevance += computeRelevanceForCaseMatching(completionToken, fullyQualifiedName);
+			relevance += computeRelevanceForCaseMatching(this.completionToken, fullyQualifiedName);
 		} else {
 			if (mustQualifyType(packageName, interfaceName)) {
 				if (packageName == null || packageName.length == 0)
-					if (unitScope != null && unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
+					if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
 						return; // ignore types from the default package from outside it
 			} else {
 				completionName = interfaceName;
 				isQualified = false;
 			}
-			relevance += computeRelevanceForCaseMatching(completionToken, interfaceName);
+			relevance += computeRelevanceForCaseMatching(this.completionToken, interfaceName);
 			relevance += computeRelevanceForExpectingType(packageName, interfaceName);
 			relevance += computeRelevanceForInterface();
 			relevance += computeRelevanceForQualification(isQualified);
 		}
 		
-		noProposal = false;
-		requestor.acceptInterface(
-			packageName,
-			interfaceName,
-			completionName,
-			modifiers,
-			startPosition - offset,
-			endPosition - offset,
-			relevance);
+		this.noProposal = false;
+		if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+			CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+			proposal.setDeclarationSignature(packageName);
+			proposal.setSignature(createNonGenericTypeSignature(packageName, interfaceName));
+			proposal.setPackageName(packageName);
+			proposal.setTypeName(interfaceName);
+			proposal.setCompletion(completionName);
+			proposal.setFlags(modifiers | Flags.AccInterface);
+			proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+			proposal.setRelevance(relevance);
+			this.requestor.accept(proposal);
+			if(DEBUG) {
+				this.printDebug(proposal);
+			}
+		}
 	}
 
 	/**
@@ -344,65 +501,26 @@
 		
 		int relevance = computeBaseRelevance();
 		relevance += computeRelevanceForInterestingProposal();
-		relevance += computeRelevanceForCaseMatching(qualifiedCompletionToken == null ? completionToken : qualifiedCompletionToken, packageName);
+		relevance += computeRelevanceForCaseMatching(this.qualifiedCompletionToken == null ? this.completionToken : this.qualifiedCompletionToken, packageName);
 		relevance += computeRelevanceForQualification(true);
+		relevance += computeRelevanceForRestrictions(false);
 		
-		noProposal = false;
-		requestor.acceptPackage(
-			packageName,
-			resolvingImports
-				? CharOperation.concat(packageName, new char[] { '.', '*', ';' })
-				: packageName,
-			startPosition - offset,
-			endPosition - offset,
-			relevance);
-	}
-
-	/**
-	 * One result of the search consists of a new type.
-	 *
-	 * NOTE - All package and type names are presented in their readable form:
-	 *    Package names are in the form "a.b.c".
-	 *    Nested type names are in the qualified form "A.M".
-	 *    The default package is represented by an empty array.
-	 */
-	public void acceptType(char[] packageName, char[] typeName) {
-
-		char[] fullyQualifiedName = CharOperation.concat(packageName, typeName, '.');
-		char[] completionName = fullyQualifiedName;
-		
-		if (this.knownTypes.containsKey(completionName)) return;
-
-		this.knownTypes.put(completionName, this);
-
-		boolean isQualified = true;
-		int relevance = computeBaseRelevance();
-		relevance += computeRelevanceForInterestingProposal();
-		if (resolvingImports) {
-			completionName = CharOperation.concat(completionName, new char[] { ';' });
-			relevance += computeRelevanceForCaseMatching(completionToken, fullyQualifiedName);
-		} else {
-			if (mustQualifyType(packageName, typeName)) {
-				if (packageName == null || packageName.length == 0)
-					if (unitScope != null && unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
-						return; // ignore types from the default package from outside it
-			} else {
-				completionName = typeName;
-				isQualified = false;
+		this.noProposal = false;
+		if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
+			CompletionProposal proposal = this.createProposal(CompletionProposal.PACKAGE_REF, this.actualCompletionPosition);
+			proposal.setDeclarationSignature(packageName);
+			proposal.setPackageName(packageName);
+			proposal.setCompletion(
+					this.resolvingImports
+					? CharOperation.concat(packageName, new char[] { '.', '*', ';' })
+					: packageName);
+			proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+			proposal.setRelevance(relevance);
+			this.requestor.accept(proposal);
+			if(DEBUG) {
+				this.printDebug(proposal);
 			}
-			relevance += computeRelevanceForCaseMatching(completionToken, typeName);
-			relevance += computeRelevanceForExpectingType(packageName, typeName);
-			relevance += computeRelevanceForQualification(isQualified);
 		}
-		
-		noProposal = false;
-		requestor.acceptType(
-			packageName,
-			typeName,
-			completionName,
-			startPosition - offset,
-			endPosition - offset,
-			relevance);
 	}
 
 	private void complete(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
@@ -411,55 +529,56 @@
 		
 		computeUninterestingBindings(astNodeParent, scope);
 		if(astNodeParent != null) {
-			computeExpectedTypes(astNodeParent, scope);
+			if(!isValidParent(astNodeParent, astNode, scope)) return;
+			computeExpectedTypes(astNodeParent, astNode, scope);
 		}
 		
 		if (astNode instanceof CompletionOnFieldType) {
 
 			CompletionOnFieldType field = (CompletionOnFieldType) astNode;
 			CompletionOnSingleTypeReference type = (CompletionOnSingleTypeReference) field.type;
-			completionToken = type.token;
+			this.completionToken = type.token;
 			setSourceRange(type.sourceStart, type.sourceEnd);
 			
-			findTypesAndPackages(completionToken, scope);
-			findKeywordsForMember(completionToken, field.modifiers);
+			findTypesAndPackages(this.completionToken, scope);
+			findKeywordsForMember(this.completionToken, field.modifiers);
 			
 			if(!field.isLocalVariable && field.modifiers == CompilerModifiers.AccDefault) {
-				findMethods(completionToken,null,scope.enclosingSourceType(),scope,new ObjectVector(),false,false,true,null,null,false, false);
-				proposeNewMethod(completionToken, scope.enclosingSourceType());
+				findMethods(this.completionToken,null,scope.enclosingSourceType(),scope,new ObjectVector(),false,false,true,null,null,false,false,true);
+				proposeNewMethod(this.completionToken, scope.enclosingSourceType());
 			}
 		} else {
 			if(astNode instanceof CompletionOnMethodReturnType) {
 				
 				CompletionOnMethodReturnType method = (CompletionOnMethodReturnType) astNode;
 				SingleTypeReference type = (CompletionOnSingleTypeReference) method.returnType;
-				completionToken = type.token;
+				this.completionToken = type.token;
 				setSourceRange(type.sourceStart, type.sourceEnd);
-				findTypesAndPackages(completionToken, scope);
-				findKeywordsForMember(completionToken, method.modifiers);
+				findTypesAndPackages(this.completionToken, scope.parent);
+				findKeywordsForMember(this.completionToken, method.modifiers);
 			
 				if(method.modifiers == CompilerModifiers.AccDefault) {
-					findMethods(completionToken,null,scope.enclosingSourceType(),scope,new ObjectVector(),false,false,true,null,null,false,false);
-					proposeNewMethod(completionToken, scope.enclosingSourceType());
+					findMethods(this.completionToken,null,scope.enclosingSourceType(),scope,new ObjectVector(),false,false,true,null,null,false,false,true);
+					proposeNewMethod(this.completionToken, scope.enclosingSourceType());
 				}
 			} else {
 				
 				if (astNode instanceof CompletionOnSingleNameReference) {
 					CompletionOnSingleNameReference singleNameReference = (CompletionOnSingleNameReference) astNode;
-					completionToken = singleNameReference.token;
+					this.completionToken = singleNameReference.token;
 					findVariablesAndMethods(
-						completionToken,
+						this.completionToken,
 						scope,
 						(CompletionOnSingleNameReference) astNode,
 						scope);
 					// can be the start of a qualified type name
-					findTypesAndPackages(completionToken, scope);
-					findKeywords(completionToken, singleNameReference.possibleKeywords);
+					findTypesAndPackages(this.completionToken, scope);
+					findKeywords(this.completionToken, singleNameReference.possibleKeywords);
 					if(singleNameReference.canBeExplicitConstructor){
-						if(CharOperation.prefixEquals(completionToken, Keywords.THIS, false)) {
+						if(CharOperation.prefixEquals(this.completionToken, Keywords.THIS, false)) {
 							ReferenceBinding ref = scope.enclosingSourceType();
 							findExplicitConstructors(Keywords.THIS, ref, (MethodScope)scope, singleNameReference);
-						} else if(CharOperation.prefixEquals(completionToken, Keywords.SUPER, false)) {
+						} else if(CharOperation.prefixEquals(this.completionToken, Keywords.SUPER, false)) {
 							ReferenceBinding ref = scope.enclosingSourceType();
 							findExplicitConstructors(Keywords.SUPER, ref.superclass(), (MethodScope)scope, singleNameReference);
 						}
@@ -468,30 +587,32 @@
 	
 					if (astNode instanceof CompletionOnSingleTypeReference) {
 	
-						completionToken = ((CompletionOnSingleTypeReference) astNode).token;
+						this.completionToken = ((CompletionOnSingleTypeReference) astNode).token;
 						
-						assistNodeIsClass = astNode instanceof CompletionOnClassReference;
-						assistNodeIsException = astNode instanceof CompletionOnExceptionReference;
-						assistNodeIsInterface = astNode instanceof CompletionOnInterfaceReference;
+						this.assistNodeIsClass = astNode instanceof CompletionOnClassReference;
+						this.assistNodeIsException = astNode instanceof CompletionOnExceptionReference;
+						this.assistNodeIsInterface = astNode instanceof CompletionOnInterfaceReference;
 	
 						// can be the start of a qualified type name
 						if (qualifiedBinding == null) {
-							findTypesAndPackages(completionToken, scope);
+							findTypesAndPackages(this.completionToken, scope);
 							} else {
 								findMemberTypes(
-								completionToken,
+								this.completionToken,
 								(ReferenceBinding) qualifiedBinding,
 								scope,
-								scope.enclosingSourceType());
+								scope.enclosingSourceType(),
+								false,
+								new ObjectVector());
 						}
 					} else {
 						
 						if (astNode instanceof CompletionOnQualifiedNameReference) {
 	
-							insideQualifiedReference = true;
+							this.insideQualifiedReference = true;
 							CompletionOnQualifiedNameReference ref =
 								(CompletionOnQualifiedNameReference) astNode;
-							completionToken = ref.completionIdentifier;
+							this.completionToken = ref.completionIdentifier;
 							long completionPosition = ref.sourcePositions[ref.sourcePositions.length - 1];
 	
 							if (qualifiedBinding instanceof VariableBinding) {
@@ -499,7 +620,7 @@
 								setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
 								TypeBinding receiverType = ((VariableBinding) qualifiedBinding).type;
 								if (receiverType != null) {
-									findFieldsAndMethods(completionToken, receiverType, scope, ref, scope,false,false);
+									findFieldsAndMethods(this.completionToken, receiverType, scope, ref, scope,false,false);
 								}
 	
 							} else {
@@ -509,26 +630,37 @@
 									ReferenceBinding receiverType = (ReferenceBinding) qualifiedBinding;
 									setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
 	
-									findMemberTypes(completionToken, receiverType, scope, scope.enclosingSourceType());
+									findMemberTypes(this.completionToken, receiverType, scope, scope.enclosingSourceType(), false, new ObjectVector());
 	
-									findClassField(completionToken, (TypeBinding) qualifiedBinding, scope);
+									findClassField(this.completionToken, (TypeBinding) qualifiedBinding, scope);
 									
 									MethodScope methodScope = null;
 									if((scope instanceof MethodScope && !((MethodScope)scope).isStatic)
 										|| ((methodScope = scope.enclosingMethodScope()) != null && !methodScope.isStatic)) {
-										if(completionToken.length > 0) {
-											findKeywords(completionToken, new char[][]{Keywords.THIS});
+										if(this.completionToken.length > 0) {
+											findKeywords(this.completionToken, new char[][]{Keywords.THIS});
 										} else {
 											int relevance = computeBaseRelevance();
 											relevance += computeRelevanceForInterestingProposal();
-											relevance += computeRelevanceForCaseMatching(completionToken, Keywords.THIS);
-											noProposal = false;
-											requestor.acceptKeyword(Keywords.THIS, startPosition - offset, endPosition - offset,relevance);
+											relevance += computeRelevanceForCaseMatching(this.completionToken, Keywords.THIS);
+											relevance += computeRelevanceForRestrictions(false); // no access restriction for keywords
+											this.noProposal = false;
+											if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
+												CompletionProposal proposal = this.createProposal(CompletionProposal.KEYWORD, this.actualCompletionPosition);
+												proposal.setName(Keywords.THIS);
+												proposal.setCompletion(Keywords.THIS);
+												proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+												proposal.setRelevance(relevance);
+												this.requestor.accept(proposal);
+												if(DEBUG) {
+													this.printDebug(proposal);
+												}
+											}
 										}
 									}
 	
 									findFields(
-										completionToken,
+										this.completionToken,
 										receiverType,
 										scope,
 										new ObjectVector(),
@@ -536,10 +668,11 @@
 										true,
 										ref,
 										scope,
-										false);
+										false,
+										true);
 	
 									findMethods(
-										completionToken,
+										this.completionToken,
 										null,
 										receiverType,
 										scope,
@@ -550,7 +683,8 @@
 										ref,
 										scope,
 										false,
-										false);
+										false,
+										true);
 	
 								} else {
 	
@@ -558,7 +692,7 @@
 	
 										setSourceRange(astNode.sourceStart, (int) completionPosition);
 										// replace to the end of the completion identifier
-										findTypesAndSubpackages(completionToken, (PackageBinding) qualifiedBinding);
+										findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding);
 									}
 								}
 							}
@@ -567,15 +701,15 @@
 	
 								if (astNode instanceof CompletionOnQualifiedTypeReference) {
 	
-								insideQualifiedReference = true;
+								this.insideQualifiedReference = true;
 								
-								assistNodeIsClass = astNode instanceof CompletionOnQualifiedClassReference;
-								assistNodeIsException = astNode instanceof CompletionOnQualifiedExceptionReference;
-								assistNodeIsInterface = astNode instanceof CompletionOnQualifiedInterfaceReference;
+								this.assistNodeIsClass = astNode instanceof CompletionOnQualifiedClassReference;
+								this.assistNodeIsException = astNode instanceof CompletionOnQualifiedExceptionReference;
+								this.assistNodeIsInterface = astNode instanceof CompletionOnQualifiedInterfaceReference;
 								
 								CompletionOnQualifiedTypeReference ref =
 									(CompletionOnQualifiedTypeReference) astNode;
-								completionToken = ref.completionIdentifier;
+								this.completionToken = ref.completionIdentifier;
 								long completionPosition = ref.sourcePositions[ref.tokens.length];
 	
 								// get the source positions of the completion identifier
@@ -583,10 +717,12 @@
 	
 									setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
 									findMemberTypes(
-										completionToken,
+										this.completionToken,
 										(ReferenceBinding) qualifiedBinding,
 										scope,
-										scope.enclosingSourceType());
+										scope.enclosingSourceType(),
+										false,
+										new ObjectVector());
 	
 								} else {
 	
@@ -594,24 +730,24 @@
 	
 										setSourceRange(astNode.sourceStart, (int) completionPosition);
 										// replace to the end of the completion identifier
-										findTypesAndSubpackages(completionToken, (PackageBinding) qualifiedBinding);
+										findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding);
 									}
 								}
 	
 							} else {
 	
 								if (astNode instanceof CompletionOnMemberAccess) {
-									insideQualifiedReference = true;
+									this.insideQualifiedReference = true;
 									CompletionOnMemberAccess access = (CompletionOnMemberAccess) astNode;
 									long completionPosition = access.nameSourcePosition;
 									setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
 					
-									completionToken = access.token;
+									this.completionToken = access.token;
 									
-									findKeywords(completionToken, new char[][]{Keywords.NEW});
+									findKeywords(this.completionToken, new char[][]{Keywords.NEW});
 									
 									findFieldsAndMethods(
-										completionToken,
+										this.completionToken,
 										(TypeBinding) qualifiedBinding,
 										scope,
 										access,
@@ -627,14 +763,14 @@
 										CompletionOnMessageSend messageSend = (CompletionOnMessageSend) astNode;
 										TypeBinding[] argTypes =
 											computeTypes(messageSend.arguments, (BlockScope) scope);
-										completionToken = messageSend.selector;
+										this.completionToken = messageSend.selector;
 										if (qualifiedBinding == null) {
 											
-											findImplicitMessageSends(completionToken, argTypes, scope, messageSend, scope);
+											findImplicitMessageSends(this.completionToken, argTypes, scope, messageSend, scope);
 										} else {
 	
 											findMethods(
-												completionToken,
+												this.completionToken,
 												argTypes,
 												(ReferenceBinding) qualifiedBinding,
 												scope,
@@ -645,7 +781,8 @@
 												messageSend,
 												scope,
 												false,
-												messageSend.receiver instanceof SuperReference);
+												messageSend.receiver instanceof SuperReference,
+												true);
 										}
 	
 									} else {
@@ -699,9 +836,9 @@
 													CompletionOnClassLiteralAccess access = (CompletionOnClassLiteralAccess) astNode;
 													setSourceRange(access.classStart, access.sourceEnd);
 									
-													completionToken = access.completionIdentifier;
+													this.completionToken = access.completionIdentifier;
 									
-													findClassField(completionToken, (TypeBinding) qualifiedBinding, scope);
+													findClassField(this.completionToken, (TypeBinding) qualifiedBinding, scope);
 												} else {
 													if(astNode instanceof CompletionOnMethodName) {
 														CompletionOnMethodName method = (CompletionOnMethodName) astNode;
@@ -714,9 +851,9 @@
 															excludeNames[i] = fields[i].name;
 														}
 														
-														completionToken = method.selector;
+														this.completionToken = method.selector;
 														
-														findVariableNames(completionToken, method.returnType, excludeNames, FIELD, method.modifiers);
+														findVariableNames(this.completionToken, method.returnType, excludeNames, FIELD, method.modifiers);
 													} else {
 														if (astNode instanceof CompletionOnFieldName) {
 															CompletionOnFieldName field = (CompletionOnFieldName) astNode;
@@ -727,7 +864,7 @@
 																excludeNames[i] = fields[i].name;
 															}
 															
-															completionToken = field.realName;
+															this.completionToken = field.realName;
 															
 															findVariableNames(field.realName, field.type, excludeNames, FIELD, field.modifiers);
 														} else {
@@ -746,17 +883,53 @@
 																System.arraycopy(excludeNames, 0, excludeNames = new char[localCount][], 0, localCount);
 																
 																if(variable instanceof CompletionOnLocalName){
-																	completionToken = ((CompletionOnLocalName) variable).realName;
-																	findVariableNames(completionToken, variable.type, excludeNames, LOCAL, variable.modifiers);
+																	this.completionToken = ((CompletionOnLocalName) variable).realName;
+																	findVariableNames(this.completionToken, variable.type, excludeNames, LOCAL, variable.modifiers);
 																} else {
 																	CompletionOnArgumentName arg = (CompletionOnArgumentName) variable;
-																	completionToken = arg.realName;
-																	findVariableNames(completionToken, variable.type, excludeNames, arg.isCatchArgument ? LOCAL : ARGUMENT, variable.modifiers);
+																	this.completionToken = arg.realName;
+																	findVariableNames(this.completionToken, variable.type, excludeNames, arg.isCatchArgument ? LOCAL : ARGUMENT, variable.modifiers);
 																}
 															} else {
 																if(astNode instanceof CompletionOnKeyword) {
 																	CompletionOnKeyword keyword = (CompletionOnKeyword)astNode;
 																	findKeywords(keyword.getToken(), keyword.getPossibleKeywords());
+																} else if(astNode instanceof CompletionOnParameterizedQualifiedTypeReference) {
+																	CompletionOnParameterizedQualifiedTypeReference ref = (CompletionOnParameterizedQualifiedTypeReference) astNode;
+																	
+																	this.insideQualifiedReference = true;
+							
+																	this.assistNodeIsClass = ref.isClass();
+																	this.assistNodeIsException = ref.isException();
+																	this.assistNodeIsInterface = ref.isInterface();
+																	
+																	this.completionToken = ref.completionIdentifier;
+																	long completionPosition = ref.sourcePositions[ref.tokens.length];
+																	setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+																	findMemberTypes(
+																		this.completionToken,
+																		(ReferenceBinding) qualifiedBinding,
+																		scope,
+																		scope.enclosingSourceType(),
+																		false,
+																		new ObjectVector());
+																} else if(astNode instanceof CompletionOnMarkerAnnotationName) {
+																	CompletionOnMarkerAnnotationName annot = (CompletionOnMarkerAnnotationName) astNode;
+																	
+																	this.assistNodeIsAnnotation = true;
+																	if(annot.type instanceof CompletionOnSingleTypeReference) {
+																		CompletionOnSingleTypeReference type = (CompletionOnSingleTypeReference) annot.type;
+																		this.completionToken = type.token;
+																		setSourceRange(type.sourceStart, type.sourceEnd);
+																		
+																		findTypesAndPackages(this.completionToken, scope);
+																	} else if(annot.type instanceof CompletionOnQualifiedTypeReference) {
+																		CompletionOnQualifiedTypeReference type = (CompletionOnQualifiedTypeReference) annot.type;
+																		this.completionToken = type.completionIdentifier;
+																		setSourceRange(type.sourceStart, type.sourceEnd);
+																		
+																		findTypesAndPackages(this.completionToken, scope);
+																	}
 																}
 															}
 														}
@@ -775,19 +948,39 @@
 	}
 	
 	public void complete(IType type, char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){	
-
+		if(this.requestor != null){
+			this.requestor.beginReporting();
+		}
+		
 		IType topLevelType = type;
 		while(topLevelType.getDeclaringType() != null) {
 			topLevelType = topLevelType.getDeclaringType();
 		}
 		
-		CompilationResult compilationResult = new CompilationResult((topLevelType.getElementName() + SUFFIX_STRING_java).toCharArray(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
+		CompilationResult compilationResult = new CompilationResult(topLevelType.getParent().getElementName().toCharArray(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
 	
-		CompilationUnitDeclaration compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, 0);
+		CompilationUnitDeclaration compilationUnit = null;
 	
 		try {
-			//TODO (david) should be instead be using SourceTypeConverter?
-			TypeDeclaration typeDeclaration = TypeConverter.buildTypeDeclaration(type, compilationUnit, compilationResult);
+			// TypeConverter is used instead of SourceTypeConverter because the type
+			// to convert can be a binary type or a source type
+			TypeDeclaration typeDeclaration = null;
+			if (type instanceof SourceType) {
+				SourceType sourceType = (SourceType) type;
+				ISourceType info = (ISourceType) sourceType.getElementInfo();
+				compilationUnit = SourceTypeConverter.buildCompilationUnit(
+					new ISourceType[] {info},//sourceTypes[0] is always toplevel here
+					SourceTypeConverter.FIELD_AND_METHOD // need field and methods
+					| SourceTypeConverter.MEMBER_TYPE, // need member types
+					// no need for field initialization
+					this.problemReporter,
+					compilationResult);
+				if (compilationUnit.types != null)
+					typeDeclaration = compilationUnit.types[0];
+			} else {
+				compilationUnit = new CompilationUnitDeclaration(this.problemReporter, compilationResult, 0);
+				typeDeclaration = BinaryTypeConverter.buildTypeDeclaration(type, compilationUnit, compilationResult);
+			}
 		
 			if(typeDeclaration != null) {	
 				// build AST from snippet
@@ -795,9 +988,14 @@
 				
 				// merge AST
 				FieldDeclaration[] oldFields = typeDeclaration.fields;
-				FieldDeclaration[] newFields = new FieldDeclaration[oldFields.length + 1];
-				System.arraycopy(oldFields, 0, newFields, 0, oldFields.length);
-				newFields[oldFields.length] = fakeInitializer;
+				FieldDeclaration[] newFields = null;
+				if (oldFields != null) {
+					newFields = new FieldDeclaration[oldFields.length + 1];
+					System.arraycopy(oldFields, 0, newFields, 0, oldFields.length);
+					newFields[oldFields.length] = fakeInitializer;
+				} else {
+					newFields = new FieldDeclaration[] {fakeInitializer};
+				}
 				typeDeclaration.fields = newFields;
 		
 				if(DEBUG) {
@@ -807,10 +1005,10 @@
 				
 				if (compilationUnit.types != null) {
 					try {
-						lookupEnvironment.buildTypeBindings(compilationUnit);
+						this.lookupEnvironment.buildTypeBindings(compilationUnit, null /*no access restriction*/);
 				
-						if ((unitScope = compilationUnit.scope) != null) {
-							lookupEnvironment.completeTypeBindings(compilationUnit, true);
+						if ((this.unitScope = compilationUnit.scope) != null) {
+							this.lookupEnvironment.completeTypeBindings(compilationUnit, true);
 							compilationUnit.scope.faultInTypes();
 							compilationUnit.resolve();
 						}
@@ -818,17 +1016,24 @@
 						//					completionNodeFound = true;
 						if (e.astNode != null) {
 							// if null then we found a problem in the completion node
-							complete(e.astNode, parser.assistNodeParent, e.qualifiedBinding, e.scope);
+							complete(e.astNode, this.parser.assistNodeParent, e.qualifiedBinding, e.scope);
 						}
 					}
 				}
-				if(noProposal && problem != null) {
-					requestor.acceptError(problem);
+				if(this.noProposal && this.problem != null) {
+					this.requestor.completionFailure(this.problem);
+					if(DEBUG) {
+						this.printDebug(this.problem);
+					}
 				}
 			}
 		} catch(JavaModelException e) {
 			// Do nothing
 		}
+		
+		if(this.requestor != null){
+			this.requestor.endReporting();
+		}
 	}
 	
 	private Initializer parseSnippeInitializer(char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){
@@ -848,7 +1053,7 @@
 		}
 		
 		char[] fakeSource = CharOperation.concat(prefix.toString().toCharArray(), snippet, "}}".toCharArray());//$NON-NLS-1$ 
-		offset = prefix.length();
+		this.offset = prefix.length();
 		
 		String encoding = this.compilerOptions.defaultEncoding;
 		BasicCompilationUnit fakeUnit = new BasicCompilationUnit(
@@ -857,12 +1062,12 @@
 			"FakeType.java", //$NON-NLS-1$
 			encoding); 
 			
-		actualCompletionPosition = prefix.length() + position - 1;
+		this.actualCompletionPosition = prefix.length() + position - 1;
 			
 		CompilationResult fakeResult = new CompilationResult(fakeUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
-		CompilationUnitDeclaration fakeAST = parser.dietParse(fakeUnit, fakeResult, actualCompletionPosition);
+		CompilationUnitDeclaration fakeAST = this.parser.dietParse(fakeUnit, fakeResult, this.actualCompletionPosition);
 		
-		parseBlockStatements(fakeAST, actualCompletionPosition);
+		parseBlockStatements(fakeAST, this.actualCompletionPosition);
 		
 		return (Initializer)fakeAST.types[0].fields[0];
 	}
@@ -891,12 +1096,16 @@
 			System.out.println("COMPLETION - Source :"); //$NON-NLS-1$
 			System.out.println(sourceUnit.getContents());
 		}
+		if(this.requestor != null){
+			this.requestor.beginReporting();
+		}
+		
 		try {
-			actualCompletionPosition = completionPosition - 1;
+			this.actualCompletionPosition = completionPosition - 1;
 			this.offset = pos;
 			// for now until we can change the UI.
 			CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
-			CompilationUnitDeclaration parsedUnit = parser.dietParse(sourceUnit, result, actualCompletionPosition);
+			CompilationUnitDeclaration parsedUnit = this.parser.dietParse(sourceUnit, result, this.actualCompletionPosition);
 
 			//		boolean completionNodeFound = false;
 			if (parsedUnit != null) {
@@ -908,8 +1117,11 @@
 				// scan the package & import statements first
 				if (parsedUnit.currentPackage instanceof CompletionOnPackageReference) {
 					findPackages((CompletionOnPackageReference) parsedUnit.currentPackage);
-					if(noProposal && problem != null) {
-						requestor.acceptError(problem);
+					if(this.noProposal && this.problem != null) {
+						this.requestor.completionFailure(this.problem);
+						if(DEBUG) {
+							this.printDebug(this.problem);
+						}
 					}
 					return;
 				}
@@ -920,16 +1132,39 @@
 						ImportReference importReference = imports[i];
 						if (importReference instanceof CompletionOnImportReference) {
 							findImports((CompletionOnImportReference) importReference);
-							if(noProposal && problem != null) {
-								requestor.acceptError(problem);
+							if(this.noProposal && this.problem != null) {
+								this.requestor.completionFailure(this.problem);
+								if(DEBUG) {
+									this.printDebug(this.problem);
+								}
+							}
+							if(importReference.isStatic()) {
+								this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
+								if ((this.unitScope = parsedUnit.scope) != null) {
+									char[][] oldTokens = importReference.tokens;
+									int tokenCount = oldTokens.length;
+									char[] lastToken = oldTokens[tokenCount - 1];
+									char[][] qualifierTokens = CharOperation.subarray(oldTokens, 0, tokenCount - 1);
+									
+									Binding binding = this.unitScope.getTypeOrPackage(qualifierTokens);
+									if(binding != null && binding instanceof ReferenceBinding) {
+										ReferenceBinding ref = (ReferenceBinding) binding;
+										this.findImportsOfMemberTypes(lastToken, ref);
+										this.findImportsOfStaticFields(lastToken, ref);
+										this.findImportsOfStaticMethdods(lastToken, ref);
+									}
+								}
 							}
 							return;
 						} else if(importReference instanceof CompletionOnKeyword) {
 							setSourceRange(importReference.sourceStart, importReference.sourceEnd);
 							CompletionOnKeyword keyword = (CompletionOnKeyword)importReference;
 							findKeywords(keyword.getToken(), keyword.getPossibleKeywords());
-							if(noProposal && problem != null) {
-								requestor.acceptError(problem);
+							if(this.noProposal && this.problem != null) {
+								this.requestor.completionFailure(this.problem);
+								if(DEBUG) {
+									this.printDebug(this.problem);
+								}
 							}
 							return;
 						}
@@ -938,13 +1173,13 @@
 
 				if (parsedUnit.types != null) {
 					try {
-						lookupEnvironment.buildTypeBindings(parsedUnit);
+						this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
 
-						if ((unitScope = parsedUnit.scope) != null) {
-							source = sourceUnit.getContents();
-							lookupEnvironment.completeTypeBindings(parsedUnit, true);
+						if ((this.unitScope = parsedUnit.scope) != null) {
+							this.source = sourceUnit.getContents();
+							this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
 							parsedUnit.scope.faultInTypes();
-							parseBlockStatements(parsedUnit, actualCompletionPosition);
+							parseBlockStatements(parsedUnit, this.actualCompletionPosition);
 							if(DEBUG) {
 								System.out.println("COMPLETION - AST :"); //$NON-NLS-1$
 								System.out.println(parsedUnit.toString());
@@ -957,25 +1192,28 @@
 							if(DEBUG) {
 								System.out.print("COMPLETION - Completion node : "); //$NON-NLS-1$
 								System.out.println(e.astNode.toString());
-								if(parser.assistNodeParent != null) {
+								if(this.parser.assistNodeParent != null) {
 									System.out.print("COMPLETION - Parent Node : ");  //$NON-NLS-1$
-									System.out.println(parser.assistNodeParent);
+									System.out.println(this.parser.assistNodeParent);
 								}
 							}
 							// if null then we found a problem in the completion node
-							complete(e.astNode, parser.assistNodeParent, e.qualifiedBinding, e.scope);
+							complete(e.astNode, this.parser.assistNodeParent, e.qualifiedBinding, e.scope);
 						}
 					}
 				}
 			}
-			if(noProposal && problem != null) {
-				requestor.acceptError(problem);
+			if(this.noProposal && this.problem != null) {
+				this.requestor.completionFailure(this.problem);
+				if(DEBUG) {
+					this.printDebug(this.problem);
+				}
 			}
 			/* Ignore package, import, class & interface keywords for now...
 					if (!completionNodeFound) {
 						if (parsedUnit == null || parsedUnit.types == null) {
 							// this is not good enough... can still be trying to define a second type
-							CompletionScanner scanner = (CompletionScanner) parser.scanner;
+							CompletionScanner scanner = (CompletionScanner) this.parser.scanner;
 							setSourceRange(scanner.completedIdentifierStart, scanner.completedIdentifierEnd);
 							findKeywords(scanner.completionIdentifier, mainDeclarations, null);
 						}
@@ -983,12 +1221,32 @@
 					}
 			*/
 		} catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D
+			if(DEBUG) {
+				System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
+				e.printStackTrace(System.out);
+			}
 		} catch (InvalidCursorLocation e) { // may eventually report a usefull error
+			if(DEBUG) {
+				System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
+				e.printStackTrace(System.out);
+			}
 		} catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
+			if(DEBUG) {
+				System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
+				e.printStackTrace(System.out);
+			}
 		} catch (CompletionNodeFound e){ // internal failure - bugs 5618
+			if(DEBUG) {
+				System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
+				e.printStackTrace(System.out);
+			}
 		} finally {
 			reset();
 		}
+		
+		if(this.requestor != null){
+			this.requestor.endReporting();
+		}
 	}
 
 	private TypeBinding[] computeTypes(Expression[] arguments, BlockScope scope) {
@@ -1010,27 +1268,45 @@
 		InvocationSite invocationSite) {
 
 		if (currentType.isInterface()) {
+			boolean hasRestrictedAccess = false;
+//			boolean hasRestrictedAccess = currentType.hasRestrictedAccess();
+//			if(this.options.checkRestrictions && hasRestrictedAccess) return;
+			
 			char[] completion = CharOperation.NO_CHAR;
 			// nothing to insert - do not want to replace the existing selector & arguments
-			if (source == null
-				|| source.length <= endPosition
-				|| source[endPosition] != ')')
+			if (this.source == null
+				|| this.source.length <= this.endPosition
+				|| this.source[this.endPosition] != ')')
 				completion = new char[] { ')' };
 			int relevance = computeBaseRelevance();
 			relevance += computeRelevanceForInterestingProposal();
+			relevance += computeRelevanceForRestrictions(hasRestrictedAccess);
 			
-			noProposal = false;
-			requestor.acceptAnonymousType(
-				currentType.qualifiedPackageName(),
-				currentType.qualifiedSourceName(),
-				CharOperation.NO_CHAR_CHAR,
-				CharOperation.NO_CHAR_CHAR,
-				CharOperation.NO_CHAR_CHAR,
-				completion,
-				IConstants.AccPublic,
-				endPosition - offset,
-				endPosition - offset,
-				relevance);
+			this.noProposal = false;
+			if(!this.requestor.isIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION)) {
+				CompletionProposal proposal = this.createProposal(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, this.actualCompletionPosition);
+				proposal.setDeclarationSignature(getSignature(currentType));
+				proposal.setSignature(
+						createMethodSignature(
+								CharOperation.NO_CHAR_CHAR,
+								CharOperation.NO_CHAR_CHAR,
+								CharOperation.NO_CHAR,
+								CharOperation.NO_CHAR));
+				proposal.setDeclarationPackageName(currentType.qualifiedPackageName());
+				proposal.setDeclarationTypeName(currentType.qualifiedSourceName());
+				//proposal.setParameterPackageNames(null);
+				//proposal.setParameterTypeNames(null);
+				//proposal.setPackageName(null);
+				//proposal.setTypeName(null);
+				proposal.setCompletion(completion);
+				proposal.setFlags(Flags.AccPublic);
+				proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset);
+				proposal.setRelevance(relevance);
+				this.requestor.accept(proposal);
+				if(DEBUG) {
+					this.printDebug(proposal);
+				}
+			}
 		} else {
 			findConstructors(
 				currentType,
@@ -1053,19 +1329,30 @@
 			relevance += computeRelevanceForInterestingProposal();
 			relevance += computeRelevanceForCaseMatching(token, classField);
 			relevance += computeRelevanceForExpectingType(scope.getJavaLangClass());
+			relevance += computeRelevanceForRestrictions(false); //no access restriction for class field 
 			
-			noProposal = false;
-			requestor.acceptField(
-				CharOperation.NO_CHAR,
-				CharOperation.NO_CHAR,
-				classField,
-				CharOperation.NO_CHAR,
-				CharOperation.NO_CHAR,
-				classField,
-				IConstants.AccStatic | IConstants.AccPublic,
-				startPosition - offset,
-				endPosition - offset,
-				relevance);
+			this.noProposal = false;
+			if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) {
+				CompletionProposal proposal = this.createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
+				//proposal.setDeclarationSignature(null);
+				proposal.setSignature(
+						createNonGenericTypeSignature(
+								CharOperation.concatWith(JAVA_LANG, '.'),
+								CLASS));
+				//proposal.setDeclarationPackageName(null);
+				//proposal.setDeclarationTypeName(null);
+				proposal.setPackageName(CharOperation.concatWith(JAVA_LANG, '.'));
+				proposal.setTypeName(CLASS);
+				proposal.setName(classField);
+				proposal.setCompletion(classField);
+				proposal.setFlags(Flags.AccStatic | Flags.AccPublic);
+				proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+				proposal.setRelevance(relevance);
+				this.requestor.accept(proposal);
+				if(DEBUG) {
+					this.printDebug(proposal);
+				}
+			}
 		}
 	}
 
@@ -1087,9 +1374,13 @@
 					
 					if (constructor.isSynthetic()) continue next;
 						
-					if (options.checkVisibility
+					if (this.options.checkVisibility
 						&& !constructor.canBeSeenBy(invocationSite, scope))	continue next;
 	
+					boolean hasRestrictedAccess = false;
+//					boolean hasRestrictedAccess = constructor.declaringClass.hasRestrictedAccess();
+//					if(this.options.checkRestrictions && hasRestrictedAccess) continue next;
+					
 					TypeBinding[] parameters = constructor.parameters;
 					int paramLength = parameters.length;
 	
@@ -1103,32 +1394,40 @@
 					char[][] parameterNames = findMethodParameterNames(constructor,parameterTypeNames);
 					
 					char[] completion = CharOperation.NO_CHAR;
-					if (source != null
-						&& source.length > endPosition
-						&& source[endPosition] == '(')
+					if (this.source != null
+						&& this.source.length > this.endPosition
+						&& this.source[this.endPosition] == '(')
 						completion = name;
 					else
 						completion = CharOperation.concat(name, new char[] { '(', ')' });
 					
 					int relevance = computeBaseRelevance();
 					relevance += computeRelevanceForInterestingProposal();
-					relevance += computeRelevanceForCaseMatching(completionToken, name);
+					relevance += computeRelevanceForCaseMatching(this.completionToken, name);
+					relevance += computeRelevanceForRestrictions(hasRestrictedAccess);
 					
-					noProposal = false;
-					requestor.acceptMethod(
-						currentType.qualifiedPackageName(),
-						currentType.qualifiedSourceName(),
-						name,
-						parameterPackageNames,
-						parameterTypeNames,
-						parameterNames,
-						CharOperation.NO_CHAR,
-						CharOperation.NO_CHAR,
-						completion,
-						constructor.modifiers,
-						startPosition - offset,
-						endPosition - offset,
-						relevance);
+					this.noProposal = false;
+					if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
+						CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
+						proposal.setDeclarationSignature(getSignature(currentType));
+						proposal.setSignature(getSignature(constructor));
+						proposal.setDeclarationPackageName(currentType.qualifiedPackageName());
+						proposal.setDeclarationTypeName(currentType.qualifiedSourceName());
+						proposal.setParameterPackageNames(parameterPackageNames);
+						proposal.setParameterTypeNames(parameterTypeNames);
+						//proposal.setPackageName(null);
+						//proposal.setTypeName(null);
+						proposal.setName(name);
+						proposal.setCompletion(completion);
+						proposal.setFlags(constructor.modifiers);
+						proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+						proposal.setRelevance(relevance);
+						if(parameterNames != null) proposal.setParameterNames(parameterNames);
+						this.requestor.accept(proposal);
+						if(DEBUG) {
+							this.printDebug(proposal);
+						}
+					}
 				}
 			}
 		}
@@ -1150,12 +1449,16 @@
 					
 					if (constructor.isSynthetic()) continue next;
 						
-					if (options.checkVisibility
+					if (this.options.checkVisibility
 						&& !constructor.canBeSeenBy(invocationSite, scope)) {
 						if(!forAnonymousType || !constructor.isProtected())
 							continue next;
 					}
-	
+					
+					boolean hasRestrictedAccess = false;
+//					boolean hasRestrictedAccess = constructor.declaringClass.hasRestrictedAccess();
+//					if(this.options.checkRestrictions && hasRestrictedAccess) continue next;
+					
 					TypeBinding[] parameters = constructor.parameters;
 					int paramLength = parameters.length;
 					if (minArgLength > paramLength)
@@ -1176,46 +1479,64 @@
 					
 					char[] completion = CharOperation.NO_CHAR;
 					// nothing to insert - do not want to replace the existing selector & arguments
-					if (source == null
-						|| source.length <= endPosition
-						|| source[endPosition] != ')')
+					if (this.source == null
+						|| this.source.length <= this.endPosition
+						|| this.source[this.endPosition] != ')')
 						completion = new char[] { ')' };
 					
 					if(forAnonymousType){
 						int relevance = computeBaseRelevance();
 						relevance += computeRelevanceForInterestingProposal();
+						relevance += computeRelevanceForRestrictions(hasRestrictedAccess);
 						
-						noProposal = false;
-						requestor.acceptAnonymousType(
-							currentType.qualifiedPackageName(),
-							currentType.qualifiedSourceName(),
-							parameterPackageNames,
-							parameterTypeNames,
-							parameterNames,
-							completion,
-							constructor.modifiers,
-							endPosition - offset,
-							endPosition - offset,
-							relevance);
+						this.noProposal = false;
+						if(!this.requestor.isIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION)) {
+							CompletionProposal proposal = this.createProposal(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, this.actualCompletionPosition);
+							proposal.setDeclarationSignature(getSignature(currentType));
+							proposal.setSignature(getSignature(constructor));
+							proposal.setDeclarationPackageName(currentType.qualifiedPackageName());
+							proposal.setDeclarationTypeName(currentType.qualifiedSourceName());
+							proposal.setParameterPackageNames(parameterPackageNames);
+							proposal.setParameterTypeNames(parameterTypeNames);
+							//proposal.setPackageName(null);
+							//proposal.setTypeName(null);
+							proposal.setCompletion(completion);
+							proposal.setFlags(constructor.modifiers);
+							proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset);
+							proposal.setRelevance(relevance);
+							if(parameterNames != null) proposal.setParameterNames(parameterNames);
+							this.requestor.accept(proposal);
+							if(DEBUG) {
+								this.printDebug(proposal);
+							}
+						}
 					} else {
 						int relevance = computeBaseRelevance();
 						relevance += computeRelevanceForInterestingProposal();
+						relevance += computeRelevanceForRestrictions(hasRestrictedAccess);
 						
-						noProposal = false;
-						requestor.acceptMethod(
-							currentType.qualifiedPackageName(),
-							currentType.qualifiedSourceName(),
-							currentType.sourceName(),
-							parameterPackageNames,
-							parameterTypeNames,
-							parameterNames,
-							CharOperation.NO_CHAR,
-							CharOperation.NO_CHAR,
-							completion,
-							constructor.modifiers,
-							endPosition - offset,
-							endPosition - offset,
-							relevance);
+						this.noProposal = false;
+						if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
+							CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
+							proposal.setDeclarationSignature(getSignature(currentType));
+							proposal.setSignature(getSignature(constructor));
+							proposal.setDeclarationPackageName(currentType.qualifiedPackageName());
+							proposal.setDeclarationTypeName(currentType.qualifiedSourceName());
+							proposal.setParameterPackageNames(parameterPackageNames);
+							proposal.setParameterTypeNames(parameterTypeNames);
+							//proposal.setPackageName(null);
+							//proposal.setTypeName(null);
+							proposal.setName(currentType.sourceName());
+							proposal.setCompletion(completion);
+							proposal.setFlags(constructor.modifiers);
+							proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset);
+							proposal.setRelevance(relevance);
+							if(parameterNames != null) proposal.setParameterNames(parameterNames);
+							this.requestor.accept(proposal);
+							if(DEBUG) {
+								this.printDebug(proposal);
+							}
+						}
 					}
 				}
 			}
@@ -1233,7 +1554,8 @@
 		ReferenceBinding receiverType,
 		InvocationSite invocationSite,
 		Scope invocationScope,
-		boolean implicitCall) {
+		boolean implicitCall,
+		boolean canBePrefixed) {
 
 		ObjectVector newFieldsFound = new ObjectVector();
 		// Inherited fields which are hidden by subclasses are filtered out
@@ -1251,8 +1573,12 @@
 
 			if (!CharOperation.prefixEquals(fieldName, field.name, false /* ignore case */))	continue next;
 
-			if (options.checkVisibility
+			if (this.options.checkVisibility
 				&& !field.canBeSeenBy(receiverType, invocationSite, scope))	continue next;
+			
+			boolean hasRestrictedAccess = false;
+//			boolean hasRestrictedAccess = field.declaringClass.hasRestrictedAccess();
+//			if(this.options.checkRestrictions && hasRestrictedAccess) continue next;
 
 			boolean prefixRequired = false;
 
@@ -1274,7 +1600,11 @@
 					if (field.declaringClass.isInterface())
 						if (otherField.declaringClass.implementsInterface(field.declaringClass, true))
 							continue next;
-					prefixRequired = true;
+					if(canBePrefixed) {
+						prefixRequired = true;
+					} else {
+						continue next;
+					}
 				}
 			}
 
@@ -1286,7 +1616,11 @@
 					if (declarationType.isAnonymousType() && declarationType != invocationScope.enclosingSourceType()) {
 						continue next;
 					}
-					prefixRequired = true;
+					if(canBePrefixed) {
+						prefixRequired = true;
+					} else {
+						continue next;
+					}
 					break;
 				}
 			}
@@ -1295,7 +1629,7 @@
 			
 			char[] completion = field.name;
 			
-			if(prefixRequired || options.forceImplicitQualification){
+			if(prefixRequired || this.options.forceImplicitQualification){
 				char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), field.isStatic());
 				completion = CharOperation.concat(prefix,completion,'.');
 			}
@@ -1306,19 +1640,27 @@
 			relevance += computeRelevanceForExpectingType(field.type);
 			relevance += computeRelevanceForStatic(onlyStaticFields, field.isStatic());
 			relevance += computeRelevanceForQualification(prefixRequired);
-
-			noProposal = false;
-			requestor
-				.acceptField(
-					field.declaringClass.qualifiedPackageName(),
-					field.declaringClass.qualifiedSourceName(),
-					field.name,
-					field.type.qualifiedPackageName(),
-					field.type.qualifiedSourceName(),
-					completion,
-			// may include some qualification to resolve ambiguities
-			field.modifiers, startPosition - offset, endPosition - offset,
-			relevance);
+			relevance += computeRelevanceForRestrictions(hasRestrictedAccess);
+			
+			this.noProposal = false;
+			if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) {
+				CompletionProposal proposal = this.createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
+				proposal.setDeclarationSignature(getSignature(field.declaringClass));
+				proposal.setSignature(getSignature(field.type));
+				proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
+				proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
+				proposal.setPackageName(field.type.qualifiedPackageName());
+				proposal.setTypeName(field.type.qualifiedSourceName()); 
+				proposal.setName(field.name);
+				proposal.setCompletion(completion);
+				proposal.setFlags(field.modifiers);
+				proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+				proposal.setRelevance(relevance);
+				this.requestor.accept(proposal);
+				if(DEBUG) {
+					this.printDebug(proposal);
+				}
+			}
 		}
 		
 		fieldsFound.addAll(newFieldsFound);
@@ -1333,7 +1675,8 @@
 		boolean onlyStaticFields,
 		InvocationSite invocationSite,
 		Scope invocationScope,
-		boolean implicitCall) {
+		boolean implicitCall,
+		boolean canBePrefixed) {
 
 		if (fieldName == null)
 			return;
@@ -1371,7 +1714,8 @@
 					receiverType,
 					invocationSite,
 					invocationScope,
-					implicitCall);
+					implicitCall,
+					canBePrefixed);
 			}
 			currentType = currentType.superclass();
 		} while (currentType != null);
@@ -1398,7 +1742,8 @@
 								receiverType,
 								invocationSite,
 								invocationScope,
-								implicitCall);
+								implicitCall,
+								canBePrefixed);
 						}
 
 						ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
@@ -1451,19 +1796,27 @@
 				relevance += computeRelevanceForInterestingProposal();
 				relevance += computeRelevanceForCaseMatching(token,lengthField);
 				relevance += computeRelevanceForExpectingType(BaseTypes.IntBinding);
+				relevance += computeRelevanceForRestrictions(false); // no access restriction for length field
 				
-				noProposal = false;
-				requestor.acceptField(
-					CharOperation.NO_CHAR,
-					CharOperation.NO_CHAR,
-					lengthField,
-					CharOperation.NO_CHAR,
-					CharOperation.NO_CHAR,
-					lengthField,
-					IConstants.AccPublic,
-					startPosition - offset,
-					endPosition - offset,
-					relevance);
+				this.noProposal = false;
+				if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) {
+					CompletionProposal proposal = this.createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
+					//proposal.setDeclarationSignature(null);
+					proposal.setSignature(INT_SIGNATURE);
+					//proposal.setDeclarationPackageName(null);
+					//proposal.setDeclarationTypeName(null);
+					//proposal.setPackageName(null);
+					proposal.setTypeName(INT);
+					proposal.setName(lengthField);
+					proposal.setCompletion(lengthField);
+					proposal.setFlags(Flags.AccPublic);
+					proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+					proposal.setRelevance(relevance);
+					this.requestor.accept(proposal);
+					if(DEBUG) {
+						this.printDebug(proposal);
+					}
+				}
 			}
 			if (token.length <= cloneMethod.length
 				&& CharOperation.prefixEquals(token, cloneMethod, false /* ignore case */
@@ -1476,31 +1829,42 @@
 				relevance += computeRelevanceForExpectingType(objectRef);
 				relevance += computeRelevanceForStatic(false, false);
 				relevance += computeRelevanceForQualification(false);
+				relevance += computeRelevanceForRestrictions(false); // no access restriction for clone() method
 				
 				char[] completion;
-				if (source != null
-					&& source.length > endPosition
-					&& source[endPosition] == '(') {
+				if (this.source != null
+					&& this.source.length > this.endPosition
+					&& this.source[this.endPosition] == '(') {
 					completion = cloneMethod;
 					} else {
 					completion = CharOperation.concat(cloneMethod, new char[] { '(', ')' });
 				}
-				noProposal = false;
-				requestor.acceptMethod(
-					CharOperation.NO_CHAR,
-					CharOperation.NO_CHAR,
-					cloneMethod,
-					CharOperation.NO_CHAR_CHAR,
-					CharOperation.NO_CHAR_CHAR,
-					CharOperation.NO_CHAR_CHAR,
-					CharOperation.concat(JAVA, LANG, '.'),
-					OBJECT,
-					completion,
-					IConstants.AccPublic,
-					startPosition - offset,
-					endPosition - offset,
-					relevance);
-					
+				this.noProposal = false;
+				if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
+					CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
+					//proposal.setDeclarationSignature(null);
+					proposal.setSignature(
+							createMethodSignature(
+									CharOperation.NO_CHAR_CHAR,
+									CharOperation.NO_CHAR_CHAR,
+									CharOperation.concatWith(JAVA_LANG, '.'),
+									OBJECT));
+					//proposal.setDeclarationPackageName(null);
+					//proposal.setDeclarationTypeName(null);
+					//proposal.setParameterPackageNames(null);
+					//proposal.setParameterTypeNames(null);
+					proposal.setPackageName(CharOperation.concatWith(JAVA_LANG, '.'));
+					proposal.setTypeName(OBJECT);
+					proposal.setName(cloneMethod);
+					proposal.setCompletion(completion);
+					proposal.setFlags(Flags.AccPublic);
+					proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+					proposal.setRelevance(relevance);
+					this.requestor.accept(proposal);
+					if(DEBUG) {
+						this.printDebug(proposal);
+					}
+				}
 				methodsFound.add(new Object[]{objectRef.getMethods(cloneMethod)[0], objectRef});
 			}
 			
@@ -1516,7 +1880,8 @@
 			false,
 			invocationSite,
 			invocationScope,
-			implicitCall);
+			implicitCall,
+			true);
 
 		findMethods(
 			token,
@@ -1530,7 +1895,8 @@
 			invocationSite,
 			invocationScope,
 			implicitCall,
-			superCall);
+			superCall,
+			true);
 	}
 
 	private void findImports(CompletionOnImportReference importReference) {
@@ -1545,17 +1911,241 @@
 		if(lastToken != null && lastToken.length == 0)
 			importName = CharOperation.concat(importName, new char[]{'.'});
 
-		resolvingImports = true;
+		this.resolvingImports = true;
 		setSourceRange(
 			importReference.sourceStart,
 			importReference.declarationSourceEnd);
 			
-		completionToken =  importName;
+		this.completionToken =  importName;
 		// want to replace the existing .*;
-		nameEnvironment.findPackages(importName, this);
-		nameEnvironment.findTypes(importName, this);
+		this.nameEnvironment.findPackages(importName, this);
+		this.nameEnvironment.findTypes(importName, this);
 	}
+	
+	private void findImportsOfMemberTypes(char[] typeName,	ReferenceBinding ref) {
+		ReferenceBinding[] memberTypes = ref.memberTypes();
+		
+		int typeLength = typeName.length;
+		next : for (int m = memberTypes.length; --m >= 0;) {
+			ReferenceBinding memberType = memberTypes[m];
+			//		if (!wantClasses && memberType.isClass()) continue next;
+			//		if (!wantInterfaces && memberType.isInterface()) continue next;
+			
+			if (typeLength > memberType.sourceName.length)
+				continue next;
 
+			if (!CharOperation.prefixEquals(typeName, memberType.sourceName, false
+				/* ignore case */
+				))
+				continue next;
+
+			if (this.options.checkVisibility
+				&& !memberType.canBeSeenBy(this.unitScope.fPackage))
+				continue next;
+			
+			boolean hasRestrictedAccess = false;
+//				boolean hasRestrictedAccess = memberType.hasRestrictedAccess();
+//				if(this.options.checkRestrictions && hasRestrictedAccess) continue next;
+			char[] completionName = CharOperation.concat(
+					memberType.qualifiedPackageName(),
+					memberType.qualifiedSourceName(),
+					'.');
+			
+			completionName = CharOperation.concat(completionName, SEMICOLON);
+			
+			int relevance = computeBaseRelevance();
+			relevance += computeRelevanceForInterestingProposal();
+			relevance += computeRelevanceForCaseMatching(typeName, memberType.sourceName);
+			relevance += computeRelevanceForRestrictions(hasRestrictedAccess);
+
+			if (memberType.isClass()) {
+				relevance += computeRelevanceForClass();
+				
+				this.noProposal = false;
+				if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+					CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+					proposal.setDeclarationSignature(memberType.qualifiedPackageName());
+					proposal.setSignature(getSignature(memberType));
+					proposal.setPackageName(memberType.qualifiedPackageName());
+					proposal.setTypeName(memberType.qualifiedSourceName());
+					proposal.setCompletion(completionName);
+					proposal.setFlags(memberType.modifiers);
+					proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+					proposal.setRelevance(relevance);
+					this.requestor.accept(proposal);
+					if(DEBUG) {
+						this.printDebug(proposal);
+					}
+				}
+
+			} else {
+				relevance += computeRelevanceForInterface();
+				
+				this.noProposal = false;
+				if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+					CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+					proposal.setDeclarationSignature(memberType.qualifiedPackageName());
+					proposal.setSignature(getSignature(memberType));
+					proposal.setPackageName(memberType.qualifiedPackageName());
+					proposal.setTypeName(memberType.qualifiedSourceName());
+					proposal.setCompletion(completionName);
+					proposal.setFlags(memberType.modifiers | Flags.AccInterface);
+					proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+					proposal.setRelevance(relevance);
+					this.requestor.accept(proposal);
+					if(DEBUG) {
+						this.printDebug(proposal);
+					}
+				}
+			}
+		}
+	}
+	
+	private void findImportsOfStaticFields(char[] fieldName, ReferenceBinding ref) {
+		FieldBinding[] fields = ref.fields();
+		
+		int fieldLength = fieldName.length;
+		next : for (int m = fields.length; --m >= 0;) {
+			FieldBinding field = fields[m];
+
+			if (fieldLength > field.name.length)
+				continue next;
+			
+			if (field.isSynthetic())
+				continue next;
+
+			if (!field.isStatic())
+				continue next;
+
+			if (!CharOperation.prefixEquals(fieldName, field.name, false
+				/* ignore case */
+				))
+				continue next;
+
+			if (this.options.checkVisibility
+				&& !field.canBeSeenBy(this.unitScope.fPackage))
+				continue next;
+			
+			boolean hasRestrictedAccess = false;
+//				boolean hasRestrictedAccess = field.declaringClass.hasRestrictedAccess();
+//				if(this.options.checkRestrictions && hasRestrictedAccess) continue next;
+			char[] completionName = CharOperation.concat(
+					field.declaringClass.qualifiedPackageName(),
+					'.',
+					field.declaringClass.qualifiedSourceName(),
+					'.',
+					field.name);
+			
+			completionName = CharOperation.concat(completionName, SEMICOLON);
+			
+			int relevance = computeBaseRelevance();
+			relevance += computeRelevanceForInterestingProposal();
+			relevance += computeRelevanceForCaseMatching(fieldName, field.name);
+			relevance += computeRelevanceForRestrictions(hasRestrictedAccess);
+
+			this.noProposal = false;
+			if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) {
+				CompletionProposal proposal = this.createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
+				proposal.setDeclarationSignature(getSignature(field.declaringClass));
+				proposal.setSignature(getSignature(field.type));
+				proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
+				proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
+				proposal.setPackageName(field.type.qualifiedPackageName());
+				proposal.setTypeName(field.type.qualifiedSourceName()); 
+				proposal.setName(field.name);
+				proposal.setCompletion(completionName);
+				proposal.setFlags(field.modifiers);
+				proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+				proposal.setRelevance(relevance);
+				this.requestor.accept(proposal);
+				if(DEBUG) {
+					this.printDebug(proposal);
+				}
+			}
+		}
+	}
+	
+	private void findImportsOfStaticMethdods(char[] methodName, ReferenceBinding ref) {
+		MethodBinding[] methods = ref.methods();
+		
+		int methodLength = methodName.length;
+		next : for (int m = methods.length; --m >= 0;) {
+			MethodBinding method = methods[m];
+
+			if (method.isSynthetic()) continue next;
+
+			if (method.isDefaultAbstract())	continue next;
+
+			if (method.isConstructor()) continue next;
+
+			if (!method.isStatic()) continue next;
+
+			if (this.options.checkVisibility
+				&& !method.canBeSeenBy(this.unitScope.fPackage)) continue next;
+			
+			if (methodLength > method.selector.length)
+				continue next;
+
+			if (!CharOperation.prefixEquals(methodName, method.selector, false
+				/* ignore case */
+				))
+				continue next;
+			
+			boolean hasRestrictedAccess = false;
+//				boolean hasRestrictedAccess = method.declaringClass.hasRestrictedAccess();
+//				if (this.options.checkRestrictions && hasRestrictedAccess) continue next;
+			
+			int length = method.parameters.length;
+			char[][] parameterPackageNames = new char[length][];
+			char[][] parameterTypeNames = new char[length][];
+
+			for (int i = 0; i < length; i++) {
+				TypeBinding type = method.original().parameters[i];
+				parameterPackageNames[i] = type.qualifiedPackageName();
+				parameterTypeNames[i] = type.qualifiedSourceName();
+			}
+			char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames);
+
+			
+			char[] completionName = CharOperation.concat(
+					method.declaringClass.qualifiedPackageName(),
+					'.',
+					method.declaringClass.qualifiedSourceName(),
+					'.',
+					method.selector);
+			
+			completionName = CharOperation.concat(completionName, SEMICOLON);
+			
+			int relevance = computeBaseRelevance();
+			relevance += computeRelevanceForInterestingProposal();
+			relevance += computeRelevanceForCaseMatching(methodName, method.selector);
+			relevance += computeRelevanceForRestrictions(hasRestrictedAccess);
+
+			this.noProposal = false;
+			if(!this.requestor.isIgnored(CompletionProposal.METHOD_NAME_REFERENCE)) {
+				CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_NAME_REFERENCE, this.actualCompletionPosition);
+				proposal.setDeclarationSignature(getSignature(method.declaringClass));
+				proposal.setSignature(getSignature(method));
+				proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
+				proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
+				proposal.setParameterPackageNames(parameterPackageNames);
+				proposal.setParameterTypeNames(parameterTypeNames);
+				proposal.setPackageName(method.returnType.qualifiedPackageName());
+				proposal.setTypeName(method.returnType.qualifiedSourceName());
+				proposal.setName(method.selector);
+				proposal.setCompletion(completionName);
+				proposal.setFlags(method.modifiers);
+				proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+				proposal.setRelevance(relevance);
+				if(parameterNames != null) proposal.setParameterNames(parameterNames);
+				this.requestor.accept(proposal);
+				if(DEBUG) {
+					this.printDebug(proposal);
+				}
+			}
+		}
+	}
+	
 	// what about onDemand types? Ignore them since it does not happen!
 	// import p1.p2.A.*;
 	private void findKeywords(char[] keyword, char[][] choices) {
@@ -1570,9 +2160,20 @@
 					int relevance = computeBaseRelevance();
 					relevance += computeRelevanceForInterestingProposal();
 					relevance += computeRelevanceForCaseMatching(keyword, choices[i]);
+					relevance += computeRelevanceForRestrictions(false); // no access restriction for keywors
 					
-					noProposal = false;
-					requestor.acceptKeyword(choices[i], startPosition - offset, endPosition - offset,relevance);
+					this.noProposal = false;
+					if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
+						CompletionProposal proposal = this.createProposal(CompletionProposal.KEYWORD, 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);
+						}
+					}
 				}
 	}
 	
@@ -1672,7 +2273,8 @@
 		ReferenceBinding[] memberTypes,
 		ObjectVector typesFound,
 		ReferenceBinding receiverType,
-		SourceTypeBinding invocationType) {
+		SourceTypeBinding invocationType,
+		boolean staticOnly) {
 
 		// Inherited member types which are hidden by subclasses are filtered out
 		// No visibility checks can be performed without the scope & invocationSite
@@ -1681,6 +2283,9 @@
 			ReferenceBinding memberType = memberTypes[m];
 			//		if (!wantClasses && memberType.isClass()) continue next;
 			//		if (!wantInterfaces && memberType.isInterface()) continue next;
+			
+			if (staticOnly && !memberType.isStatic()) continue next;
+			
 			if (typeLength > memberType.sourceName.length)
 				continue next;
 
@@ -1689,9 +2294,13 @@
 				))
 				continue next;
 
-			if (options.checkVisibility
+			if (this.options.checkVisibility
 				&& !memberType.canBeSeenBy(receiverType, invocationType))
 				continue next;
+			
+			boolean hasRestrictedAccess = false;
+//			boolean hasRestrictedAccess = memberType.hasRestrictedAccess();
+//			if(this.options.checkRestrictions && hasRestrictedAccess) continue next;
 
 			for (int i = typesFound.size; --i >= 0;) {
 				ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(i);
@@ -1722,33 +2331,48 @@
 			relevance += computeRelevanceForInterestingProposal();
 			relevance += computeRelevanceForCaseMatching(typeName, memberType.sourceName);
 			relevance += computeRelevanceForExpectingType(memberType);
+			relevance += computeRelevanceForRestrictions(hasRestrictedAccess);
 
 			if (memberType.isClass()) {
 				relevance += computeRelevanceForClass();
 				relevance += computeRelevanceForException(memberType.sourceName);
 				
-				noProposal = false;
-				requestor.acceptClass(
-					memberType.qualifiedPackageName(),
-					memberType.qualifiedSourceName(),
-					memberType.sourceName(),
-					memberType.modifiers,
-					startPosition - offset,
-					endPosition - offset,
-					relevance);
+				this.noProposal = false;
+				if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+					CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+					proposal.setDeclarationSignature(memberType.qualifiedPackageName());
+					proposal.setSignature(getSignature(memberType));
+					proposal.setPackageName(memberType.qualifiedPackageName());
+					proposal.setTypeName(memberType.qualifiedSourceName());
+					proposal.setCompletion(memberType.sourceName());
+					proposal.setFlags(memberType.modifiers);
+					proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+					proposal.setRelevance(relevance);
+					this.requestor.accept(proposal);
+					if(DEBUG) {
+						this.printDebug(proposal);
+					}
+				}
 
 			} else {
 				relevance += computeRelevanceForInterface();
 				
-				noProposal = false;
-				requestor.acceptInterface(
-					memberType.qualifiedPackageName(),
-					memberType.qualifiedSourceName(),
-					memberType.sourceName(),
-					memberType.modifiers,
-					startPosition - offset,
-					endPosition - offset,
-					relevance);
+				this.noProposal = false;
+				if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+					CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+					proposal.setDeclarationSignature(memberType.qualifiedPackageName());
+					proposal.setSignature(getSignature(memberType));
+					proposal.setPackageName(memberType.qualifiedPackageName());
+					proposal.setTypeName(memberType.qualifiedSourceName());
+					proposal.setCompletion(memberType.sourceName());
+					proposal.setFlags(memberType.modifiers | Flags.AccInterface);
+					proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+					proposal.setRelevance(relevance);
+					this.requestor.accept(proposal);
+					if(DEBUG) {
+						this.printDebug(proposal);
+					}
+				}
 			}
 		}
 	}
@@ -1757,7 +2381,9 @@
 		char[] typeName,
 		ReferenceBinding receiverType,
 		Scope scope,
-		SourceTypeBinding typeInvocation) {
+		SourceTypeBinding typeInvocation,
+		boolean staticOnly,
+		ObjectVector typesFound) {
 
 		ReferenceBinding currentType = receiverType;
 		if (typeName == null)
@@ -1766,8 +2392,7 @@
 		if (currentType.superInterfaces() == null)
 			return; // we're trying to find a supertype
 
-		ObjectVector typesFound = new ObjectVector();
-		if (insideQualifiedReference
+		if (this.insideQualifiedReference
 			|| typeName.length == 0) { // do not search up the hierarchy
 
 			findMemberTypes(
@@ -1775,7 +2400,8 @@
 				currentType.memberTypes(),
 				typesFound,
 				receiverType,
-				typeInvocation);
+				typeInvocation,
+				staticOnly);
 			return;
 		}
 
@@ -1805,7 +2431,8 @@
 				currentType.memberTypes(),
 				typesFound,
 				receiverType,
-				typeInvocation);
+				typeInvocation,
+				staticOnly);
 			currentType = currentType.superclass();
 
 		} while (currentType != null);
@@ -1825,7 +2452,8 @@
 							anInterface.memberTypes(),
 							typesFound,
 							receiverType,
-							typeInvocation);
+							typeInvocation,
+							staticOnly);
 
 						ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
 						if (itsInterfaces != NoSuperInterfaces) {
@@ -1865,7 +2493,8 @@
 		InvocationSite invocationSite,
 		Scope invocationScope,
 		boolean implicitCall,
-		boolean superCall) {
+		boolean superCall,
+		boolean canBePrefixed) {
 
 		if (selector == null)
 			return;
@@ -1912,7 +2541,8 @@
 									invocationSite,
 									invocationScope,
 									implicitCall,
-									superCall);
+									superCall,
+									canBePrefixed);
 							}
 						}
 
@@ -1982,7 +2612,8 @@
 						invocationSite,
 						invocationScope,
 						true,
-						false);
+						false,
+						true);
 					staticsOnly |= enclosingType.isStatic();
 					break;
 
@@ -2006,7 +2637,8 @@
 		InvocationSite invocationSite,
 		Scope invocationScope,
 		boolean implicitCall,
-		boolean superCall) {
+		boolean superCall,
+		boolean canBePrefixed) {
 
 		ObjectVector newMethodsFound =  new ObjectVector();
 		// Inherited methods which are hidden by subclasses are filtered out
@@ -2029,8 +2661,12 @@
 			
 			if (onlyStaticMethods && !method.isStatic()) continue next;
 
-			if (options.checkVisibility
+			if (this.options.checkVisibility
 				&& !method.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
+			
+			boolean hasRestrictedAccess = false;
+//			boolean hasRestrictedAccess = method.declaringClass.hasRestrictedAccess();
+//			if (this.options.checkRestrictions && hasRestrictedAccess) continue next;
 
 			if(superCall && method.isAbstract()) {
 				methodsFound.add(new Object[]{method, receiverType});
@@ -2100,7 +2736,11 @@
 					if(receiverType.isAnonymousType()) continue next;
 					
 					if(!superCall) {
-						prefixRequired = true;
+						if(canBePrefixed) {
+							prefixRequired = true;
+						} else {
+							continue next;
+						}
 					}
 				}
 			}
@@ -2111,7 +2751,7 @@
 			char[][] parameterTypeNames = new char[length][];
 
 			for (int i = 0; i < length; i++) {
-				TypeBinding type = method.parameters[i];
+				TypeBinding type = method.original().parameters[i];
 				parameterPackageNames[i] = type.qualifiedPackageName();
 				parameterTypeNames[i] = type.qualifiedSourceName();
 			}
@@ -2119,25 +2759,25 @@
 
 			char[] completion = CharOperation.NO_CHAR;
 			
-			int previousStartPosition = startPosition;
+			int previousStartPosition = this.startPosition;
 			
 			// nothing to insert - do not want to replace the existing selector & arguments
 			if (!exactMatch) {
-				if (source != null
-					&& source.length > endPosition
-					&& source[endPosition] == '(')
+				if (this.source != null
+					&& this.source.length > this.endPosition
+					&& this.source[this.endPosition] == '(')
 					completion = method.selector;
 				else
 					completion = CharOperation.concat(method.selector, new char[] { '(', ')' });
 			} else {
-				if(prefixRequired && (source != null)) {
-					completion = CharOperation.subarray(source, startPosition, endPosition);
+				if(prefixRequired && (this.source != null)) {
+					completion = CharOperation.subarray(this.source, this.startPosition, this.endPosition);
 				} else {
-					startPosition = endPosition;
+					this.startPosition = this.endPosition;
 				}
 			}
 			
-			if(prefixRequired || options.forceImplicitQualification){
+			if(prefixRequired || this.options.forceImplicitQualification){
 				char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), method.isStatic());
 				completion = CharOperation.concat(prefix,completion,'.');
 			}
@@ -2148,23 +2788,31 @@
 			relevance += computeRelevanceForExpectingType(method.returnType);
 			relevance += computeRelevanceForStatic(onlyStaticMethods, method.isStatic());
 			relevance += computeRelevanceForQualification(prefixRequired);
+			relevance += computeRelevanceForRestrictions(hasRestrictedAccess);
 			
-			noProposal = false;
-			requestor.acceptMethod(
-				method.declaringClass.qualifiedPackageName(),
-				method.declaringClass.qualifiedSourceName(),
-				method.selector,
-				parameterPackageNames,
-				parameterTypeNames,
-				parameterNames,
-				method.returnType.qualifiedPackageName(),
-				method.returnType.qualifiedSourceName(),
-				completion,
-				method.modifiers,
-				startPosition - offset,
-				endPosition - offset,
-				relevance);
-			startPosition = previousStartPosition;
+			this.noProposal = false;
+			if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
+				CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
+				proposal.setDeclarationSignature(getSignature(method.declaringClass));
+				proposal.setSignature(getSignature(method));
+				proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
+				proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
+				proposal.setParameterPackageNames(parameterPackageNames);
+				proposal.setParameterTypeNames(parameterTypeNames);
+				proposal.setPackageName(method.returnType.qualifiedPackageName());
+				proposal.setTypeName(method.returnType.qualifiedSourceName());
+				proposal.setName(method.selector);
+				proposal.setCompletion(completion);
+				proposal.setFlags(method.modifiers);
+				proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+				proposal.setRelevance(relevance);
+				if(parameterNames != null) proposal.setParameterNames(parameterNames);
+				this.requestor.accept(proposal);
+				if(DEBUG) {
+					this.printDebug(proposal);
+				}
+			}
+			this.startPosition = previousStartPosition;
 		}
 		
 		methodsFound.addAll(newMethodsFound);
@@ -2178,33 +2826,48 @@
 				return R_CASE;
 			}
 		} else {
+			if(CharOperation.equals(token, proposalName, false /* ignore case */)) {
+				return R_EXACT_NAME;
+			}
 			return 0;
 		}
 	}
+	private int computeRelevanceForAnnotation(){
+		if(this.assistNodeIsAnnotation) {
+			return R_ANNOTATION;
+		}
+		return 0;
+	}
 	private int computeRelevanceForClass(){
-		if(assistNodeIsClass) {
+		if(this.assistNodeIsClass) {
 			return R_CLASS;
 		}
 		return 0;
 	}
 	private int computeRelevanceForInterface(){
-		if(assistNodeIsInterface) {
+		if(this.assistNodeIsInterface) {
 			return R_INTERFACE;
 		}
 		return 0;
 	}
 	private int computeRelevanceForQualification(boolean prefixRequired) {
-		if(!prefixRequired && !insideQualifiedReference) {
+		if(!prefixRequired && !this.insideQualifiedReference) {
 			return R_UNQUALIFIED;
 		}
 		
-		if(prefixRequired && insideQualifiedReference) {
+		if(prefixRequired && this.insideQualifiedReference) {
 			return R_QUALIFIED;
 		}
 		return 0;
 	}
+	int computeRelevanceForRestrictions(boolean hasRestrictedAccess) {
+		if(!hasRestrictedAccess) {
+			return R_NON_RESTRICTED;
+		}
+		return 0;
+	}
 	private int computeRelevanceForStatic(boolean onlyStatic, boolean isStatic) {
-		if(insideQualifiedReference && !onlyStatic && !isStatic) {
+		if(this.insideQualifiedReference && !onlyStatic && !isStatic) {
 			return R_NON_STATIC;
 		}
 		return 0;
@@ -2214,7 +2877,7 @@
 	}
 	private int computeRelevanceForException(char[] proposalName){
 		
-		if(assistNodeIsException &&
+		if(this.assistNodeIsException &&
 			(CharOperation.match(EXCEPTION_PATTERN, proposalName, false) ||
 			CharOperation.match(ERROR_PATTERN, proposalName, false))) { 
 			return R_EXCEPTION;
@@ -2222,18 +2885,18 @@
 		return 0;
 	}
 	private int computeRelevanceForExpectingType(TypeBinding proposalType){
-		if(expectedTypes != null && proposalType != null) {
-			for (int i = 0; i <= expectedTypesPtr; i++) {
-				if(CharOperation.equals(expectedTypes[i].qualifiedPackageName(), proposalType.qualifiedPackageName()) &&
-					CharOperation.equals(expectedTypes[i].qualifiedSourceName(), proposalType.qualifiedSourceName())) {
+		if(this.expectedTypes != null && proposalType != null) {
+			for (int i = 0; i <= this.expectedTypesPtr; i++) {
+				if(CharOperation.equals(this.expectedTypes[i].qualifiedPackageName(), proposalType.qualifiedPackageName()) &&
+					CharOperation.equals(this.expectedTypes[i].qualifiedSourceName(), proposalType.qualifiedSourceName())) {
 					return R_EXACT_EXPECTED_TYPE;
 				}
-				if((expectedTypesFilter & SUBTYPE) != 0
-					&& proposalType.isCompatibleWith(expectedTypes[i])) {
+				if((this.expectedTypesFilter & SUBTYPE) != 0
+					&& proposalType.isCompatibleWith(this.expectedTypes[i])) {
 						return R_EXPECTED_TYPE;
 				}
-				if((expectedTypesFilter & SUPERTYPE) != 0
-					&& expectedTypes[i].isCompatibleWith(proposalType)) {
+				if((this.expectedTypesFilter & SUPERTYPE) != 0
+					&& this.expectedTypes[i].isCompatibleWith(proposalType)) {
 					return R_EXPECTED_TYPE;
 				}
 			}
@@ -2241,10 +2904,10 @@
 		return 0;
 	}
 	private int computeRelevanceForExpectingType(char[] packageName, char[] typeName){
-		if(expectedTypes != null) {
-			for (int i = 0; i <= expectedTypesPtr; i++) {
-				if(CharOperation.equals(expectedTypes[i].qualifiedPackageName(), packageName) &&
-					CharOperation.equals(expectedTypes[i].qualifiedSourceName(), typeName)) {
+		if(this.expectedTypes != null) {
+			for (int i = 0; i <= this.expectedTypesPtr; i++) {
+				if(CharOperation.equals(this.expectedTypes[i].qualifiedPackageName(), packageName) &&
+					CharOperation.equals(this.expectedTypes[i].qualifiedSourceName(), typeName)) {
 					return R_EXACT_EXPECTED_TYPE;
 				}
 			}
@@ -2255,9 +2918,9 @@
 		return computeRelevanceForInterestingProposal(null);
 	}
 	private int computeRelevanceForInterestingProposal(Binding binding){
-		if(uninterestingBindings != null) {
-			for (int i = 0; i <= uninterestingBindingsPtr; i++) {
-				if(uninterestingBindings[i] == binding) {
+		if(this.uninterestingBindings != null) {
+			for (int i = 0; i <= this.uninterestingBindingsPtr; i++) {
+				if(this.uninterestingBindings[i] == binding) {
 					return 0;
 				}
 			}
@@ -2308,9 +2971,13 @@
 				if(onlyStaticMethods) continue next;
 			}
 
-			if (options.checkVisibility
+			if (this.options.checkVisibility
 				&& !method.canBeSeenBy(receiverType, FakeInvocationSite , scope)) continue next;
 
+			boolean hasRestrictedAccess = false;
+//			boolean hasRestrictedAccess = method.declaringClass.hasRestrictedAccess();
+//			if(this.options.checkRestrictions && hasRestrictedAccess) continue next;
+			
 			if (exactMatch) {
 				if (!CharOperation.equals(methodName, method.selector, false /* ignore case */
 					))
@@ -2419,22 +3086,30 @@
 			relevance += computeRelevanceForCaseMatching(methodName, method.selector);
 			relevance += computeRelevanceForStaticOveride(method.isStatic());
 			if(method.isAbstract()) relevance += R_ABSTRACT_METHOD;
-
-			noProposal = false;
-			requestor.acceptMethodDeclaration(
-				method.declaringClass.qualifiedPackageName(),
-				method.declaringClass.qualifiedSourceName(),
-				method.selector,
-				parameterPackageNames,
-				parameterTypeNames,
-				parameterNames,
-				method.returnType.qualifiedPackageName(),
-				method.returnType.qualifiedSourceName(),
-				completion.toString().toCharArray(),
-				method.modifiers,
-				startPosition - offset,
-				endPosition - offset,
-				relevance);
+			relevance += computeRelevanceForRestrictions(hasRestrictedAccess);
+			
+			this.noProposal = false;
+			if(!this.requestor.isIgnored(CompletionProposal.METHOD_DECLARATION)) {
+				CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_DECLARATION, this.actualCompletionPosition);
+				proposal.setDeclarationSignature(getSignature(method.declaringClass));
+				proposal.setSignature(getSignature(method));
+				proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
+				proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
+				proposal.setParameterPackageNames(parameterPackageNames);
+				proposal.setParameterTypeNames(parameterTypeNames);
+				proposal.setPackageName(method.returnType.qualifiedPackageName());
+				proposal.setTypeName(method.returnType.qualifiedSourceName());
+				proposal.setCompletion(completion.toString().toCharArray());
+				proposal.setName(method.selector);
+				proposal.setFlags(method.modifiers);
+				proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+				proposal.setRelevance(relevance);
+				if(parameterNames != null) proposal.setParameterNames(parameterNames);
+				this.requestor.accept(proposal);
+				if(DEBUG) {
+					this.printDebug(proposal);
+				}
+			}
 		}
 		methodsFound.addAll(newMethodsFound);
 	}
@@ -2450,7 +3125,8 @@
 		InvocationSite invocationSite,
 		Scope invocationScope,
 		boolean implicitCall,
-		boolean superCall) {
+		boolean superCall,
+		boolean canBePrefixed) {
 		if (selector == null)
 			return;
 		
@@ -2481,7 +3157,8 @@
 					invocationSite,
 					invocationScope,
 					implicitCall,
-					superCall);
+					superCall,
+					canBePrefixed);
 			} else {
 				findIntefacesMethods(
 					selector,
@@ -2496,7 +3173,8 @@
 					invocationSite,
 					invocationScope,
 					implicitCall,
-					superCall);
+					superCall,
+					canBePrefixed);
 			}
 			
 			currentType = scope.getJavaLangObject();
@@ -2515,7 +3193,8 @@
 					invocationSite,
 					invocationScope,
 					implicitCall,
-					superCall);
+					superCall,
+					canBePrefixed);
 				
 				currentType = receiverType.superclass();
 			}
@@ -2547,7 +3226,8 @@
 						invocationSite,
 						invocationScope,
 						implicitCall,
-						superCall);
+						superCall,
+						canBePrefixed);
 				}
 			}
 			
@@ -2565,7 +3245,8 @@
 					invocationSite,
 					invocationScope,
 					implicitCall,
-					superCall);
+					superCall,
+					canBePrefixed);
 			} else {
 				hasPotentialDefaultAbstractMethods = false;
 			}
@@ -2590,7 +3271,7 @@
 				TypeDeclaration parsedType;
 
 				if ((parsedType = sourceType.scope.referenceContext) != null){
-					AbstractMethodDeclaration methodDecl = parsedType.declarationOf(method);
+					AbstractMethodDeclaration methodDecl = parsedType.declarationOf(method.original());
 
 					if (methodDecl != null){
 						Argument[] arguments = methodDecl.arguments;
@@ -2606,7 +3287,7 @@
 		// look into the model		
 		if(parameterNames == null){
 			char[] compoundName = CharOperation.concatWith(bindingType.compoundName, '.');
-			Object type = typeCache.get(compoundName);
+			Object type = this.typeCache.get(compoundName);
 			
 			ISourceType sourceType = null;
 			if(type != null) {
@@ -2614,16 +3295,16 @@
 					sourceType = (ISourceType) type;
 				}
 			} else {
-				NameEnvironmentAnswer answer = nameEnvironment.findType(bindingType.compoundName);
+				NameEnvironmentAnswer answer = this.nameEnvironment.findType(bindingType.compoundName);
 				if(answer != null && answer.isSourceType()) {
 					sourceType = answer.getSourceTypes()[0];
-					typeCache.put(compoundName, sourceType);
+					this.typeCache.put(compoundName, sourceType);
 				}
 			}
 			
 			if(sourceType != null) {
 				ISourceMethod[] sourceMethods = sourceType.getMethods();
-				int len = sourceMethods == null ? 0 : sourceMethods.length;
+				int len = sourceMethods.length;
 				for(int i = 0; i < len ; i++){
 					ISourceMethod sourceMethod = sourceMethods[i];
 					char[][] argTypeNames = sourceMethod.getArgumentTypeNames();
@@ -2643,7 +3324,8 @@
 	private void findNestedTypes(
 		char[] typeName,
 		SourceTypeBinding currentType,
-		Scope scope) {
+		Scope scope,
+		ObjectVector typesFound) {
 		if (typeName == null)
 			return;
 
@@ -2678,23 +3360,31 @@
 								relevance += computeRelevanceForException(localType.sourceName);
 								relevance += computeRelevanceForClass();
 								relevance += computeRelevanceForQualification(false);
+								relevance += computeRelevanceForRestrictions(false); // no access restriction for nested type
 								
-								noProposal = false;
-								requestor.acceptClass(
-									localType.qualifiedPackageName(),
-									localType.sourceName,
-									localType.sourceName,
-									localType.modifiers,
-									startPosition - offset,
-									endPosition - offset,
-									relevance);
+								this.noProposal = false;
+								if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+									CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+									proposal.setDeclarationSignature(localType.qualifiedPackageName());
+									proposal.setSignature(getSignature(localType));
+									proposal.setPackageName(localType.qualifiedPackageName());
+									proposal.setTypeName(localType.sourceName);
+									proposal.setCompletion(localType.sourceName);
+									proposal.setFlags(localType.modifiers);
+									proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+									proposal.setRelevance(relevance);
+									this.requestor.accept(proposal);
+									if(DEBUG) {
+										this.printDebug(proposal);
+									}
+								}
 							}
 						}
 					}
 					break;
 
 				case Scope.CLASS_SCOPE :
-					findMemberTypes(typeName, scope.enclosingSourceType(), scope, currentType);
+					findMemberTypes(typeName, scope.enclosingSourceType(), scope, currentType, false, typesFound);
 					if (typeLength == 0)
 						return; // do not search outside the class scope if no prefix was provided
 					break;
@@ -2708,25 +3398,89 @@
 
 	private void findPackages(CompletionOnPackageReference packageStatement) {
 
-		completionToken = CharOperation.concatWith(packageStatement.tokens, '.');
-		if (completionToken.length == 0)
+		this.completionToken = CharOperation.concatWith(packageStatement.tokens, '.');
+		if (this.completionToken.length == 0)
 			return;
 
 		setSourceRange(packageStatement.sourceStart, packageStatement.sourceEnd);
-		nameEnvironment.findPackages(CharOperation.toLowerCase(completionToken), this);
+		this.nameEnvironment.findPackages(CharOperation.toLowerCase(this.completionToken), this);
 	}
 
+	private void findTypeParameters(char[] token, Scope scope) {
+		TypeParameter[] typeParameters = null;
+		while (scope != null) { // done when a COMPILATION_UNIT_SCOPE is found
+			typeParameters = null;
+			switch (scope.kind) {
+				case Scope.METHOD_SCOPE :
+					MethodScope methodScope = (MethodScope) scope;
+					if(methodScope.referenceContext instanceof MethodDeclaration) {
+						MethodDeclaration methodDeclaration = (MethodDeclaration) methodScope.referenceContext;
+						typeParameters = methodDeclaration.typeParameters;
+					} else if(methodScope.referenceContext instanceof ConstructorDeclaration) {
+						ConstructorDeclaration methodDeclaration = (ConstructorDeclaration) methodScope.referenceContext;
+						typeParameters = methodDeclaration.typeParameters;
+					}
+					break;
+				case Scope.CLASS_SCOPE :
+					ClassScope classScope = (ClassScope) scope;
+					typeParameters = classScope.referenceContext.typeParameters;
+					break;
+				case Scope.COMPILATION_UNIT_SCOPE :
+					return;
+			}
+			if(typeParameters != null) {
+				for (int i = 0; i < typeParameters.length; i++) {
+					int typeLength = token.length;
+					TypeParameter typeParameter = typeParameters[i];
+					
+					if (typeLength > typeParameter.name.length) continue;
+					
+					if (!CharOperation.prefixEquals(token, typeParameter.name, false)) continue;
+	
+					int relevance = computeBaseRelevance();
+					relevance += computeRelevanceForInterestingProposal();
+					relevance += computeRelevanceForCaseMatching(token, typeParameter.name);
+					relevance += computeRelevanceForExpectingType(typeParameter.type == null ? null :typeParameter.type.resolvedType);
+					relevance += computeRelevanceForQualification(false);
+					relevance += computeRelevanceForException(typeParameter.name);
+					relevance += computeRelevanceForRestrictions(false); // no access restriction fot type parameter
+					
+					this.noProposal = false;
+					if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+						CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+						//proposal.setDeclarationSignature(null);
+						proposal.setSignature(getSignature(typeParameter.binding));
+						//proposal.setPackageName(null);
+						proposal.setTypeName(typeParameter.name);
+						proposal.setCompletion(typeParameter.name);
+						proposal.setFlags(typeParameter.modifiers);
+						proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+						proposal.setRelevance(relevance);
+						this.requestor.accept(proposal);
+						if(DEBUG) {
+							this.printDebug(proposal);
+						}
+					}
+				}
+			}
+			scope = scope.parent;
+		}
+	}
+	
 	private void findTypesAndPackages(char[] token, Scope scope) {
 
 		if (token == null)
 			return;
+		ObjectVector typesFound = new ObjectVector();
+		
+		if (scope.enclosingSourceType() != null) {
+			findNestedTypes(token, scope.enclosingSourceType(), scope, typesFound);
+			findTypeParameters(token, scope);
+		}
 
-		if (scope.enclosingSourceType() != null)
-			findNestedTypes(token, scope.enclosingSourceType(), scope);
-
-		if (unitScope != null) {
+		if (this.unitScope != null) {
 			int typeLength = token.length;
-			SourceTypeBinding[] types = unitScope.topLevelTypes;
+			SourceTypeBinding[] types = this.unitScope.topLevelTypes;
 
 			for (int i = 0, length = types.length; i < length; i++) {
 				SourceTypeBinding sourceType = types[i]; 
@@ -2734,48 +3488,71 @@
 				if (typeLength > sourceType.sourceName.length)	continue;
 				
 				if (!CharOperation.prefixEquals(token, sourceType.sourceName, false))	continue;
+				
+				this.knownTypes.put(CharOperation.concat(sourceType.qualifiedPackageName(), sourceType.sourceName(), '.'), this);
 
 				int relevance = computeBaseRelevance();
 				relevance += computeRelevanceForInterestingProposal();
 				relevance += computeRelevanceForCaseMatching(token, sourceType.sourceName);
 				relevance += computeRelevanceForExpectingType(sourceType);
 				relevance += computeRelevanceForQualification(false);
+				relevance += computeRelevanceForRestrictions(false); // no access restriction for type in the current unit
 
 				if (sourceType.isClass()){
 					relevance += computeRelevanceForClass();
 					relevance += computeRelevanceForException(sourceType.sourceName);
 					
-					noProposal = false;
-					requestor.acceptClass(
-						sourceType.qualifiedPackageName(),
-						sourceType.sourceName(),
-						sourceType.sourceName(),
-						sourceType.modifiers,
-						startPosition - offset, 
-						endPosition - offset,
-						relevance);
+					this.noProposal = false;
+					if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+						CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+						proposal.setDeclarationSignature(sourceType.qualifiedPackageName());
+						proposal.setSignature(getSignature(sourceType));
+						proposal.setPackageName(sourceType.qualifiedPackageName());
+						proposal.setTypeName(sourceType.sourceName());
+						proposal.setCompletion(sourceType.sourceName());
+						proposal.setFlags(sourceType.modifiers);
+						proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+						proposal.setRelevance(relevance);
+						this.requestor.accept(proposal);
+						if(DEBUG) {
+							this.printDebug(proposal);
+						}
+					}
 				} else {
 					relevance += computeRelevanceForInterface();
 					
-					noProposal = false;
-					requestor.acceptInterface(
-						sourceType.qualifiedPackageName(),
-						sourceType.sourceName(),
-						sourceType.sourceName(),
-						sourceType.modifiers,
-						startPosition - offset,
-						endPosition - offset,
-						relevance);
+					this.noProposal = false;
+					if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+						CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+						proposal.setDeclarationSignature(sourceType.qualifiedPackageName());
+						proposal.setSignature(getSignature(sourceType));
+						proposal.setPackageName(sourceType.qualifiedPackageName());
+						proposal.setTypeName(sourceType.sourceName());
+						proposal.setCompletion(sourceType.sourceName());
+						proposal.setFlags(sourceType.modifiers | Flags.AccInterface);
+						proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+						proposal.setRelevance(relevance);
+						this.requestor.accept(proposal);
+						if(DEBUG) {
+							this.printDebug(proposal);
+						}
+					}
 				}
 			}
 		}
 		
+		this.findTypesFromStaticImports(token, scope, typesFound);
+		
 		if (token.length == 0) {
-			if(expectedTypesPtr > -1) {
-				next : for (int i = 0; i <= expectedTypesPtr; i++) {
-					if(expectedTypes[i] instanceof ReferenceBinding) {
-						ReferenceBinding refBinding = (ReferenceBinding)expectedTypes[i];
-						boolean inSameUnit = unitScope.isDefinedInSameUnit(refBinding);
+			if(this.expectedTypesPtr > -1) {
+				next : for (int i = 0; i <= this.expectedTypesPtr; i++) {
+					if(this.expectedTypes[i] instanceof ReferenceBinding) {
+						ReferenceBinding refBinding = (ReferenceBinding)this.expectedTypes[i];
+						
+						boolean hasRestrictedAccess = refBinding.hasRestrictedAccess();
+						if(this.options.checkRestrictions && hasRestrictedAccess) continue next;
+						
+						boolean inSameUnit = this.unitScope.isDefinedInSameUnit(refBinding);
 						
 						// top level types of the current unit are already proposed.
 						if(!inSameUnit || (inSameUnit && refBinding.isMemberType())) {
@@ -2784,10 +3561,10 @@
 							char[] completionName = typeName;
 							
 							boolean isQualified = false;
-							if (!insideQualifiedReference && !refBinding.isMemberType()) {
+							if (!this.insideQualifiedReference && !refBinding.isMemberType()) {
 								if (mustQualifyType(packageName, typeName)) {
 									if (packageName == null || packageName.length == 0)
-										if (unitScope != null && unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
+										if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
 											continue next; // ignore types from the default package from outside it
 									completionName = CharOperation.concat(packageName, typeName, '.');
 									isQualified = true;
@@ -2799,31 +3576,46 @@
 							relevance += computeRelevanceForCaseMatching(token, typeName);
 							relevance += computeRelevanceForExpectingType(refBinding);
 							relevance += computeRelevanceForQualification(isQualified);
+							relevance += computeRelevanceForRestrictions(hasRestrictedAccess);
 							
 							if(refBinding.isClass()) {
 								relevance += computeRelevanceForClass();
 								
-								noProposal = false;
-								requestor.acceptClass(
-									packageName,
-									typeName,
-									completionName,
-									refBinding.modifiers,
-									startPosition - offset, 
-									endPosition - offset,
-									relevance);
+								this.noProposal = false;
+								if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+									CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+									proposal.setDeclarationSignature(packageName);
+									proposal.setSignature(getSignature(refBinding));
+									proposal.setPackageName(packageName);
+									proposal.setTypeName(typeName);
+									proposal.setCompletion(completionName);
+									proposal.setFlags(refBinding.modifiers);
+									proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+									proposal.setRelevance(relevance);
+									this.requestor.accept(proposal);
+									if(DEBUG) {
+										this.printDebug(proposal);
+									}
+								}
 							} else if (refBinding.isInterface()) {
 								relevance += computeRelevanceForInterface();
 								
-								noProposal = false;
-								requestor.acceptInterface(
-									packageName,
-									typeName,
-									completionName,
-									refBinding.modifiers,
-									startPosition - offset, 
-									endPosition - offset,
-									relevance);
+								this.noProposal = false;
+								if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+									CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+									proposal.setDeclarationSignature(packageName);
+									proposal.setSignature(getSignature(refBinding));
+									proposal.setPackageName(packageName);
+									proposal.setTypeName(typeName);
+									proposal.setCompletion(completionName);
+									proposal.setFlags(refBinding.modifiers | Flags.AccInterface);
+									proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+									proposal.setRelevance(relevance);
+									this.requestor.accept(proposal);
+									if(DEBUG) {
+										this.printDebug(proposal);
+									}
+								}
 							}
 						}
 					}
@@ -2831,8 +3623,8 @@
 			} 
 		} else {
 			findKeywords(token, baseTypes);
-			nameEnvironment.findTypes(token, this);
-			nameEnvironment.findPackages(token, this);
+			this.nameEnvironment.findTypes(token, this);
+			this.nameEnvironment.findPackages(token, this);
 		}
 	}
 
@@ -2856,9 +3648,9 @@
 		
 		this.qualifiedCompletionToken = qualifiedName;
 		
-		if (unitScope != null) {
+		if (this.unitScope != null) {
 			int typeLength = qualifiedName.length;
-			SourceTypeBinding[] types = unitScope.topLevelTypes;
+			SourceTypeBinding[] types = this.unitScope.topLevelTypes;
 
 			for (int i = 0, length = types.length; i < length; i++) {
 				SourceTypeBinding sourceType = types[i]; 
@@ -2868,46 +3660,154 @@
 				if (typeLength > qualifiedSourceTypeName.length) continue;
 				if (!(packageBinding == sourceType.getPackage())) continue;
 				if (!CharOperation.prefixEquals(qualifiedName, qualifiedSourceTypeName, false))	continue;
+				
+				boolean hasRestrictedAccess = sourceType.hasRestrictedAccess();
+				if(this.options.checkRestrictions && hasRestrictedAccess) continue;
+				
+				this.knownTypes.put(CharOperation.concat(sourceType.qualifiedPackageName(), sourceType.sourceName(), '.'), this);
 
 				int relevance = computeBaseRelevance();
 				relevance += computeRelevanceForInterestingProposal();
 				relevance += computeRelevanceForCaseMatching(qualifiedName, qualifiedSourceTypeName);
 				relevance += computeRelevanceForExpectingType(sourceType);
 				relevance += computeRelevanceForQualification(false);
-
+				relevance += computeRelevanceForRestrictions(hasRestrictedAccess);
+				
 				if (sourceType.isClass()){
 					relevance += computeRelevanceForClass();
 					relevance += computeRelevanceForException(sourceType.sourceName);
 					
-					noProposal = false;
-					requestor.acceptClass(
-						sourceType.qualifiedPackageName(),
-						sourceType.sourceName(),
-						sourceType.sourceName(),
-						sourceType.modifiers,
-						startPosition - offset, 
-						endPosition - offset,
-						relevance);
+					this.noProposal = false;
+					if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+						CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+						proposal.setDeclarationSignature(sourceType.qualifiedPackageName());
+						proposal.setSignature(getSignature(sourceType));
+						proposal.setPackageName(sourceType.qualifiedPackageName());
+						proposal.setTypeName(sourceType.sourceName());
+						proposal.setCompletion(sourceType.sourceName());
+						proposal.setFlags(sourceType.modifiers);
+						proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+						proposal.setRelevance(relevance);
+						this.requestor.accept(proposal);
+						if(DEBUG) {
+							this.printDebug(proposal);
+						}
+					}
 				} else {
 					relevance += computeRelevanceForInterface();
 					
-					noProposal = false;
-					requestor.acceptInterface(
-						sourceType.qualifiedPackageName(),
-						sourceType.sourceName(),
-						sourceType.sourceName(),
-						sourceType.modifiers,
-						startPosition - offset,
-						endPosition - offset,
-						relevance);
+					this.noProposal = false;
+					if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+						CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+						proposal.setDeclarationSignature(sourceType.qualifiedPackageName());
+						proposal.setSignature(getSignature(sourceType));
+						proposal.setPackageName(sourceType.qualifiedPackageName());
+						proposal.setTypeName(sourceType.sourceName());
+						proposal.setCompletion(sourceType.sourceName());
+						proposal.setFlags(sourceType.modifiers | Flags.AccInterface);
+						proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+						proposal.setRelevance(relevance);
+						this.requestor.accept(proposal);
+						if(DEBUG) {
+							this.printDebug(proposal);
+						}
+					}
 				}
 			}
 		}
 		
-		nameEnvironment.findTypes(qualifiedName, this);
-		nameEnvironment.findPackages(qualifiedName, this);
+		this.nameEnvironment.findTypes(qualifiedName, this);
+		this.nameEnvironment.findPackages(qualifiedName, this);
 	}
 
+	private void findTypesFromStaticImports(char[] token, Scope scope, ObjectVector typesFound) {
+		ImportBinding[] importBindings = scope.compilationUnitScope().imports;
+		for (int i = 0; i < importBindings.length; i++) {
+			ImportBinding importBinding = importBindings[i];
+			if(importBinding.isValidBinding() && importBinding.isStatic()) {
+				Binding binding = importBinding.resolvedImport;
+				if(binding != null && binding.isValidBinding()) {
+					if(importBinding.onDemand) {
+						if((binding.kind() & Binding.TYPE) != 0) {
+							this.findMemberTypes(
+									token,
+									(ReferenceBinding) binding,
+									scope,
+									scope.enclosingSourceType(),
+									true,
+									typesFound);
+						}
+					} else {
+						if ((binding.kind() & Binding.TYPE) != 0) {
+							ReferenceBinding typeBinding = (ReferenceBinding) binding;
+							int typeLength = token.length;
+							
+							if (!typeBinding.isStatic()) continue;
+							
+							if (typeLength > typeBinding.sourceName.length)	continue;
+							
+							boolean hasRestrictedAccess = false;
+//							boolean hasRestrictedAccess = typeBinding.hasRestrictedAccess();
+//							if(this.options.checkRestrictions && hasRestrictedAccess) continue;
+							
+							if (!CharOperation.prefixEquals(token, typeBinding.sourceName, false))	continue;
+							
+							if (typesFound.contains(typeBinding))  continue;
+							
+							typesFound.add(typeBinding);
+							
+							int relevance = computeBaseRelevance();
+							relevance += computeRelevanceForInterestingProposal();
+							relevance += computeRelevanceForCaseMatching(token, typeBinding.sourceName);
+							relevance += computeRelevanceForExpectingType(typeBinding);
+							relevance += computeRelevanceForRestrictions(hasRestrictedAccess);
+							
+							if (typeBinding.isClass()){
+								relevance += computeRelevanceForClass();
+								relevance += computeRelevanceForException(typeBinding.sourceName);
+								
+								this.noProposal = false;
+								if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+									CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+									proposal.setDeclarationSignature(typeBinding.qualifiedPackageName());
+									proposal.setSignature(getSignature(typeBinding));
+									proposal.setPackageName(typeBinding.qualifiedPackageName());
+									proposal.setTypeName(typeBinding.qualifiedSourceName());
+									proposal.setCompletion(typeBinding.sourceName());
+									proposal.setFlags(typeBinding.modifiers);
+									proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+									proposal.setRelevance(relevance);
+									this.requestor.accept(proposal);
+									if(DEBUG) {
+										this.printDebug(proposal);
+									}
+								}
+							} else {
+								relevance += computeRelevanceForInterface();
+								
+								this.noProposal = false;
+								if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+									CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+									proposal.setDeclarationSignature(typeBinding.qualifiedPackageName());
+									proposal.setSignature(getSignature(typeBinding));
+									proposal.setPackageName(typeBinding.qualifiedPackageName());
+									proposal.setTypeName(typeBinding.qualifiedSourceName());
+									proposal.setCompletion(typeBinding.sourceName());
+									proposal.setFlags(typeBinding.modifiers);
+									proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+									proposal.setRelevance(relevance);
+									this.requestor.accept(proposal);
+									if(DEBUG) {
+										this.printDebug(proposal);
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
 	private void findVariablesAndMethods(
 		char[] token,
 		Scope scope,
@@ -2971,20 +3871,33 @@
 						relevance += computeRelevanceForCaseMatching(token, local.name);
 						relevance += computeRelevanceForExpectingType(local.type);
 						relevance += computeRelevanceForQualification(false);
-						
-						noProposal = false;
-						requestor.acceptLocalVariable(
-							local.name,
-							local.type == null 
-								? CharOperation.NO_CHAR
-								: local.type.qualifiedPackageName(),
-							local.type == null
-								? local.declaration.type.toString().toCharArray()
-								: local.type.qualifiedSourceName(),
-							local.modifiers,
-							startPosition - offset,
-							endPosition - offset,
-							relevance);
+						relevance += computeRelevanceForRestrictions(false); // no access restriction for local variable
+						this.noProposal = false;
+						if(!this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) {
+							CompletionProposal proposal = this.createProposal(CompletionProposal.LOCAL_VARIABLE_REF, this.actualCompletionPosition);
+							proposal.setSignature(
+								local.type == null
+								? createTypeSignature(
+										CharOperation.NO_CHAR,
+										local.declaration.type.toString().toCharArray())
+								: getSignature(local.type));
+							if(local.type == null) {
+								//proposal.setPackageName(null);
+								proposal.setTypeName(local.declaration.type.toString().toCharArray());
+							} else {
+								proposal.setPackageName(local.type.qualifiedPackageName());
+								proposal.setTypeName(local.type.qualifiedSourceName());
+							}
+							proposal.setName(local.name);
+							proposal.setCompletion(local.name);
+							proposal.setFlags(local.modifiers);
+							proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+							proposal.setRelevance(relevance);
+							this.requestor.accept(proposal);
+							if(DEBUG) {
+								this.printDebug(proposal);
+							}
+						}
 					}
 					break;
 
@@ -3022,6 +3935,7 @@
 						staticsOnly,
 						invocationSite,
 						invocationScope,
+						true,
 						true);
 
 					findMethods(
@@ -3036,7 +3950,8 @@
 						invocationSite,
 						invocationScope,
 						true,
-						false);
+						false,
+						true);
 					staticsOnly |= enclosingType.isStatic();
 					//				}
 					break;
@@ -3046,6 +3961,61 @@
 			}
 			currentScope = currentScope.parent;
 		}
+		
+		ImportBinding[] importBindings = scope.compilationUnitScope().imports;
+		for (int i = 0; i < importBindings.length; i++) {
+			ImportBinding importBinding = importBindings[i];
+			if(importBinding.isValidBinding() && importBinding.isStatic()) {
+				Binding binding = importBinding.resolvedImport;
+				if(binding != null && binding.isValidBinding()) {
+					if(importBinding.onDemand) {
+						if((binding.kind() & Binding.TYPE) != 0) {
+							findFields(
+								token,
+								(ReferenceBinding)binding,
+								scope,
+								fieldsFound,
+								localsFound,
+								true,
+								invocationSite,
+								invocationScope,
+								true,
+								false);
+							
+							findMethods(
+								token,
+								null,
+								(ReferenceBinding)binding,
+								scope,
+								methodsFound,
+								true,
+								false,
+								false,
+								invocationSite,
+								invocationScope,
+								true,
+								false,
+								false);
+						}
+					} else {
+						if ((binding.kind() & Binding.FIELD) != 0) {
+								findFields(
+										token,
+										new FieldBinding[]{(FieldBinding)binding},
+										scope,
+										fieldsFound,
+										localsFound,
+										true,
+										((FieldBinding)binding).declaringClass,
+										invocationSite,
+										invocationScope,
+										true,
+										false);
+						}
+					}
+				}
+			}
+		}
 	}
 		// Helper method for private void findVariableNames(char[] name, TypeReference type )
 	private void findVariableName(
@@ -3053,6 +4023,7 @@
 		char[] qualifiedPackageName,
 		char[] qualifiedSourceName,
 		char[] sourceName,
+		final TypeBinding typeBinding,
 		char[][] excludeNames,
 		int dim,
 		int kind,
@@ -3100,17 +4071,25 @@
 					relevance += computeRelevanceForInterestingProposal();
 					relevance += computeRelevanceForCaseMatching(t, name);
 					relevance += prefixAndSuffixRelevance;
-
+					relevance += computeRelevanceForRestrictions(false); // no access restriction for variable name
+					
 					// accept result
-					noProposal = false;
-					requestor.acceptVariableName(
-						q,
-						displayName,
-						name,
-						name,
-						startPosition - offset,
-						endPosition - offset,
-						relevance);
+					CompletionEngine.this.noProposal = false;
+					if(!CompletionEngine.this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) {
+						CompletionProposal proposal = CompletionEngine.this.createProposal(CompletionProposal.VARIABLE_DECLARATION, CompletionEngine.this.actualCompletionPosition);
+						proposal.setSignature(getSignature(typeBinding));
+						proposal.setPackageName(q);
+						proposal.setTypeName(displayName);
+						proposal.setName(name);
+						proposal.setCompletion(name);
+						//proposal.setFlags(Flags.AccDefault);
+						proposal.setReplaceRange(CompletionEngine.this.startPosition - CompletionEngine.this.offset, CompletionEngine.this.endPosition - CompletionEngine.this.offset);
+						proposal.setRelevance(relevance);
+						CompletionEngine.this.requestor.accept(proposal);
+						if(DEBUG) {
+							CompletionEngine.this.printDebug(proposal);
+						}
+					}
 				}
 			}
 		};
@@ -3118,7 +4097,7 @@
 		switch (kind) {
 			case FIELD :
 				InternalNamingConventions.suggestFieldNames(
-					javaProject,
+					this.javaProject,
 					qualifiedPackageName,
 					qualifiedSourceName,
 					dim,
@@ -3128,7 +4107,7 @@
 				break;
 			case LOCAL :
 				InternalNamingConventions.suggestLocalVariableNames(
-					javaProject,
+					this.javaProject,
 					qualifiedPackageName,
 					qualifiedSourceName,
 					dim,
@@ -3137,7 +4116,7 @@
 				break;
 			case ARGUMENT :
 				InternalNamingConventions.suggestArgumentNames(
-					javaProject,
+					this.javaProject,
 					qualifiedPackageName,
 					qualifiedSourceName,
 					dim,
@@ -3158,6 +4137,7 @@
 				tb.leafComponentType().qualifiedPackageName(),
 				tb.leafComponentType().qualifiedSourceName(),
 				tb.leafComponentType().sourceName(),
+				tb,
 				excludeNames,
 				type.dimensions(),
 				kind,
@@ -3176,7 +4156,7 @@
 	
 	public AssistParser getParser() {
 
-		return parser;
+		return this.parser;
 	}
 
 	protected void reset() {
@@ -3193,7 +4173,7 @@
 	private void setSourceRange(int start, int end, boolean emptyTokenAdjstment) {		
 		this.startPosition = start;
 		if(emptyTokenAdjstment) {
-			int endOfEmptyToken = ((CompletionScanner)parser.scanner).endOfEmptyToken;
+			int endOfEmptyToken = ((CompletionScanner)this.parser.scanner).endOfEmptyToken;
 			this.endPosition = endOfEmptyToken > end ? endOfEmptyToken + 1 : end + 1;
 		} else {
 			this.endPosition = end + 1;
@@ -3202,10 +4182,10 @@
 	int computeBaseRelevance(){
 		return R_DEFAULT;
 	}
-	private void computeExpectedTypes(ASTNode parent, Scope scope){
+	private void computeExpectedTypes(ASTNode parent, ASTNode node, Scope scope){
 		
 		// default filter
-		expectedTypesFilter = SUBTYPE;
+		this.expectedTypesFilter = SUBTYPE;
 		
 		// find types from parent
 		if(parent instanceof AbstractVariableDeclaration) {
@@ -3234,13 +4214,13 @@
 			TypeBinding binding = e.resolvedType;
 			if(binding != null){
 				addExpectedType(binding);
-				expectedTypesFilter = SUBTYPE | SUPERTYPE;
+				this.expectedTypesFilter = SUBTYPE | SUPERTYPE;
 			}
 		} else if(parent instanceof MessageSend) {
 			MessageSend messageSend = (MessageSend) parent;
 
-			if(messageSend.receiverType instanceof ReferenceBinding) {
-				ReferenceBinding binding = (ReferenceBinding)messageSend.receiverType;
+			if(messageSend.actualReceiverType instanceof ReferenceBinding) {
+				ReferenceBinding binding = (ReferenceBinding)messageSend.actualReceiverType;
 				boolean isStatic = messageSend.receiver.isTypeReference();
 				
 				while(binding != null) {	
@@ -3248,7 +4228,7 @@
 						binding,
 						messageSend.selector,
 						messageSend.arguments,
-						(ReferenceBinding)messageSend.receiverType,
+						(ReferenceBinding)messageSend.actualReceiverType,
 						scope,
 						messageSend,
 						isStatic);
@@ -3256,7 +4236,7 @@
 						binding,
 						messageSend.selector,
 						messageSend.arguments,
-						(ReferenceBinding)messageSend.receiverType,
+						(ReferenceBinding)messageSend.actualReceiverType,
 						scope,
 						messageSend,
 						isStatic);
@@ -3284,7 +4264,7 @@
 				TypeBinding binding = e.expression.resolvedType;
 				if(binding != null){
 					addExpectedType(binding);
-					expectedTypesFilter = SUBTYPE | SUPERTYPE;
+					this.expectedTypesFilter = SUBTYPE | SUPERTYPE;
 				}
 			} else if(parent instanceof BinaryExpression) {
 				switch(operator) {
@@ -3313,6 +4293,20 @@
 						addExpectedType(BaseTypes.ByteBinding);
 						break;
 				}
+				BinaryExpression binaryExpression = (BinaryExpression) parent;
+				if(operator == OperatorIds.LESS) {
+					if(binaryExpression.left instanceof SingleNameReference){
+						SingleNameReference name = (SingleNameReference) binaryExpression.left;
+						Binding b = scope.getBinding(name.token, Binding.VARIABLE | Binding.TYPE, name, false);
+						if(b instanceof ReferenceBinding) {
+							TypeVariableBinding[] typeVariableBindings =((ReferenceBinding)b).typeVariables();
+							if(typeVariableBindings != null && typeVariableBindings.length > 0) {
+								addExpectedType(typeVariableBindings[0].firstBound);
+							}
+							
+						}
+					}
+				}
 			} else if(parent instanceof UnaryExpression) {
 				switch(operator) {
 					case OperatorIds.NOT :
@@ -3343,10 +4337,35 @@
 			addExpectedType(BaseTypes.ShortBinding);
 			addExpectedType(BaseTypes.IntBinding);
 			addExpectedType(BaseTypes.LongBinding);
+		} else if(parent instanceof ParameterizedSingleTypeReference) {
+			ParameterizedSingleTypeReference ref = (ParameterizedSingleTypeReference) parent;
+			TypeVariableBinding[] typeVariables = ((ReferenceBinding)ref.resolvedType).typeVariables();
+			int length = ref.typeArguments == null ? 0 : ref.typeArguments.length;
+			if(typeVariables != null && typeVariables.length >= length) {
+				int index = length - 1;
+				while(index > -1 && ref.typeArguments[index] != node) index--;
+				addExpectedType(typeVariables[index].firstBound);
+			}
+		} else if(parent instanceof ParameterizedQualifiedTypeReference) {
+			ParameterizedQualifiedTypeReference ref = (ParameterizedQualifiedTypeReference) parent;
+			TypeVariableBinding[] typeVariables = ((ReferenceBinding)ref.resolvedType).typeVariables();
+			TypeReference[][] arguments = ref.typeArguments;
+			if(typeVariables != null) {
+				int iLength = arguments == null ? 0 : arguments.length;
+				done: for (int i = 0; i < iLength; i++) {
+					int jLength = arguments[i] == null ? 0 : arguments[i].length;
+					for (int j = 0; j < jLength; j++) {
+						if(arguments[i][j] == node && typeVariables.length > j) {
+							addExpectedType(typeVariables[j].firstBound);
+							break done;
+						}
+					}
+				}
+			}
 		}
 		
-		if(expectedTypesPtr + 1 != expectedTypes.length) {
-			System.arraycopy(expectedTypes, 0, expectedTypes = new TypeBinding[expectedTypesPtr + 1], 0, expectedTypesPtr + 1);
+		if(this.expectedTypesPtr + 1 != this.expectedTypes.length) {
+			System.arraycopy(this.expectedTypes, 0, this.expectedTypes = new TypeBinding[this.expectedTypesPtr + 1], 0, this.expectedTypesPtr + 1);
 		}
 	}
 	
@@ -3364,7 +4383,7 @@
 			
 			if (method.isSynthetic()) continue nextMethod;
 			
-			if (options.checkVisibility && !method.canBeSeenBy(invocationSite, scope)) continue nextMethod;
+			if (this.options.checkVisibility && !method.canBeSeenBy(invocationSite, scope)) continue nextMethod;
 			
 			TypeBinding[] parameters = method.parameters;
 			if(parameters.length < arguments.length)
@@ -3468,7 +4487,7 @@
 
 			if (isStatic && !method.isStatic()) continue nextMethod;
 			
-			if (options.checkVisibility && !method.canBeSeenBy(receiverType, invocationSite, scope)) continue nextMethod;
+			if (this.options.checkVisibility && !method.canBeSeenBy(receiverType, invocationSite, scope)) continue nextMethod;
 			
 			if(!CharOperation.equals(method.selector, selector)) continue nextMethod;
 			
@@ -3539,20 +4558,234 @@
 	}
 	
 	private void proposeNewMethod(char[] token, ReferenceBinding reference) {
-		
-		if(requestor instanceof IExtendedCompletionRequestor) {
-			IExtendedCompletionRequestor extendedRequestor = (IExtendedCompletionRequestor) requestor;
-			
+		if(!this.requestor.isIgnored(CompletionProposal.POTENTIAL_METHOD_DECLARATION)) {
 			int relevance = computeBaseRelevance();
 			relevance += computeRelevanceForInterestingProposal();
+			relevance += computeRelevanceForRestrictions(false); // no access restriction for new method
 			
-			extendedRequestor.acceptPotentialMethodDeclaration(
-					reference.qualifiedPackageName(),
-					reference.qualifiedSourceName(),
-					token,
-					startPosition - offset,
-					endPosition - offset,
-					relevance);
+			CompletionProposal proposal = this.createProposal(CompletionProposal.POTENTIAL_METHOD_DECLARATION, this.actualCompletionPosition);
+			proposal.setDeclarationSignature(getSignature(reference));
+			proposal.setSignature(
+					createMethodSignature(
+							CharOperation.NO_CHAR_CHAR,
+							CharOperation.NO_CHAR_CHAR,
+							CharOperation.NO_CHAR,
+							VOID));
+			proposal.setDeclarationPackageName(reference.qualifiedPackageName());
+			proposal.setDeclarationTypeName(reference.qualifiedSourceName());
+			
+			//proposal.setPackageName(null);
+			proposal.setTypeName(VOID);
+			proposal.setName(token);
+			//proposal.setParameterPackageNames(null);
+			//proposal.setParameterTypeNames(null);
+			//proposal.setPackageName(null);
+			proposal.setCompletion(token);
+			proposal.setFlags(Flags.AccPublic);
+			proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+			proposal.setRelevance(relevance);
+			this.requestor.accept(proposal);
+			if(DEBUG) {
+				this.printDebug(proposal);
+			}
 		}
 	}
+	
+	private boolean isValidParent(ASTNode parent, ASTNode node, Scope scope){
+		
+		if(parent instanceof ParameterizedSingleTypeReference) {
+			ParameterizedSingleTypeReference ref = (ParameterizedSingleTypeReference) parent;
+			TypeVariableBinding[] typeVariables = ((ReferenceBinding)ref.resolvedType).typeVariables();
+			int length = ref.typeArguments == null ? 0 : ref.typeArguments.length;
+			int nodeIndex = -1;
+			for(int i = length - 1 ; i > -1 ; i--) {
+				if(node == ref.typeArguments[i]) {
+					nodeIndex = i;
+					break;
+				}
+			}
+			if(nodeIndex > -1 && (typeVariables == null || typeVariables.length < nodeIndex + 1)) {
+				TypeBinding[] typeBindings = new TypeBinding[nodeIndex + 1];
+				for(int i = 0; i < nodeIndex; i++) {
+					typeBindings[i] = ref.typeArguments[i].resolvedType;
+				}
+				typeBindings[nodeIndex] = scope.getJavaLangObject();
+				if(typeVariables == null || typeVariables.length == 0) {
+					scope.problemReporter().nonGenericTypeCannotBeParameterized(ref, ref.resolvedType, typeBindings);
+				} else {
+					scope.problemReporter().incorrectArityForParameterizedType(ref, ref.resolvedType, typeBindings);
+				}
+				return false;
+			}
+		} else if(parent instanceof ParameterizedQualifiedTypeReference) {
+			ParameterizedQualifiedTypeReference ref = (ParameterizedQualifiedTypeReference) parent;
+			TypeVariableBinding[] typeVariables = ((ReferenceBinding)ref.resolvedType).typeVariables();
+			TypeReference[][] arguments = ref.typeArguments;
+			int iLength = arguments == null ? 0 : arguments.length;
+			done: for (int i = 0; i < iLength; i++) {
+				int jLength = arguments[i] == null ? 0 : arguments[i].length;
+				for (int j = 0; j < jLength; j++) {
+					if(arguments[i][j] == node && (typeVariables == null || typeVariables.length <= j)) {
+						TypeBinding[] typeBindings = new TypeBinding[j + 1];
+						for(int k = 0; k < j; k++) {
+							typeBindings[k] = ref.typeArguments[i][k].resolvedType;
+						}
+						typeBindings[j] = scope.getJavaLangObject();
+						if(typeVariables == null || typeVariables.length == 0) {
+							scope.problemReporter().nonGenericTypeCannotBeParameterized(ref, ref.resolvedType, typeBindings);
+						} else {
+							scope.problemReporter().incorrectArityForParameterizedType(ref, ref.resolvedType, typeBindings);
+						}
+						return false;
+					}
+				}
+			}
+		}
+		return true;
+	}
+	
+	public static char[] createNonGenericTypeSignature(char[] qualifiedPackageName, char[] qualifiedTypeName) {
+		return Signature.createCharArrayTypeSignature(
+				CharOperation.concat(
+						qualifiedPackageName,
+						CharOperation.replaceOnCopy(qualifiedTypeName, '.', '$'), '.'), true);
+	}
+	public static char[] createTypeSignature(char[] qualifiedPackageName, char[] qualifiedTypeName) {
+		char[] name = new char[qualifiedTypeName.length];
+		System.arraycopy(qualifiedTypeName, 0, name, 0, qualifiedTypeName.length);
+		
+		int depth = 0;
+		int length = name.length;
+		lastDotLookup: for (int i = length -1; i >= 0; i--) {
+			switch (name[i]) {
+				case '.':
+					if (depth == 0 && name[i - 1] != '>') {
+						name[i] = '$';
+					}
+					break;
+				case '<':
+					depth--;
+					break;
+				case '>':
+					depth++;
+					break;
+			}
+		}
+		return Signature.createCharArrayTypeSignature(
+				CharOperation.concat(
+						qualifiedPackageName,
+						name, '.'), true);
+	}
+	
+	public static char[] createMethodSignature(char[][] parameterPackageNames, char[][] parameterTypeNames, char[] returnPackagename, char[] returnTypeName) {
+		char[][] parameterTypeSignature = new char[parameterTypeNames.length][];
+		for (int i = 0; i < parameterTypeSignature.length; i++) {
+			parameterTypeSignature[i] = 
+				Signature.createCharArrayTypeSignature(
+						CharOperation.concat(
+								parameterPackageNames[i],
+								CharOperation.replaceOnCopy(parameterTypeNames[i], '.', '$'), '.'), true);
+		}
+		
+		char[] returnTypeSignature =
+			returnTypeName == null || returnTypeName.length == 0
+			? Signature.createCharArrayTypeSignature(VOID, true)
+			: Signature.createCharArrayTypeSignature(
+					CharOperation.concat(
+							returnPackagename,
+							CharOperation.replaceOnCopy(returnTypeName, '.', '$'), '.'), true);
+			
+		return Signature.createMethodSignature(
+				parameterTypeSignature,
+				returnTypeSignature);
+	}
+	
+	protected CompletionProposal createProposal(int kind, int compteionOffset) {
+		CompletionProposal proposal = CompletionProposal.create(kind, compteionOffset);
+		proposal.nameLookup = this.nameEnvironment.nameLookup;
+		proposal.completionEngine = this;
+		return proposal;
+	}
+	
+	protected void printDebug(IProblem error) {
+		if(CompletionEngine.DEBUG) {
+			System.out.print("COMPLETION - completionFailure("); //$NON-NLS-1$
+			System.out.print(error);
+			System.out.println(")"); //$NON-NLS-1$
+		}
+	}
+	
+	protected void printDebug(CompletionProposal proposal){
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("COMPLETION - "); //$NON-NLS-1$
+		switch(proposal.getKind()) {
+			case CompletionProposal.ANONYMOUS_CLASS_DECLARATION :
+				buffer.append("ANONYMOUS_CLASS_DECLARATION"); //$NON-NLS-1$
+				break;
+			case CompletionProposal.FIELD_REF :
+				buffer.append("FIELD_REF"); //$NON-NLS-1$
+				break;
+			case CompletionProposal.KEYWORD :
+				buffer.append("KEYWORD"); //$NON-NLS-1$
+				break;
+			case CompletionProposal.LABEL_REF :
+				buffer.append("LABEL_REF"); //$NON-NLS-1$
+				break;
+			case CompletionProposal.LOCAL_VARIABLE_REF :
+				buffer.append("LOCAL_VARIABLE_REF"); //$NON-NLS-1$
+				break;
+			case CompletionProposal.METHOD_DECLARATION :
+				buffer.append("METHOD_DECLARATION"); //$NON-NLS-1$
+				break;
+			case CompletionProposal.METHOD_REF :
+				buffer.append("METHOD_REF"); //$NON-NLS-1$
+				break;
+			case CompletionProposal.PACKAGE_REF :
+				buffer.append("PACKAGE_REF"); //$NON-NLS-1$
+				break;
+			case CompletionProposal.TYPE_REF :
+				buffer.append("TYPE_REF"); //$NON-NLS-1$
+				break;
+			case CompletionProposal.VARIABLE_DECLARATION :
+				buffer.append("VARIABLE_DECLARATION"); //$NON-NLS-1$
+				break;
+			case CompletionProposal.POTENTIAL_METHOD_DECLARATION :
+				buffer.append("POTENTIAL_METHOD_DECLARATION"); //$NON-NLS-1$
+				break;
+			case CompletionProposal.METHOD_NAME_REFERENCE :
+				buffer.append("METHOD_IMPORT"); //$NON-NLS-1$
+				break;
+			default :
+				buffer.append("PROPOSAL"); //$NON-NLS-1$
+				break;
+				
+		}
+		
+		buffer.append("{\n");//$NON-NLS-1$
+		buffer.append("\tCompletion[").append(proposal.getCompletion() == null ? "null".toCharArray() : proposal.getCompletion()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buffer.append("\tDeclarationSignature[").append(proposal.getDeclarationSignature() == null ? "null".toCharArray() : proposal.getDeclarationSignature()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buffer.append("\tSignature[").append(proposal.getSignature() == null ? "null".toCharArray() : proposal.getSignature()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+//		buffer.append("\tDeclarationPackage[").append(proposal.getDeclarationPackageName() == null ? "null".toCharArray() : proposal.getDeclarationPackageName()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+//		buffer.append("\tDeclarationType[").append(proposal.getDeclarationTypeName() == null ? "null".toCharArray() : proposal.getDeclarationTypeName()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+//		buffer.append("\tPackage[").append(proposal.getPackageName() == null ? "null".toCharArray() : proposal.getPackageName()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+//		buffer.append("\tType[").append(proposal.getTypeName() == null ? "null".toCharArray() : proposal.getTypeName()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buffer.append("\tName[").append(proposal.getName() == null ? "null".toCharArray() : proposal.getName()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		
+		buffer.append("\tFlags[");//$NON-NLS-1$
+		int flags = proposal.getFlags();
+		buffer.append(Flags.toString(flags));
+		if((flags & Flags.AccInterface) != 0) buffer.append("interface ");//$NON-NLS-1$
+		if((flags & Flags.AccEnum) != 0) buffer.append("enum ");//$NON-NLS-1$
+		buffer.append("]\n"); //$NON-NLS-1$
+		
+		buffer.append("\tCompletionLocation[").append(proposal.getCompletionLocation()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$
+		buffer.append("\tReplaceStart[").append(proposal.getReplaceStart()).append("]"); //$NON-NLS-1$ //$NON-NLS-2$
+		buffer.append("-ReplaceEnd[").append(proposal.getReplaceEnd()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$
+		buffer.append("\tTokenStart[").append(proposal.getTokenStart()).append("]"); //$NON-NLS-1$ //$NON-NLS-2$
+		buffer.append("-TokenEnd[").append(proposal.getTokenEnd()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$
+		buffer.append("\tRelevance[").append(proposal.getRelevance()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$
+
+		buffer.append("}\n");//$NON-NLS-1$
+		System.out.println(buffer.toString());
+	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionRequestorWrapper.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionRequestorWrapper.java
new file mode 100644
index 0000000..04ca5bc
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionRequestorWrapper.java
@@ -0,0 +1,339 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist;
+
+import org.eclipse.jdt.core.CompletionProposal;
+import org.eclipse.jdt.core.CompletionRequestor;
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.IProblem;
+
+/**
+ * This CompletionRequetor wrap the old requestor ICOmpletionRequestor
+ * @since 3.1
+ * @deprecated
+ */
+public class CompletionRequestorWrapper extends CompletionRequestor {
+	private static boolean DECODE_SIGNATURE = false;
+	
+	private org.eclipse.jdt.core.ICompletionRequestor requestor;
+	public CompletionRequestorWrapper(org.eclipse.jdt.core.ICompletionRequestor requestor) {
+		this.requestor = requestor;
+	}
+	
+	public void accept(CompletionProposal proposal) {
+		switch(proposal.getKind()) {
+			case CompletionProposal.KEYWORD:
+				this.requestor.acceptKeyword(
+						proposal.getName(),
+						proposal.getReplaceStart(),
+						proposal.getReplaceEnd(),
+						proposal.getRelevance());
+				break;
+			case CompletionProposal.PACKAGE_REF:
+				if(DECODE_SIGNATURE) {
+					this.requestor.acceptPackage(
+							proposal.getDeclarationSignature(),
+							proposal.getCompletion(),
+							proposal.getReplaceStart(),
+							proposal.getReplaceEnd(),
+							proposal.getRelevance());
+				} else {
+					this.requestor.acceptPackage(
+							proposal.getPackageName(),
+							proposal.getCompletion(),
+							proposal.getReplaceStart(),
+							proposal.getReplaceEnd(),
+							proposal.getRelevance());
+				}
+				break;
+			case CompletionProposal.TYPE_REF:
+				if((proposal.getFlags() & Flags.AccEnum) != 0) {
+					// does not exist for old requestor
+				} else if((proposal.getFlags() & Flags.AccInterface) != 0) {
+					if(DECODE_SIGNATURE) {
+						this.requestor.acceptInterface(
+								proposal.getDeclarationSignature(),
+								Signature.getSignatureSimpleName(proposal.getSignature()),
+								proposal.getCompletion(),
+								proposal.getFlags() & ~Flags.AccInterface,
+								proposal.getReplaceStart(),
+								proposal.getReplaceEnd(),
+								proposal.getRelevance());
+					} else {
+						this.requestor.acceptInterface(
+								proposal.getPackageName() == null ? CharOperation.NO_CHAR : proposal.getPackageName(),
+								proposal.getTypeName(),
+								proposal.getCompletion(),
+								proposal.getFlags() & ~Flags.AccInterface,
+								proposal.getReplaceStart(),
+								proposal.getReplaceEnd(),
+								proposal.getRelevance());
+					}
+				} else {
+					if(DECODE_SIGNATURE) {
+						this.requestor.acceptClass(
+								proposal.getDeclarationSignature(),
+								Signature.getSignatureSimpleName(proposal.getSignature()),
+								proposal.getCompletion(),
+								proposal.getFlags(),
+								proposal.getReplaceStart(),
+								proposal.getReplaceEnd(),
+								proposal.getRelevance());
+					} else {
+						this.requestor.acceptClass(
+								proposal.getPackageName() == null ? CharOperation.NO_CHAR : proposal.getPackageName(),
+								proposal.getTypeName(),
+								proposal.getCompletion(),
+								proposal.getFlags(),
+								proposal.getReplaceStart(),
+								proposal.getReplaceEnd(),
+								proposal.getRelevance());
+					}
+				}
+				break;
+			case CompletionProposal.FIELD_REF:
+				if(DECODE_SIGNATURE) {
+					this.requestor.acceptField(
+							Signature.getSignatureQualifier(proposal.getDeclarationSignature()),
+							Signature.getSignatureSimpleName(proposal.getDeclarationSignature()),
+							proposal.getName(),
+							Signature.getSignatureQualifier(proposal.getSignature()),
+							Signature.getSignatureSimpleName(proposal.getSignature()), 
+							proposal.getCompletion(),
+							proposal.getFlags(),
+							proposal.getReplaceStart(),
+							proposal.getReplaceEnd(),
+							proposal.getRelevance()
+					);
+				} else {
+					this.requestor.acceptField(
+							proposal.getDeclarationPackageName() == null ? CharOperation.NO_CHAR : proposal.getDeclarationPackageName(),
+							proposal.getDeclarationTypeName() == null ? CharOperation.NO_CHAR : proposal.getDeclarationTypeName(),
+							proposal.getName(),
+							proposal.getPackageName() == null ? CharOperation.NO_CHAR : proposal.getPackageName(),
+							proposal.getTypeName() == null ? CharOperation.NO_CHAR : proposal.getTypeName(),
+							proposal.getCompletion(),
+							proposal.getFlags(),
+							proposal.getReplaceStart(),
+							proposal.getReplaceEnd(),
+							proposal.getRelevance()
+					);
+				}
+				break;
+			case CompletionProposal.METHOD_REF:
+				if(DECODE_SIGNATURE) {
+					this.requestor.acceptMethod(
+							Signature.getSignatureQualifier(proposal.getDeclarationSignature()),
+							Signature.getSignatureSimpleName(proposal.getDeclarationSignature()),
+							proposal.getName(),
+							getParameterPackages(proposal.getSignature()),
+							getParameterTypes(proposal.getSignature()),
+							proposal.findParameterNames(null) == null ? CharOperation.NO_CHAR_CHAR : proposal.findParameterNames(null),
+							Signature.getSignatureQualifier(Signature.getReturnType(proposal.getSignature())),
+							Signature.getSignatureSimpleName(Signature.getReturnType(proposal.getSignature())),
+							proposal.getCompletion(),
+							proposal.getFlags(),
+							proposal.getReplaceStart(),
+							proposal.getReplaceEnd(),
+							proposal.getRelevance()
+						);
+				} else {
+					this.requestor.acceptMethod(
+							proposal.getDeclarationPackageName() == null ? CharOperation.NO_CHAR : proposal.getDeclarationPackageName(),
+							proposal.getDeclarationTypeName() == null ? CharOperation.NO_CHAR : proposal.getDeclarationTypeName(),
+							proposal.getName(),
+							proposal.getParameterPackageNames() == null ? CharOperation.NO_CHAR_CHAR : proposal.getParameterPackageNames(),
+							proposal.getParameterTypeNames() == null ? CharOperation.NO_CHAR_CHAR : proposal.getParameterTypeNames(),
+							proposal.findParameterNames(null) == null ? CharOperation.NO_CHAR_CHAR : proposal.findParameterNames(null),
+							proposal.getPackageName() == null ? CharOperation.NO_CHAR : proposal.getPackageName(),
+							proposal.getTypeName() == null ? CharOperation.NO_CHAR : proposal.getTypeName(),
+							proposal.getCompletion(),
+							proposal.getFlags(),
+							proposal.getReplaceStart(),
+							proposal.getReplaceEnd(),
+							proposal.getRelevance()
+					);
+				}
+				break;
+			case CompletionProposal.METHOD_DECLARATION:
+				if(DECODE_SIGNATURE) {
+					this.requestor.acceptMethodDeclaration(
+							Signature.getSignatureQualifier(proposal.getDeclarationSignature()),
+							Signature.getSignatureSimpleName(proposal.getDeclarationSignature()),
+							proposal.getName(),
+							getParameterPackages(proposal.getSignature()),
+							getParameterTypes(proposal.getSignature()),
+							proposal.findParameterNames(null) == null ? CharOperation.NO_CHAR_CHAR : proposal.findParameterNames(null),
+							Signature.getSignatureQualifier(Signature.getReturnType(proposal.getSignature())),
+							Signature.getSignatureSimpleName(Signature.getReturnType(proposal.getSignature())),
+							proposal.getCompletion(),
+							proposal.getFlags(),
+							proposal.getReplaceStart(),
+							proposal.getReplaceEnd(),
+							proposal.getRelevance()
+					);
+				} else {
+					this.requestor.acceptMethodDeclaration(
+							proposal.getDeclarationPackageName(),
+							proposal.getDeclarationTypeName(),
+							proposal.getName(),
+							proposal.getParameterPackageNames() == null ? CharOperation.NO_CHAR_CHAR : proposal.getParameterPackageNames(),
+							proposal.getParameterTypeNames() == null ? CharOperation.NO_CHAR_CHAR : proposal.getParameterTypeNames(),
+							proposal.findParameterNames(null) == null ? CharOperation.NO_CHAR_CHAR : proposal.findParameterNames(null),
+							proposal.getPackageName(),
+							proposal.getTypeName(),
+							proposal.getCompletion(),
+							proposal.getFlags(),
+							proposal.getReplaceStart(),
+							proposal.getReplaceEnd(),
+							proposal.getRelevance()
+					);
+				}
+				break;
+			case CompletionProposal.ANONYMOUS_CLASS_DECLARATION:
+				if(DECODE_SIGNATURE) {
+					this.requestor.acceptAnonymousType(
+							Signature.getSignatureQualifier(proposal.getDeclarationSignature()),
+							Signature.getSignatureSimpleName(proposal.getDeclarationSignature()), 
+							getParameterPackages(proposal.getSignature()),
+							getParameterTypes(proposal.getSignature()),
+							proposal.findParameterNames(null) == null ? CharOperation.NO_CHAR_CHAR : proposal.findParameterNames(null),
+							proposal.getCompletion(),
+							proposal.getFlags(),
+							proposal.getReplaceStart(),
+							proposal.getReplaceEnd(),
+							proposal.getRelevance()
+						);
+				} else {
+					this.requestor.acceptAnonymousType(
+						proposal.getDeclarationPackageName(),
+						proposal.getDeclarationTypeName(),
+						proposal.getParameterPackageNames() == null ? CharOperation.NO_CHAR_CHAR : proposal.getParameterPackageNames(),
+						proposal.getParameterTypeNames() == null ? CharOperation.NO_CHAR_CHAR : proposal.getParameterTypeNames(),
+						proposal.findParameterNames(null) == null ? CharOperation.NO_CHAR_CHAR : proposal.findParameterNames(null),
+						proposal.getCompletion(),
+						proposal.getFlags(),
+						proposal.getReplaceStart(),
+						proposal.getReplaceEnd(),
+						proposal.getRelevance()
+					);
+				}
+				break;
+			case CompletionProposal.LABEL_REF :
+				this.requestor.acceptLabel(
+					proposal.getCompletion(),
+					proposal.getReplaceStart(),
+					proposal.getReplaceEnd(),
+					proposal.getRelevance()
+				);
+				break;
+			case CompletionProposal.LOCAL_VARIABLE_REF:
+				if(DECODE_SIGNATURE) {
+					this.requestor.acceptLocalVariable(
+							proposal.getCompletion(),
+							Signature.getSignatureQualifier(proposal.getSignature()),
+							Signature.getSignatureSimpleName(proposal.getSignature()),
+							proposal.getFlags(),
+							proposal.getReplaceStart(),
+							proposal.getReplaceEnd(),
+							proposal.getRelevance()
+					);
+				} else {
+					this.requestor.acceptLocalVariable(
+							proposal.getCompletion(),
+							proposal.getPackageName() == null ? CharOperation.NO_CHAR : proposal.getPackageName(),
+							proposal.getTypeName(),
+							proposal.getFlags(),
+							proposal.getReplaceStart(),
+							proposal.getReplaceEnd(),
+							proposal.getRelevance()
+					);
+				}
+				break;
+			case CompletionProposal.VARIABLE_DECLARATION:
+				if(DECODE_SIGNATURE) {
+					this.requestor.acceptLocalVariable(
+							proposal.getCompletion(),
+							Signature.getSignatureQualifier(proposal.getSignature()),
+							Signature.getSignatureSimpleName(proposal.getSignature()),
+							proposal.getFlags(),
+							proposal.getReplaceStart(),
+							proposal.getReplaceEnd(),
+							proposal.getRelevance()
+						);
+				} else {
+					this.requestor.acceptLocalVariable(
+						proposal.getCompletion(),
+						proposal.getPackageName(),
+						proposal.getTypeName(),
+						proposal.getFlags(),
+						proposal.getReplaceStart(),
+						proposal.getReplaceEnd(),
+						proposal.getRelevance()
+					);
+				}
+				break;
+			case CompletionProposal.POTENTIAL_METHOD_DECLARATION:
+				if(this.requestor instanceof IExtendedCompletionRequestor) {
+					IExtendedCompletionRequestor r = (IExtendedCompletionRequestor) this.requestor;
+					if(DECODE_SIGNATURE) {
+						r.acceptPotentialMethodDeclaration(
+								Signature.getSignatureQualifier(proposal.getDeclarationSignature()),
+								Signature.getSignatureSimpleName(proposal.getDeclarationSignature()),
+								proposal.getName(),
+								proposal.getReplaceStart(),
+								proposal.getReplaceEnd(),
+								proposal.getRelevance()
+						);
+					} else {
+						r.acceptPotentialMethodDeclaration(
+								proposal.getDeclarationPackageName(),
+								proposal.getDeclarationTypeName(),
+								proposal.getName(),
+								proposal.getReplaceStart(),
+								proposal.getReplaceEnd(),
+								proposal.getRelevance()
+						);
+					}
+				}
+				break;
+				
+		}
+	}
+	
+	public void completionFailure(IProblem problem) {
+		this.requestor.acceptError(problem);
+	}
+	
+	private char[][] getParameterPackages(char[] methodSignature) {
+		char[][] parameterQualifiedTypes = Signature.getParameterTypes(methodSignature);
+		int length = parameterQualifiedTypes == null ? 0 : parameterQualifiedTypes.length;
+		char[][] parameterPackages = new char[length][];
+		for(int i = 0; i < length; i++) {
+			parameterPackages[i] = Signature.getSignatureQualifier(parameterQualifiedTypes[i]);
+		}
+
+		return parameterPackages;
+	}
+	
+	private char[][] getParameterTypes(char[] methodSignature) {
+		char[][] parameterQualifiedTypes = Signature.getParameterTypes(methodSignature);
+		int length = parameterQualifiedTypes == null ? 0 : parameterQualifiedTypes.length;
+		char[][] parameterPackages = new char[length][];
+		for(int i = 0; i < length; i++) {
+			parameterPackages[i] = Signature.getSignatureSimpleName(parameterQualifiedTypes[i]);
+		}
+
+		return parameterPackages;
+	}
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/IExtendedCompletionRequestor.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/IExtendedCompletionRequestor.java
index b8fd525..3565330 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/IExtendedCompletionRequestor.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/IExtendedCompletionRequestor.java
@@ -10,10 +10,11 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.codeassist;
 
-import org.eclipse.jdt.core.ICompletionRequestor;
-
-//TODO remove this class once new CompletionRequestor is working.
-public interface IExtendedCompletionRequestor extends ICompletionRequestor {
+/**
+ * @deprecated Use {@link org.eclipse.jdt.core.CompletionRequestor} instead
+ */
+//TODO remove this class once no more clients
+public interface IExtendedCompletionRequestor extends org.eclipse.jdt.core.ICompletionRequestor {
 	void acceptPotentialMethodDeclaration(
 			char[] declaringTypePackageName,
 			char[] declaringTypeName,
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java
index 188c0c8..7fcfffe 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java
@@ -10,6 +10,8 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.codeassist;
 
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+
 /**
  * This is the internal requestor passed to the searchable name environment
  * so as to process the multiple search results as they are discovered.
@@ -18,7 +20,16 @@
  * to the raw name environment results before answering them to the UI.
  */
 public interface ISearchRequestor {
-	
+	/**
+	 * One result of the search consists of a new annotation.
+	 *
+	 * NOTE - All package and type names are presented in their readable form:
+	 *    Package names are in the form "a.b.c".
+	 *    Nested type names are in the qualified form "A.I".
+	 *    The default package is represented by an empty array.
+	 */
+	public void acceptAnnotation(char[] packageName, char[] typeName, int modifiers, AccessRestriction accessRestriction);
+
 	/**
 	 * One result of the search consists of a new class.
 	 *
@@ -27,7 +38,17 @@
 	 *    Nested type names are in the qualified form "A.M".
 	 *    The default package is represented by an empty array.
 	 */
-	public void acceptClass(char[] packageName, char[] typeName, int modifiers);
+	public void acceptClass(char[] packageName, char[] typeName, int modifiers, AccessRestriction accessRestriction);
+
+	/**
+	 * One result of the search consists of a new enum.
+	 *
+	 * NOTE - All package and type names are presented in their readable form:
+	 *    Package names are in the form "a.b.c".
+	 *    Nested type names are in the qualified form "A.I".
+	 *    The default package is represented by an empty array.
+	 */
+	public void acceptEnum(char[] packageName, char[] typeName, int modifiers, AccessRestriction accessRestriction);
 
 	/**
 	 * One result of the search consists of a new interface.
@@ -37,7 +58,7 @@
 	 *    Nested type names are in the qualified form "A.I".
 	 *    The default package is represented by an empty array.
 	 */
-	public void acceptInterface(char[] packageName, char[] typeName, int modifiers);
+	public void acceptInterface(char[] packageName, char[] typeName, int modifiers, AccessRestriction accessRestriction);
 
 	/**
 	 * One result of the search consists of a new package.
@@ -47,14 +68,4 @@
 	 *    The default package is represented by an empty array.
 	 */
 	public void acceptPackage(char[] packageName);
-
-	/**
-	 * One result of the search consists of a new type.
-	 *
-	 * NOTE - All package and type names are presented in their readable form:
-	 *    Package names are in the form "a.b.c".
-	 *    Nested type names are in the qualified form "A.M".
-	 *    The default package is represented by an empty array.
-	 */
-	public void acceptType(char[] packageName, char[] typeName);
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISearchableNameEnvironment.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISearchableNameEnvironment.java
deleted file mode 100644
index 05b9d00..0000000
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISearchableNameEnvironment.java
+++ /dev/null
@@ -1,48 +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 Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.codeassist;
-
-import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
-
-/**
- * This interface defines the API that may be used to implement any
- * search-based tool (such as a CodeAssist, a Finder, ...).
- * It is mainly used to hide from the search tool the implementation
- * of the underlying environment and its constructions.
- */
-public interface ISearchableNameEnvironment extends INameEnvironment {
-
-	/**
-	 * Find the packages that start with the given prefix.
-	 * A valid prefix is a qualified name separated by periods
-	 * (ex. java.util).
-	 * The packages found are passed to:
-	 *    ISearchRequestor.acceptPackage(char[][] packageName)
-	 */
-	void findPackages(char[] prefix, ISearchRequestor requestor);
-
-	/**
-	 * Find the top-level types (classes and interfaces) that are defined
-	 * in the current environment and whose name starts with the
-	 * given prefix. The prefix is a qualified name separated by periods
-	 * or a simple name (ex. java.util.V or V).
-	 *
-	 * The types found are passed to one of the following methods (if additional
-	 * information is known about the types):
-	 *    ISearchRequestor.acceptType(char[][] packageName, char[] typeName)
-	 *    ISearchRequestor.acceptClass(char[][] packageName, char[] typeName, int modifiers)
-	 *    ISearchRequestor.acceptInterface(char[][] packageName, char[] typeName, int modifiers)
-	 *
-	 * This method can not be used to find member types... member
-	 * types are found relative to their enclosing type.
-	 */
-	void findTypes(char[] prefix, ISearchRequestor requestor);
-}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISelectionRequestor.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISelectionRequestor.java
index 59730f2..cf86981 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISelectionRequestor.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISelectionRequestor.java
@@ -17,6 +17,39 @@
  */
 public interface ISelectionRequestor {
 	/**
+	 * Code assist notification of a enum selection.
+	 * @param packageName char[]
+	 * 		Declaring package name of the type.
+	 * 
+	 * @param annotationName char[]
+	 * 		Name of the type.
+	 * 
+	 * @param isDeclaration boolean
+	 *  	Answer if the selected type is a declaration
+	 *  
+	 * @param uniqueKey
+	 *  	unique key of the selected type if it is a
+	 *  	parameterized type ({@link org.eclipse.jdt.internal.compiler.lookup.Binding#computeUniqueKey()})
+	 * 
+	 * @param start
+	 *  	Start of the selection
+	 * 
+	 * @param end
+	 *  	End of the selection
+	 *
+	 * NOTE - All package and type names are presented in their readable form:
+	 *    Package names are in the form "a.b.c".
+	 *    Nested type names are in the qualified form "A.M".
+	 *    The default package is represented by an empty array.
+	 */
+	void acceptAnnotation(
+		char[] packageName,
+		char[] annotationName,
+		boolean isDeclaration,
+		char[] uniqueKey,
+		int start,
+		int end);
+	/**
 	 * Code assist notification of a class selection.
 	 * @param packageName char[]
 	 * 		Declaring package name of the class.
@@ -24,12 +57,12 @@
 	 * @param className char[]
 	 * 		Name of the class.
 	 * 
-	 * @param needQualification boolean
-	 * 		Flag indicating if the type name 
-	 *    	must be qualified by its package name (depending on imports).
-	 * 
 	 * @param isDeclaration boolean
 	 *  	Answer if the selected method is a declaration
+	 *  
+	 * @param uniqueKey
+	 *  	unique key of the selected type if it is a
+	 *  	parameterized type ({@link org.eclipse.jdt.internal.compiler.lookup.Binding#computeUniqueKey()})
 	 * 
 	 * @param start
 	 *  	Start of the selection
@@ -45,8 +78,42 @@
 	void acceptClass(
 		char[] packageName,
 		char[] className,
-		boolean needQualification,
 		boolean isDeclaration,
+		char[] uniqueKey,
+		int start,
+		int end);
+	
+	/**
+	 * Code assist notification of a enum selection.
+	 * @param packageName char[]
+	 * 		Declaring package name of the type.
+	 * 
+	 * @param enumName char[]
+	 * 		Name of the class.
+	 * 
+	 * @param isDeclaration boolean
+	 *  	Answer if the selected type is a declaration
+	 *  
+	 * @param uniqueKey
+	 *  	unique key of the selected type if it is a
+	 *  	parameterized type ({@link org.eclipse.jdt.internal.compiler.lookup.Binding#computeUniqueKey()})
+	 * 
+	 * @param start
+	 *  	Start of the selection
+	 * 
+	 * @param end
+	 *  	End of the selection
+	 *
+	 * NOTE - All package and type names are presented in their readable form:
+	 *    Package names are in the form "a.b.c".
+	 *    Nested type names are in the qualified form "A.M".
+	 *    The default package is represented by an empty array.
+	 */
+	void acceptEnum(
+		char[] packageName,
+		char[] enumName,
+		boolean isDeclaration,
+		char[] uniqueKey,
 		int start,
 		int end);
 
@@ -78,6 +145,10 @@
 	 * @param isDeclaration boolean
 	 *  	Answer if the selected field is a declaration
 	 * 
+	 * @param uniqueKey
+	 *  	unique key of the selected field if the field's type is a
+	 *  	parameterized type ({@link org.eclipse.jdt.internal.compiler.lookup.Binding#computeUniqueKey()})
+	 *  
 	 * @param start
 	 *  	Start of the selection
 	 * 
@@ -94,6 +165,7 @@
 		char[] declaringTypeName,
 		char[] name,
 		boolean isDeclaration,
+		char[] uniqueKey,
 		int start,
 		int end);
 
@@ -105,12 +177,12 @@
 	 * @param interfaceName char[]
 	 * 		Name of the interface.
 	 * 
-	 * @param needQualification boolean
-	 * 		Flag indicating if the type name 
-	 *    	must be qualified by its package name (depending on imports).
-	 * 
 	 * @param isDeclaration boolean
 	 *  	Answer if the selected method is a declaration
+	 *  
+	 * @param uniqueKey
+	 *  	unique key of the selected type if it is a
+	 *  	parameterized type ({@link org.eclipse.jdt.internal.compiler.lookup.Binding#computeUniqueKey()})
 	 * 
 	 * @param start
 	 *  	Start of the selection
@@ -126,8 +198,8 @@
 	void acceptInterface(
 		char[] packageName,
 		char[] interfaceName,
-		boolean needQualification,
 		boolean isDeclaration,
+		char[] uniqueKey,
 		int start,
 		int end);
 
@@ -139,6 +211,10 @@
 	 * @param declaringTypeName char[]
 	 * 		Name of the type declaring this new method.
 	 * 
+	 * @param enclosingDeclaringTypeSignature String
+	 *  	Type signature of the declaring type of the declaring type or <code>null</code>
+	 *  	if declaring type is a top level type.
+	 * 
 	 * @param selector char[]
 	 * 		Name of the new method.
 	 * 
@@ -150,12 +226,20 @@
 	 * 		Names of the parameters types.
 	 *    	Should contain as many elements as parameterPackageNames.
 	 * 
+	 * @param parameterSignatures String[]
+	 * 		Signature of the parameters types.
+	 *    	Should contain as many elements as parameterPackageNames.
+	 * 
 	 *  @param isConstructor boolean
 	 * 		Answer if the method is a constructor.
 	 * 
 	 * @param isDeclaration boolean
 	 *  	Answer if the selected method is a declaration
 	 * 
+	 * @param uniqueKey
+	 *  	unique key of the selected method if it is a
+	 *  	parameterized method ({@link org.eclipse.jdt.internal.compiler.lookup.Binding#computeUniqueKey()})
+	 *  
 	 * @param start
 	 *  	Start of the selection
 	 * 
@@ -173,11 +257,14 @@
 	void acceptMethod(
 		char[] declaringTypePackageName,
 		char[] declaringTypeName,
+		String enclosingDeclaringTypeSignature,
 		char[] selector,
 		char[][] parameterPackageNames,
 		char[][] parameterTypeNames,
+		String[] parameterSignatures,
 		boolean isConstructor,
 		boolean isDeclaration,
+		char[] uniqueKey,
 		int start,
 		int end);
 	
@@ -191,4 +278,83 @@
 	 *    The default package is represented by an empty array.
 	 */
 	void acceptPackage(char[] packageName);
+	/**
+	 * Code assist notification of a type parameter selection.
+	 * 
+	 * @param declaringTypePackageName char[]
+	 * 		Name of the package in which the type that contains this new method is declared.
+	 * 
+	 * @param declaringTypeName char[]
+	 * 		Name of the type declaring this new method.
+	 * 
+	 * @param typeParameterName char[]
+	 * 		Name of the type parameter.
+	 * 
+	 * @param isDeclaration boolean
+	 *  	Answer if the selected type parameter is a declaration
+	 * 
+	 * @param start
+	 *  	Start of the selection
+	 * 
+	 * @param end
+	 *  	End of the selection
+	 *
+	 * NOTE - All package and type names are presented in their readable form:
+	 *    Package names are in the form "a.b.c".
+	 *    Nested type names are in the qualified form "A.M".
+	 *    The default package is represented by an empty array.
+	 */
+	void acceptTypeParameter(
+		char[] declaringTypePackageName,
+		char[] declaringTypeName,
+		char[] typeParameterName,
+		boolean isDeclaration,
+		int start,
+		int end);
+	
+	/**
+	 * Code assist notification of a type parameter selection.
+	 * 
+	 * @param declaringTypePackageName char[]
+	 * 		Name of the package in which the type that contains this new method is declared.
+	 * 
+	 * @param declaringTypeName char[]
+	 * 		Name of the type declaring this new method.
+	 * 
+	 * @param selector char[]
+	 * 		Name of the declaring method.
+	 * 
+	 * @param selectorStart int
+	 * 		Start of the selector.
+	 * 
+	 * @param selectorEnd int
+	 * 		End of the selector.
+	 * 
+	 * @param typeParameterName char[]
+	 * 		Name of the type parameter.
+	 * 
+	 * @param isDeclaration boolean
+	 *  	Answer if the selected type parameter is a declaration
+	 * 
+	 * @param start
+	 *  	Start of the selection
+	 * 
+	 * @param end
+	 *  	End of the selection
+	 *
+	 * NOTE - All package and type names are presented in their readable form:
+	 *    Package names are in the form "a.b.c".
+	 *    Nested type names are in the qualified form "A.M".
+	 *    The default package is represented by an empty array.
+	 */
+	void acceptMethodTypeParameter(
+		char[] declaringTypePackageName,
+		char[] declaringTypeName,
+		char[] selector,
+		int selectorStart,
+		int selectorEnd,
+		char[] typeParameterName,
+		boolean isDeclaration,
+		int start,
+		int end);
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionProposal.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionProposal.java
new file mode 100644
index 0000000..eb25366
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionProposal.java
@@ -0,0 +1,249 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist;
+
+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.core.BinaryType;
+import org.eclipse.jdt.internal.core.NameLookup;
+
+/**
+ * Internal completion proposal
+ * @since 3.1
+ */
+public class InternalCompletionProposal {
+	private static Object NO_ATTACHED_SOURCE = new Object();
+	
+	static final char[] ARG = "arg".toCharArray();  //$NON-NLS-1$
+	static final char[] ARG0 = "arg0".toCharArray();  //$NON-NLS-1$
+	static final char[] ARG1 = "arg1".toCharArray();  //$NON-NLS-1$
+	static final char[] ARG2 = "arg2".toCharArray();  //$NON-NLS-1$
+	static final char[] ARG3 = "arg3".toCharArray();  //$NON-NLS-1$
+	static final char[][] ARGS1 = new char[][]{ARG0};
+	static final char[][] ARGS2 = new char[][]{ARG0, ARG1};
+	static final char[][] ARGS3 = new char[][]{ARG0, ARG1, ARG2};
+	static final char[][] ARGS4 = new char[][]{ARG0, ARG1, ARG2, ARG3};
+	
+	protected CompletionEngine completionEngine;
+	protected NameLookup nameLookup;
+	
+	protected char[] declarationPackageName;
+	protected char[] declarationTypeName;
+	protected char[] packageName;
+	protected char[] typeName;
+	protected char[][] parameterPackageNames;
+	protected char[][] parameterTypeNames;
+	
+	protected char[][] findMethodParameterNames(char[] signatureType, char[] selector, char[][] paramTypeNames){
+		if(signatureType == null) return null;
+		
+		char[] tName = Signature.toCharArray(signatureType);
+		char[][] parameterNames = null;
+		int length = paramTypeNames.length;
+		
+		Object cachedType = this.completionEngine.typeCache.get(tName);
+		
+		IType type = null;
+		if(cachedType != null) {
+			if(cachedType != NO_ATTACHED_SOURCE && cachedType instanceof BinaryType) {
+				type = (BinaryType)cachedType;
+			}
+		} else { 
+			// TODO (david) shouldn't it be NameLookup.ACCEPT_ALL ?
+			type = this.nameLookup.findType(new String(tName), false, NameLookup.ACCEPT_CLASSES & NameLookup.ACCEPT_INTERFACES);
+			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;
+				}
+			} else {
+				type = null;
+			}
+		}
+		
+		if(type != null) {
+			String[] args = new String[length];
+			for(int i = 0;	i< length ; i++){
+				args[i] = new String(paramTypeNames[i]);
+			}
+			IMethod method = type.getMethod(new String(selector),args);
+			try{
+				parameterNames = new char[length][];
+				String[] params = method.getParameterNames();
+				for(int i = 0;	i< length ; i++){
+					parameterNames[i] = params[i].toCharArray();
+				}
+			} catch(JavaModelException e){
+				parameterNames = null;
+			}
+		}
+		
+//		 default parameters name
+		if(parameterNames == null) {
+			switch (length) {
+				case 0 :
+					parameterNames = new char[length][];
+					break;
+				case 1 :
+					parameterNames = ARGS1;
+					break;
+				case 2 :
+					parameterNames = ARGS2;
+					break;
+				case 3 :
+					parameterNames = ARGS3;
+					break;
+				case 4 :
+					parameterNames = ARGS4;
+					break;
+				default :
+					parameterNames = new char[length][];
+					for (int i = 0; i < length; i++) {
+						parameterNames[i] = CharOperation.concat(ARG, String.valueOf(i).toCharArray());
+					}
+					break;
+			}
+			
+		}
+		
+		return parameterNames;
+	}
+	
+	protected char[] getDeclarationPackageName() {
+		return this.declarationPackageName;
+	}
+	
+	protected char[] getDeclarationTypeName() {
+		return this.declarationTypeName;
+	}
+	
+	protected char[] getPackageName() {
+		return this.packageName;
+	}
+	
+	protected char[] getTypeName() {
+		return this.typeName;
+	}
+	
+	protected char[][] getParameterPackageNames() {
+		return this.parameterPackageNames;
+	}
+	
+	
+	protected char[][] getParameterTypeNames() {
+		return this.parameterTypeNames;
+	}
+	
+	protected char[][] findMethodParameterNames(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, char[][] paramPackageNames, char[][] paramTypeNames){
+		if(paramTypeNames == null) return null;
+		
+		char[][] parameterNames = null;
+		int length = paramTypeNames.length;
+		
+		char[] tName = CharOperation.concat(declaringTypePackageName,declaringTypeName,'.');
+		Object cachedType = this.completionEngine.typeCache.get(tName);
+		
+		IType type = null;
+		if(cachedType != null) {
+			if(cachedType != NO_ATTACHED_SOURCE && cachedType instanceof BinaryType) {
+				type = (BinaryType)cachedType;
+			}
+		} else { 
+			// TODO (david) shouldn't it be NameLookup.ACCEPT_ALL ?
+			type = this.nameLookup.findType(new String(tName), false, NameLookup.ACCEPT_CLASSES & NameLookup.ACCEPT_INTERFACES);
+			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;
+				}
+			} else {
+				type = null;
+			}
+		}
+		
+		if(type != null) {
+			String[] args = new String[length];
+			for(int i = 0;	i< length ; i++){
+				char[] parameterType = CharOperation.concat(paramPackageNames[i],paramTypeNames[i],'.');
+				args[i] = Signature.createTypeSignature(parameterType,true);
+			}
+			IMethod method = type.getMethod(new String(selector),args);
+			try{
+				parameterNames = new char[length][];
+				String[] params = method.getParameterNames();
+				for(int i = 0;	i< length ; i++){
+					parameterNames[i] = params[i].toCharArray();
+				}
+			} catch(JavaModelException e){
+				parameterNames = null;
+			}
+		}
+		// default parameters name
+		if(parameterNames == null) {
+			switch (length) {
+				case 0 :
+					parameterNames = new char[length][];
+					break;
+				case 1 :
+					parameterNames = ARGS1;
+					break;
+				case 2 :
+					parameterNames = ARGS2;
+					break;
+				case 3 :
+					parameterNames = ARGS3;
+					break;
+				case 4 :
+					parameterNames = ARGS4;
+					break;
+				default :
+					parameterNames = new char[length][];
+					for (int i = 0; i < length; i++) {
+						parameterNames[i] = CharOperation.concat(ARG, String.valueOf(i).toCharArray());
+					}
+					break;
+			}
+			
+		}
+		return parameterNames;
+	}
+	
+	protected void setDeclarationPackageName(char[] declarationPackageName) {
+		this.declarationPackageName = declarationPackageName;
+	}
+	
+	protected void setDeclarationTypeName(char[] declarationTypeName) {
+		this.declarationTypeName = declarationTypeName;
+	}
+	
+	protected void setPackageName(char[] packageName) {
+		this.packageName = packageName;
+	}
+	
+	protected void setTypeName(char[] typeName) {
+		this.typeName = typeName;
+	}
+	
+	protected void setParameterPackageNames(char[][] parameterPackageNames) {
+		this.parameterPackageNames = parameterPackageNames;
+	}
+	
+	protected void setParameterTypeNames(char[][] parameterTypeNames) {
+		this.parameterTypeNames = parameterTypeNames;
+	}
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java
index af57daa..94c46fa 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java
@@ -20,6 +20,7 @@
 	int R_EXACT_EXPECTED_TYPE = 30;
 	int R_INTERFACE = 20;
 	int R_CLASS = 20;
+	int R_ANNOTATION = 20;
 	int R_EXCEPTION = 20;
 	int R_ABSTRACT_METHOD = 20;
 	int R_NON_STATIC = 11;
@@ -30,5 +31,6 @@
 	int R_NAME_FIRST_SUFFIX = 4;
 	int R_NAME_SUFFIX = 3;
 	int R_NON_STATIC_OVERIDE = 3;
+	int R_NON_RESTRICTED = 3;
 	
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
index 642504d..5622632 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
@@ -12,6 +12,7 @@
 
 import java.util.*;
 
+import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.internal.codeassist.impl.*;
 import org.eclipse.jdt.internal.codeassist.select.*;
@@ -22,11 +23,11 @@
 import org.eclipse.jdt.internal.compiler.parser.*;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
 import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.core.SearchableEnvironment;
 import org.eclipse.jdt.internal.core.SelectionRequestor;
 import org.eclipse.jdt.internal.core.SourceType;
 import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
 import org.eclipse.jdt.internal.core.util.ASTNodeFinder;
-import org.eclipse.jdt.internal.core.util.ElementInfoConverter;
 
 /**
  * The selection engine is intended to infer the nature of a selected name in some
@@ -48,13 +49,16 @@
 
 	private int actualSelectionStart;
 	private int actualSelectionEnd;
-	private char[] qualifiedSelection;
 	private char[] selectedIdentifier;
 	
 	private char[][][] acceptedClasses;
 	private char[][][] acceptedInterfaces;
+	private char[][][] acceptedEnums;
+	private char[][][] acceptedAnnotations;
 	int acceptedClassesCount;
 	int acceptedInterfacesCount;
+	int acceptedEnumsCount;
+	int acceptedAnnotationsCount;
 	
 	boolean noProposal = true;
 	IProblem problem = null;
@@ -65,7 +69,7 @@
 	 * It requires a searchable name environment, which supports some
 	 * specific search APIs, and a requestor to feed back the results to a UI.
 	 *
-	 *  @param nameEnvironment org.eclipse.jdt.internal.codeassist.ISearchableNameEnvironment
+	 *  @param nameEnvironment org.eclipse.jdt.internal.core.SearchableEnvironment
 	 *      used to resolve type/package references and search for types/packages
 	 *      based on partial names.
 	 *
@@ -77,7 +81,7 @@
 	 *		set of options used to configure the code assist engine.
 	 */
 	public SelectionEngine(
-		ISearchableNameEnvironment nameEnvironment,
+		SearchableEnvironment nameEnvironment,
 		ISelectionRequestor requestor,
 		Map settings) {
 
@@ -122,6 +126,37 @@
 		this.parser = new SelectionParser(problemReporter);
 	}
 
+	public void acceptAnnotation(char[] packageName, char[] typeName, int modifiers, AccessRestriction accessRestriction) {
+		if (CharOperation.equals(typeName, this.selectedIdentifier)) {
+			if(mustQualifyType(packageName, typeName)) {
+				char[][] acceptedAnnotation = new char[2][];
+				acceptedAnnotation[0] = packageName;
+				acceptedAnnotation[1] = typeName;
+				
+				if(this.acceptedAnnotations == null) {
+					this.acceptedAnnotations = new char[10][][];
+					this.acceptedAnnotationsCount = 0;
+				}
+				int length = this.acceptedAnnotations.length;
+				if(length == this.acceptedAnnotationsCount) {
+					System.arraycopy(this.acceptedAnnotations, 0, this.acceptedAnnotations = new char[(length + 1)* 2][][], 0, length);
+				}
+				this.acceptedAnnotations[this.acceptedAnnotationsCount++] = acceptedAnnotation;
+				
+			} else {
+				this.noProposal = false;
+				this.requestor.acceptAnnotation(
+					packageName,
+					typeName,
+					false,
+					null,
+					this.actualSelectionStart,
+					this.actualSelectionEnd);
+				this.acceptedAnswer = true;
+			}
+		}
+	}
+	
 	/**
 	 * One result of the search consists of a new class.
 	 * @param packageName char[]
@@ -133,37 +168,30 @@
 	 *    Nested type names are in the qualified form "A.M".
 	 *    The default package is represented by an empty array.
 	 */
-	public void acceptClass(char[] packageName, char[] className, int modifiers) {
-		if (CharOperation.equals(className, selectedIdentifier)) {
-			if (qualifiedSelection != null
-				&& !CharOperation.equals(
-					qualifiedSelection,
-					CharOperation.concat(packageName, className, '.'))) {
-				return;
-			}
-			
+	public void acceptClass(char[] packageName, char[] className, int modifiers, AccessRestriction accessRestriction) {
+		if (CharOperation.equals(className, this.selectedIdentifier)) {
 			if(mustQualifyType(packageName, className)) {
 				char[][] acceptedClass = new char[2][];
 				acceptedClass[0] = packageName;
 				acceptedClass[1] = className;
 				
-				if(acceptedClasses == null) {
-					acceptedClasses = new char[10][][];
-					acceptedClassesCount = 0;
+				if(this.acceptedClasses == null) {
+					this.acceptedClasses = new char[10][][];
+					this.acceptedClassesCount = 0;
 				}
-				int length = acceptedClasses.length;
-				if(length == acceptedClassesCount) {
-					System.arraycopy(acceptedClasses, 0, acceptedClasses = new char[(length + 1)* 2][][], 0, length);
+				int length = this.acceptedClasses.length;
+				if(length == this.acceptedClassesCount) {
+					System.arraycopy(this.acceptedClasses, 0, this.acceptedClasses = new char[(length + 1)* 2][][], 0, length);
 				}
-				acceptedClasses[acceptedClassesCount++] = acceptedClass;
+				this.acceptedClasses[this.acceptedClassesCount++] = acceptedClass;
 				
 			} else {
-				noProposal = false;
-				requestor.acceptClass(
+				this.noProposal = false;
+				this.requestor.acceptClass(
 					packageName,
 					className,
 					false,
-					false,
+					null,
 					this.actualSelectionStart,
 					this.actualSelectionEnd);
 				this.acceptedAnswer = true;
@@ -171,6 +199,36 @@
 		}
 	}
 
+	public void acceptEnum(char[] packageName, char[] typeName, int modifiers, AccessRestriction accessRestriction) {
+		if (CharOperation.equals(typeName, this.selectedIdentifier)) {
+			if(mustQualifyType(packageName, typeName)) {
+				char[][] acceptedEnum = new char[2][];
+				acceptedEnum[0] = packageName;
+				acceptedEnum[1] = typeName;
+				
+				if(this.acceptedEnums == null) {
+					this.acceptedEnums = new char[10][][];
+					this.acceptedEnumsCount = 0;
+				}
+				int length = this.acceptedEnums.length;
+				if(length == this.acceptedEnumsCount) {
+					System.arraycopy(this.acceptedEnums, 0, this.acceptedEnums = new char[(length + 1)* 2][][], 0, length);
+				}
+				this.acceptedEnums[this.acceptedEnumsCount++] = acceptedEnum;
+				
+			} else {
+				this.noProposal = false;
+				this.requestor.acceptEnum(
+					packageName,
+					typeName,
+					false,
+					null,
+					this.actualSelectionStart,
+					this.actualSelectionEnd);
+				this.acceptedAnswer = true;
+			}
+		}
+	}
 	/**
 	 * One result of the search consists of a new interface.
 	 *
@@ -182,38 +240,32 @@
 	public void acceptInterface(
 		char[] packageName,
 		char[] interfaceName,
-		int modifiers) {
+		int modifiers,
+		AccessRestriction accessRestriction) {
 
-		if (CharOperation.equals(interfaceName, selectedIdentifier)) {
-			if (qualifiedSelection != null
-				&& !CharOperation.equals(
-					qualifiedSelection,
-					CharOperation.concat(packageName, interfaceName, '.'))) {
-				return;
-			}
-			
+		if (CharOperation.equals(interfaceName, this.selectedIdentifier)) {
 			if(mustQualifyType(packageName, interfaceName)) {
 				char[][] acceptedInterface= new char[2][];
 				acceptedInterface[0] = packageName;
 				acceptedInterface[1] = interfaceName;
 				
-				if(acceptedInterfaces == null) {
-					acceptedInterfaces = new char[10][][];
-					acceptedInterfacesCount = 0;
+				if(this.acceptedInterfaces == null) {
+					this.acceptedInterfaces = new char[10][][];
+					this.acceptedInterfacesCount = 0;
 				}
-				int length = acceptedInterfaces.length;
-				if(length == acceptedInterfacesCount) {
-					System.arraycopy(acceptedInterfaces, 0, acceptedInterfaces = new char[(length + 1) * 2][][], 0, length);
+				int length = this.acceptedInterfaces.length;
+				if(length == this.acceptedInterfacesCount) {
+					System.arraycopy(this.acceptedInterfaces, 0, this.acceptedInterfaces = new char[(length + 1) * 2][][], 0, length);
 				}
-				acceptedInterfaces[acceptedInterfacesCount++] = acceptedInterface;
+				this.acceptedInterfaces[this.acceptedInterfacesCount++] = acceptedInterface;
 				
 			} else {
-				noProposal = false;
+				this.noProposal = false;
 				this.requestor.acceptInterface(
 					packageName,
 					interfaceName,
 					false,
-					false,
+					null,
 					this.actualSelectionStart,
 					this.actualSelectionEnd);
 				this.acceptedAnswer = true;
@@ -234,52 +286,67 @@
 	}
 
 	private void acceptQualifiedTypes() {
-		if(acceptedClasses != null){
+		if(this.acceptedClasses != null){
 			this.acceptedAnswer = true;
-			for (int i = 0; i < acceptedClassesCount; i++) {
-				noProposal = false;
+			for (int i = 0; i < this.acceptedClassesCount; i++) {
+				this.noProposal = false;
 				this.requestor.acceptClass(
-					acceptedClasses[i][0],
-					acceptedClasses[i][1],
-					true,
+					this.acceptedClasses[i][0],
+					this.acceptedClasses[i][1],
 					false,
+					null,
 					this.actualSelectionStart,
 					this.actualSelectionEnd);
 			}
-			acceptedClasses = null;
-			acceptedClassesCount = 0;
+			this.acceptedClasses = null;
+			this.acceptedClassesCount = 0;
 		}
-		if(acceptedInterfaces != null){
+		if(this.acceptedInterfaces != null){
 			this.acceptedAnswer = true;
-			for (int i = 0; i < acceptedInterfacesCount; i++) {
-				noProposal = false;
+			for (int i = 0; i < this.acceptedInterfacesCount; i++) {
+				this.noProposal = false;
 				this.requestor.acceptInterface(
-					acceptedInterfaces[i][0],
-					acceptedInterfaces[i][1],
-					true,
+					this.acceptedInterfaces[i][0],
+					this.acceptedInterfaces[i][1],
 					false,
+					null,
 					this.actualSelectionStart,
 					this.actualSelectionEnd);
 			}
-			acceptedInterfaces = null;
-			acceptedInterfacesCount = 0;
+			this.acceptedInterfaces = null;
+			this.acceptedInterfacesCount = 0;
+		}
+		if(this.acceptedAnnotations != null){
+			this.acceptedAnswer = true;
+			for (int i = 0; i < this.acceptedAnnotationsCount; i++) {
+				this.noProposal = false;
+				this.requestor.acceptAnnotation(
+					this.acceptedAnnotations[i][0],
+					this.acceptedAnnotations[i][1],
+					false,
+					null,
+					this.actualSelectionStart,
+					this.actualSelectionEnd);
+			}
+			this.acceptedAnnotations = null;
+			this.acceptedAnnotationsCount = 0;
+		}
+		if(this.acceptedEnums != null){
+			this.acceptedAnswer = true;
+			for (int i = 0; i < this.acceptedEnumsCount; i++) {
+				this.noProposal = false;
+				this.requestor.acceptEnum(
+					this.acceptedEnums[i][0],
+					this.acceptedEnums[i][1],
+					false,
+					null,
+					this.actualSelectionStart,
+					this.actualSelectionEnd);
+			}
+			this.acceptedEnums = null;
+			this.acceptedEnumsCount = 0;
 		}
 	}
-	
-	/**
-	 * One result of the search consists of a new type.
-	 * @param packageName char[]
-	 * @param typeName char[]
-	 * 
-	 * NOTE - All package and type names are presented in their readable form:
-	 *    Package names are in the form "a.b.c".
-	 *    Nested type names are in the qualified form "A.M".
-	 *    The default package is represented by an empty array.
-	 */
-	public void acceptType(char[] packageName, char[] typeName) {
-		acceptClass(packageName, typeName, 0);
-	}
-
 	private boolean checkSelection(
 		char[] source,
 		int selectionStart,
@@ -291,8 +358,7 @@
 		int lastIdentifierStart = -1;
 		int lastIdentifierEnd = -1;
 		char[] lastIdentifier = null;
-		int token, identCount = 0;
-		StringBuffer entireSelection = new StringBuffer(selectionEnd - selectionStart + 1);
+		int token;
 		
 		if(selectionStart > selectionEnd){
 			
@@ -358,59 +424,174 @@
 			scanner.resetTo(selectionStart, selectionEnd);
 	
 			boolean expectingIdentifier = true;
-			
-			do {
-				try {
+			try {
+				do {
 					token = scanner.getNextToken();
-				} catch (InvalidInputException e) {
-					return false;
-				}
-				switch (token) {
-					case TerminalTokens.TokenNamethis :
-					case TerminalTokens.TokenNamesuper :
-					case TerminalTokens.TokenNameIdentifier :
-						if (!expectingIdentifier)
+
+					switch (token) {
+						case TerminalTokens.TokenNamethis :
+						case TerminalTokens.TokenNamesuper :
+						case TerminalTokens.TokenNameIdentifier :
+							if (!expectingIdentifier)
+								return false;
+							lastIdentifier = scanner.getCurrentTokenSource();
+							lastIdentifierStart = scanner.startPosition;
+							lastIdentifierEnd = scanner.currentPosition - 1;
+							if(lastIdentifierEnd > selectionEnd) {
+								lastIdentifierEnd = selectionEnd;
+								lastIdentifier = CharOperation.subarray(lastIdentifier, 0,lastIdentifierEnd - lastIdentifierStart + 1);
+							}
+	
+							expectingIdentifier = false;
+							break;
+						case TerminalTokens.TokenNameDOT :
+							if (expectingIdentifier)
+								return false;
+							expectingIdentifier = true;
+							break;
+						case TerminalTokens.TokenNameEOF :
+							if (expectingIdentifier)
+								return false;
+							break;
+						case TerminalTokens.TokenNameLESS :
+							if(!checkTypeArgument(scanner))
+								return false;
+							break;
+						default :
 							return false;
-						lastIdentifier = scanner.getCurrentTokenSource();
-						lastIdentifierStart = scanner.startPosition;
-						lastIdentifierEnd = scanner.currentPosition - 1;
-						if(lastIdentifierEnd > selectionEnd) {
-							lastIdentifierEnd = selectionEnd;
-							lastIdentifier = CharOperation.subarray(lastIdentifier, 0,lastIdentifierEnd - lastIdentifierStart + 1);
-						}
-						entireSelection.append(lastIdentifier);
-							
-						identCount++;
-						expectingIdentifier = false;
-						break;
-					case TerminalTokens.TokenNameDOT :
-						if (expectingIdentifier)
-							return false;
-						entireSelection.append('.');
-						expectingIdentifier = true;
-						break;
-					case TerminalTokens.TokenNameEOF :
-						if (expectingIdentifier)
-							return false;
-						break;
-					default :
-						return false;
-				}
-			} while (token != TerminalTokens.TokenNameEOF);
+					}
+				} while (token != TerminalTokens.TokenNameEOF);
+			} catch (InvalidInputException e) {
+				return false;
+			}
 		}
 		if (lastIdentifierStart > 0) {
-			actualSelectionStart = lastIdentifierStart;
-			actualSelectionEnd = lastIdentifierEnd;
-			selectedIdentifier = lastIdentifier;
-			if (identCount > 1)
-				qualifiedSelection = entireSelection.toString().toCharArray();
+			this.actualSelectionStart = lastIdentifierStart;
+			this.actualSelectionEnd = lastIdentifierEnd;
+			this.selectedIdentifier = lastIdentifier;
 			return true;
 		}
 		return false;
 	}
+	private boolean checkTypeArgument(Scanner scanner) throws InvalidInputException {
+		int depth = 1;
+		int token;
+		StringBuffer buffer = new StringBuffer();
+		do {
+			token = scanner.getNextToken();
+	
+			switch(token) {
+				case TerminalTokens.TokenNameLESS :
+					depth++;
+					buffer.append(scanner.getCurrentTokenSource());
+					break;
+				case TerminalTokens.TokenNameGREATER :
+					depth--;
+					buffer.append(scanner.getCurrentTokenSource());
+					break;
+				case TerminalTokens.TokenNameRIGHT_SHIFT :
+					depth-=2;
+					buffer.append(scanner.getCurrentTokenSource());
+					break;
+				case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT :
+					depth-=3;
+					buffer.append(scanner.getCurrentTokenSource());
+					break;
+				case TerminalTokens.TokenNameextends :
+				case TerminalTokens.TokenNamesuper :
+					buffer.append(' ');
+					buffer.append(scanner.getCurrentTokenSource());
+					buffer.append(' ');
+					break;
+				case TerminalTokens.TokenNameCOMMA :
+					if(depth == 1) {
+						int length = buffer.length();
+						char[] typeRef = new char[length];
+						buffer.getChars(0, length, typeRef, 0);
+						try {
+							Signature.createTypeSignature(typeRef, true);
+							buffer = new StringBuffer();
+						} catch(IllegalArgumentException e) {
+							return false;
+						}
+					}
+					break;
+				default :
+					buffer.append(scanner.getCurrentTokenSource());
+					break;
+				
+			}
+			if(depth < 0) {
+				return false;
+			}
+		} while (depth != 0 && token != TerminalTokens.TokenNameEOF);
+		
+		if(depth == 0) {
+			int length = buffer.length() - 1;
+			char[] typeRef = new char[length];
+			buffer.getChars(0, length, typeRef, 0);
+			try {
+				Signature.createTypeSignature(typeRef, true);
+				return true;
+			} catch(IllegalArgumentException e) {
+				return false;
+			}
+		}
+		
+		return false;
+	}
 
+	private void completeLocalTypes(Binding binding){
+		switch(binding.kind()) {
+			case Binding.PARAMETERIZED_TYPE :
+			case Binding.RAW_TYPE :
+				ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) binding;
+				this.completeLocalTypes(parameterizedTypeBinding.type);
+				TypeBinding[] args = parameterizedTypeBinding.arguments;
+				int length = args == null ? 0 : args.length;
+				for (int i = 0; i < length; i++) {
+					this.completeLocalTypes(args[i]);
+				}
+				break;
+			case Binding.TYPE :
+			case Binding.GENERIC_TYPE :
+				if(binding instanceof LocalTypeBinding) {
+					LocalTypeBinding localTypeBinding = (LocalTypeBinding) binding;
+					if(localTypeBinding.constantPoolName() == null) {
+						char[] constantPoolName = this.unitScope.computeConstantPoolName(localTypeBinding);
+						localTypeBinding.setConstantPoolName(constantPoolName);
+					}
+				}
+				TypeBinding typeBinding = (TypeBinding) binding;
+				ReferenceBinding enclosingType = typeBinding.enclosingType();
+				if(enclosingType != null) {
+					this.completeLocalTypes(enclosingType);
+				}
+				break;
+			case Binding.ARRAY_TYPE :
+				ArrayBinding arrayBinding = (ArrayBinding) binding;
+				this.completeLocalTypes(arrayBinding.leafComponentType);
+			case Binding.WILDCARD_TYPE :
+			case Binding.TYPE_PARAMETER :
+				break;	
+			case Binding.FIELD :
+				FieldBinding fieldBinding = (FieldBinding) binding;
+				this.completeLocalTypes(fieldBinding.declaringClass);
+				this.completeLocalTypes(fieldBinding.type);
+				break;	
+			case Binding.METHOD :
+				MethodBinding methodBinding = (MethodBinding) binding;
+				this.completeLocalTypes(methodBinding.returnType);
+				TypeBinding[] parameters = methodBinding.parameters;
+				for(int i = 0, max = parameters == null ? 0 : parameters.length; i < max; i++) {
+					this.completeLocalTypes(parameters[i]);
+				}
+				break;
+		}
+	}
+	
 	public AssistParser getParser() {
-		return parser;
+		return this.parser;
 	}
 
 	/*
@@ -418,6 +599,9 @@
 	 * local.
 	 */
 	private boolean isLocal(ReferenceBinding binding) {
+		if(binding instanceof ParameterizedTypeBinding) {
+			return isLocal(((ParameterizedTypeBinding)binding).type);
+		}
 		if (!(binding instanceof SourceTypeBinding)) return false;
 		if (binding instanceof LocalTypeBinding) return true;
 		if (binding instanceof MemberTypeBinding) {
@@ -460,7 +644,7 @@
 			this.acceptedAnswer = false;
 			CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
 			CompilationUnitDeclaration parsedUnit =
-				parser.dietParse(sourceUnit, result, actualSelectionStart, actualSelectionEnd);
+				this.parser.dietParse(sourceUnit, result, this.actualSelectionStart, this.actualSelectionEnd);
 
 			if (parsedUnit != null) {
 				if(DEBUG) {
@@ -472,8 +656,8 @@
 				if (parsedUnit.currentPackage instanceof SelectionOnPackageReference) {
 					char[][] tokens =
 						((SelectionOnPackageReference) parsedUnit.currentPackage).tokens;
-					noProposal = false;
-					requestor.acceptPackage(CharOperation.concatWith(tokens, '.'));
+					this.noProposal = false;
+					this.requestor.acceptPackage(CharOperation.concatWith(tokens, '.'));
 					return;
 				}
 				ImportReference[] imports = parsedUnit.imports;
@@ -482,22 +666,22 @@
 						ImportReference importReference = imports[i];
 						if (importReference instanceof SelectionOnImportReference) {
 							char[][] tokens = ((SelectionOnImportReference) importReference).tokens;
-							noProposal = false;
-							requestor.acceptPackage(CharOperation.concatWith(tokens, '.'));
-							nameEnvironment.findTypes(CharOperation.concatWith(tokens, '.'), this);
+							this.noProposal = false;
+							this.requestor.acceptPackage(CharOperation.concatWith(tokens, '.'));
+							this.nameEnvironment.findTypes(CharOperation.concatWith(tokens, '.'), this);
 							// accept qualified types only if no unqualified type was accepted
-							if(!acceptedAnswer) {
+							if(!this.acceptedAnswer) {
 								acceptQualifiedTypes();
-								if (!acceptedAnswer) {
-									nameEnvironment.findTypes(selectedIdentifier, this);
+								if (!this.acceptedAnswer) {
+									this.nameEnvironment.findTypes(this.selectedIdentifier, this);
 									// try with simple type name
-									if(!acceptedAnswer) {
+									if(!this.acceptedAnswer) {
 										acceptQualifiedTypes();
 									}
 								}
 							}
-							if(noProposal && problem != null) {
-								requestor.acceptError(problem);
+							if(this.noProposal && this.problem != null) {
+								this.requestor.acceptError(this.problem);
 							}
 							return;
 						}
@@ -506,10 +690,10 @@
 				if (parsedUnit.types != null) {
 					if(selectDeclaration(parsedUnit))
 						return;
-					lookupEnvironment.buildTypeBindings(parsedUnit);
+					this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
 					if ((this.unitScope = parsedUnit.scope)  != null) {
 						try {
-							lookupEnvironment.completeTypeBindings(parsedUnit, true);
+							this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
 							parsedUnit.scope.faultInTypes();
 							ASTNode node = parseBlockStatements(parsedUnit, selectionSourceStart);
 							if(DEBUG) {
@@ -535,75 +719,114 @@
 			}
 			// only reaches here if no selection could be derived from the parsed tree
 			// thus use the selected source and perform a textual type search
-			if (!acceptedAnswer) {
-				nameEnvironment.findTypes(selectedIdentifier, this);
+			if (!this.acceptedAnswer) {
+				this.nameEnvironment.findTypes(this.selectedIdentifier, this);
 				
 				// accept qualified types only if no unqualified type was accepted
-				if(!acceptedAnswer) {
+				if(!this.acceptedAnswer) {
 					acceptQualifiedTypes();
 				}
 			}
-			if(noProposal && problem != null) {
-				requestor.acceptError(problem);
+			if(this.noProposal && this.problem != null) {
+				this.requestor.acceptError(this.problem);
 			}
 		} catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D		
+			if(DEBUG) {
+				System.out.println("Exception caught by SelectionEngine:"); //$NON-NLS-1$
+				e.printStackTrace(System.out);
+			}
 		} catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
+			if(DEBUG) {
+				System.out.println("Exception caught by SelectionEngine:"); //$NON-NLS-1$
+				e.printStackTrace(System.out);
+			}
 		} finally {
 			reset();
 		}
 	}
 
 	private void selectFrom(Binding binding, CompilationUnitDeclaration parsedUnit, boolean isDeclaration) {
-		if (binding instanceof ReferenceBinding) {
-			ReferenceBinding typeBinding = (ReferenceBinding) binding;
-			if (qualifiedSelection != null
-				&& !CharOperation.equals(qualifiedSelection, typeBinding.readableName())) {
-				return;
+		if(binding instanceof TypeVariableBinding) {
+			TypeVariableBinding typeVariableBinding = (TypeVariableBinding) binding;
+			Binding enclosingElement = typeVariableBinding.declaringElement;
+			this.noProposal = false;
+			
+			if(enclosingElement instanceof SourceTypeBinding) {
+				SourceTypeBinding enclosingType = (SourceTypeBinding) enclosingElement;
+				this.requestor.acceptTypeParameter(
+					enclosingType.qualifiedPackageName(),
+					enclosingType.qualifiedSourceName(),
+					typeVariableBinding.sourceName(),
+					false,
+					this.actualSelectionStart,
+					this.actualSelectionEnd);
+			} else if(enclosingElement instanceof MethodBinding) {
+				MethodBinding enclosingMethod = (MethodBinding) enclosingElement;
+				
+				this.requestor.acceptMethodTypeParameter(
+					enclosingMethod.declaringClass.qualifiedPackageName(),
+					enclosingMethod.declaringClass.qualifiedSourceName(),
+					enclosingMethod.selector,
+					enclosingMethod.sourceStart(),
+					enclosingMethod.sourceEnd(),
+					typeVariableBinding.sourceName(),
+					false,
+					this.actualSelectionStart,
+					this.actualSelectionEnd);
 			}
-			if (typeBinding.isInterface()) {
-				noProposal = false;
-				if (isLocal(typeBinding) && this.requestor instanceof SelectionRequestor) {
-					((SelectionRequestor)this.requestor).acceptLocalType(
-						(SourceTypeBinding)typeBinding,
-						parsedUnit);
-				} else {
+			this.acceptedAnswer = true;
+		} else if (binding instanceof ReferenceBinding) {
+			ReferenceBinding typeBinding = (ReferenceBinding) binding;
+			
+			if(typeBinding instanceof ProblemReferenceBinding) {
+				typeBinding = ((ProblemReferenceBinding) typeBinding).original;
+			}
+			if (typeBinding == null) return;
+			if (isLocal(typeBinding) && this.requestor instanceof SelectionRequestor) {
+				this.noProposal = false;
+				if(typeBinding.isParameterizedType() || typeBinding.isRawType()) {
+					completeLocalTypes(typeBinding);
+				}
+				((SelectionRequestor)this.requestor).acceptLocalType(typeBinding);
+			} else {
+				this.noProposal = false;
+				
+				char[] genericTypeSignature = null;
+				if(typeBinding.isParameterizedType() || typeBinding.isRawType()) {
+					completeLocalTypes(typeBinding);
+					genericTypeSignature = typeBinding.computeUniqueKey();
+				}
+				if (typeBinding.isAnnotationType()) {
+					this.requestor.acceptAnnotation(
+						typeBinding.qualifiedPackageName(),
+						typeBinding.qualifiedSourceName(),
+						false,
+						genericTypeSignature,
+						this.actualSelectionStart,
+						this.actualSelectionEnd);
+				} else if (typeBinding.isInterface()) {
 					this.requestor.acceptInterface(
 						typeBinding.qualifiedPackageName(),
 						typeBinding.qualifiedSourceName(),
 						false,
-						false,
+						genericTypeSignature,
 						this.actualSelectionStart,
 						this.actualSelectionEnd);
-				}
-			} else if(typeBinding instanceof ProblemReferenceBinding){
-				ReferenceBinding original = ((ProblemReferenceBinding) typeBinding).original;
-				if(original == null) return;
-				noProposal = false;
-				if (isLocal(original) && this.requestor instanceof SelectionRequestor) {
-					((SelectionRequestor)this.requestor).acceptLocalType(
-						(SourceTypeBinding)original,
-						parsedUnit);
-				} else {
-					this.requestor.acceptClass(
-						original.qualifiedPackageName(),
-						original.qualifiedSourceName(),
+				} else if (typeBinding.isEnum()) {
+					this.requestor.acceptEnum(
+						typeBinding.qualifiedPackageName(),
+						typeBinding.qualifiedSourceName(),
 						false,
-						false,
+						genericTypeSignature,
 						this.actualSelectionStart,
 						this.actualSelectionEnd);
-				}
-			} else {
-				noProposal = false;
-				if (isLocal(typeBinding) && this.requestor instanceof SelectionRequestor) {
-					((SelectionRequestor)this.requestor).acceptLocalType(
-						(SourceTypeBinding)typeBinding,
-						parsedUnit);
 				} else {
+					this.noProposal = false;
 					this.requestor.acceptClass(
 						typeBinding.qualifiedPackageName(),
 						typeBinding.qualifiedSourceName(),
 						false,
-						false,
+						genericTypeSignature,
 						this.actualSelectionStart,
 						this.actualSelectionEnd);
 				}
@@ -612,42 +835,44 @@
 		} else
 			if (binding instanceof MethodBinding) {
 				MethodBinding methodBinding = (MethodBinding) binding;
-				TypeBinding[] parameterTypes = methodBinding.parameters;
+				TypeBinding[] parameterTypes = methodBinding.original().parameters;
 				int length = parameterTypes.length;
 				char[][] parameterPackageNames = new char[length][];
 				char[][] parameterTypeNames = new char[length][];
+				String[] parameterSignatures = new String[length];
 				for (int i = 0; i < length; i++) {
 					parameterPackageNames[i] = parameterTypes[i].qualifiedPackageName();
 					parameterTypeNames[i] = parameterTypes[i].qualifiedSourceName();
+					parameterSignatures[i] = new String(getSignature(parameterTypes[i])).replace('/', '.');
 				}
-				noProposal = false;
+				this.noProposal = false;
 				ReferenceBinding declaringClass = methodBinding.declaringClass;
 				if (isLocal(declaringClass) && this.requestor instanceof SelectionRequestor) {
-					((SelectionRequestor)this.requestor).acceptLocalMethod(
-						(SourceTypeBinding)declaringClass,
-						methodBinding.isConstructor()
-							? declaringClass.sourceName()
-							: methodBinding.selector,
-						parameterPackageNames,
-						parameterTypeNames,
-						methodBinding.isConstructor(),
-						parsedUnit,
-						isDeclaration,
-						actualSelectionStart,
-						actualSelectionEnd);
+					if(methodBinding instanceof ParameterizedMethodBinding) {
+						completeLocalTypes(methodBinding);
+					}
+					((SelectionRequestor)this.requestor).acceptLocalMethod(methodBinding);
 				} else {
+					char[] uniqueKey = null;
+					if(methodBinding instanceof ParameterizedMethodBinding) {
+						completeLocalTypes(methodBinding);
+						uniqueKey = methodBinding.computeUniqueKey();
+					}
 					this.requestor.acceptMethod(
 						declaringClass.qualifiedPackageName(),
 						declaringClass.qualifiedSourceName(),
+						declaringClass.enclosingType() == null ? null : new String(getSignature(declaringClass.enclosingType())),
 						methodBinding.isConstructor()
 							? declaringClass.sourceName()
 							: methodBinding.selector,
 						parameterPackageNames,
 						parameterTypeNames,
+						parameterSignatures,
 						methodBinding.isConstructor(), 
 						isDeclaration,
-						actualSelectionStart,
-						actualSelectionEnd);
+						uniqueKey,
+						this.actualSelectionStart,
+						this.actualSelectionEnd);
 				}
 				this.acceptedAnswer = true;
 			} else
@@ -655,18 +880,24 @@
 					FieldBinding fieldBinding = (FieldBinding) binding;
 					ReferenceBinding declaringClass = fieldBinding.declaringClass;
 					if (declaringClass != null) { // arraylength
-						noProposal = false;
+						this.noProposal = false;
 						if (isLocal(declaringClass) && this.requestor instanceof SelectionRequestor) {
-							((SelectionRequestor)this.requestor).acceptLocalField(
-								(SourceTypeBinding)declaringClass,
-								fieldBinding.name,
-								parsedUnit);
+							if(fieldBinding instanceof ParameterizedFieldBinding) {
+								completeLocalTypes(fieldBinding.declaringClass);
+							}
+							((SelectionRequestor)this.requestor).acceptLocalField(fieldBinding);
 						} else {
+							char[] uniqueKey = null;
+							if(fieldBinding instanceof ParameterizedFieldBinding) {
+								completeLocalTypes(fieldBinding.declaringClass);
+								uniqueKey = fieldBinding.computeUniqueKey();
+							}
 							this.requestor.acceptField(
 								declaringClass.qualifiedPackageName(),
 								declaringClass.qualifiedSourceName(),
 								fieldBinding.name,
 								false,
+								uniqueKey,
 								this.actualSelectionStart,
 								this.actualSelectionEnd);
 						}
@@ -675,9 +906,7 @@
 				} else
 					if (binding instanceof LocalVariableBinding) {
 						if (this.requestor instanceof SelectionRequestor) {
-							((SelectionRequestor)this.requestor).acceptLocalVariable(
-								(LocalVariableBinding)binding,
-								parsedUnit);
+							((SelectionRequestor)this.requestor).acceptLocalVariable((LocalVariableBinding)binding);
 							this.acceptedAnswer = true;
 						} else {
 							// open on the type of the variable
@@ -690,8 +919,8 @@
 						} else
 							if (binding instanceof PackageBinding) {
 								PackageBinding packageBinding = (PackageBinding) binding;
-								noProposal = false;
-								requestor.acceptPackage(packageBinding.readableName());
+								this.noProposal = false;
+								this.requestor.acceptPackage(packageBinding.readableName());
 								this.acceptedAnswer = true;
 							} else
 								if(binding instanceof BaseTypeBinding) {
@@ -798,10 +1027,13 @@
 			CompilationResult result = new CompilationResult(outerType.getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
 			if (!(sourceType instanceof SourceTypeElementInfo)) return;
 			SourceType typeHandle = (SourceType) ((SourceTypeElementInfo)sourceType).getHandle();
+			int flags = SourceTypeConverter.FIELD_AND_METHOD | SourceTypeConverter.MEMBER_TYPE;
+			if (typeHandle.isAnonymous() || typeHandle.isLocal()) 
+				flags |= SourceTypeConverter.LOCAL_TYPE;
 			CompilationUnitDeclaration parsedUnit =
-				ElementInfoConverter.buildCompilationUnit(
+				SourceTypeConverter.buildCompilationUnit(
 						topLevelTypes,
-						typeHandle.isAnonymous() || typeHandle.isLocal(),
+						flags,
 						this.parser.problemReporter(), 
 						result);
 
@@ -838,7 +1070,7 @@
 					typeDecl.fields = new FieldDeclaration[] { field };
 
 					// build bindings
-					lookupEnvironment.buildTypeBindings(parsedUnit);
+					this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
 					if ((this.unitScope = parsedUnit.scope) != null) {
 						try {
 							// build fields
@@ -863,18 +1095,18 @@
 			}
 			// only reaches here if no selection could be derived from the parsed tree
 			// thus use the selected source and perform a textual type search
-			if (!acceptedAnswer && searchInEnvironment) {
+			if (!this.acceptedAnswer && searchInEnvironment) {
 				if (this.selectedIdentifier != null) {
-					nameEnvironment.findTypes(typeName, this);
+					this.nameEnvironment.findTypes(typeName, this);
 					
 					// accept qualified types only if no unqualified type was accepted
-					if(!acceptedAnswer) {
+					if(!this.acceptedAnswer) {
 						acceptQualifiedTypes();
 					}
 				}
 			}
-			if(noProposal && problem != null) {
-				requestor.acceptError(problem);
+			if(this.noProposal && this.problem != null) {
+				this.requestor.acceptError(this.problem);
 			}
 		} catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
 		} finally {
@@ -912,24 +1144,44 @@
 				qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.');
 				enclosingType = enclosingType.enclosingType;
 			}
-			
-			if(!typeDeclaration.isInterface()) {
-				this.requestor.acceptClass(
-					packageName,
-					qualifiedSourceName,
-					false,
-					true,
-					this.actualSelectionStart,
-					this.actualSelectionEnd);
-			} else {
-				this.requestor.acceptInterface(
-					packageName,
-					qualifiedSourceName,
-					false,
-					true,
-					this.actualSelectionStart,
-					this.actualSelectionEnd);
-			}
+			switch (typeDeclaration.kind()) {
+				case IGenericType.CLASS_DECL :
+					this.requestor.acceptClass(
+						packageName,
+						qualifiedSourceName,
+						true,
+						null,
+						this.actualSelectionStart,
+						this.actualSelectionEnd);
+					break;
+				case IGenericType.INTERFACE_DECL :
+					this.requestor.acceptInterface(
+						packageName,
+						qualifiedSourceName,
+						true,
+						null,
+						this.actualSelectionStart,
+						this.actualSelectionEnd);
+					break;
+				case IGenericType.ENUM_DECL :
+					this.requestor.acceptEnum(
+						packageName,
+						qualifiedSourceName,
+						true,
+						null,
+						this.actualSelectionStart,
+						this.actualSelectionEnd);
+					break;
+				case IGenericType.ANNOTATION_TYPE_DECL :
+					this.requestor.acceptAnnotation(
+						packageName,
+						qualifiedSourceName,
+						true,
+						null,
+						this.actualSelectionStart,
+						this.actualSelectionEnd);
+					break;
+			}			
 			this.noProposal = false;
 			return true;
 		}
@@ -954,6 +1206,7 @@
 					qualifiedSourceName,
 					fields[i].name,
 					true,
+					null,
 					this.actualSelectionStart,
 					this.actualSelectionEnd);
 
@@ -964,6 +1217,7 @@
 		AbstractMethodDeclaration[] methods = typeDeclaration.methods;
 		for (int i = 0, length = methods == null ? 0 : methods.length; i < length; i++){
 			AbstractMethodDeclaration method = methods[i];
+			
 			if (method.selector == assistIdentifier){
 				char[] qualifiedSourceName = null;
 				
@@ -976,11 +1230,68 @@
 				this.requestor.acceptMethod(
 					packageName,
 					qualifiedSourceName,
+					null, // SelectionRequestor does not need of declaring type signature for method declaration
 					method.selector,
 					null, // SelectionRequestor does not need of parameters type for method declaration
 					null, // SelectionRequestor does not need of parameters type for method declaration
+					null, // SelectionRequestor does not need of parameters type for method declaration
 					method.isConstructor(),
 					true,
+					null,
+					this.actualSelectionStart,
+					this.actualSelectionEnd);
+				
+				this.noProposal = false;
+				return true;
+			}
+			
+			TypeParameter[] methodTypeParameters = method.typeParameters();
+			for (int j = 0, length2 = methodTypeParameters == null ? 0 : methodTypeParameters.length; j < length2; j++){
+				TypeParameter methodTypeParameter = methodTypeParameters[j];
+				
+				if(methodTypeParameter.name == assistIdentifier) {
+					char[] qualifiedSourceName = null;
+					
+					TypeDeclaration enclosingType = typeDeclaration;
+					while(enclosingType != null) {
+						qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.');
+						enclosingType = enclosingType.enclosingType;
+					}
+					
+					this.requestor.acceptMethodTypeParameter(
+						packageName,
+						qualifiedSourceName,
+						method.selector,
+						method.sourceStart,
+						method.sourceEnd,
+						methodTypeParameter.name,
+						true,
+						this.actualSelectionStart,
+						this.actualSelectionEnd);
+					
+					this.noProposal = false;
+					return true;
+				}
+			}
+		}
+		
+		TypeParameter[] typeParameters = typeDeclaration.typeParameters;
+		for (int i = 0, length = typeParameters == null ? 0 : typeParameters.length; i < length; i++){
+			TypeParameter typeParameter = typeParameters[i];
+			if(typeParameter.name == assistIdentifier) {
+				char[] qualifiedSourceName = null;
+				
+				TypeDeclaration enclosingType = typeDeclaration;
+				while(enclosingType != null) {
+					qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.');
+					enclosingType = enclosingType.enclosingType;
+				}
+				
+				this.requestor.acceptTypeParameter(
+					packageName,
+					qualifiedSourceName,
+					typeParameter.name,
+					true,
 					this.actualSelectionStart,
 					this.actualSelectionEnd);
 				
@@ -988,6 +1299,7 @@
 				return true;
 			}
 		}
+		
 		return false;
 	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java
index a55afda..71fd1ca 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java
@@ -32,11 +32,11 @@
 	}
 	
 	public boolean containsCompletionNode() {
-		return result;
+		return this.result;
 	}
 	
 	public ASTNode getCompletionNodeParent() {
-		return parent;
+		return this.parent;
 	}
 	public void endVisit(AllocationExpression allocationExpression, BlockScope scope) {
 		endVisit(allocationExpression);
@@ -98,6 +98,18 @@
 	public void endVisit(OR_OR_Expression or_or_Expression, BlockScope scope) {
 		endVisit(or_or_Expression);
 	}
+	public void endVisit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, BlockScope scope) {
+		endVisit(parameterizedQualifiedTypeReference);
+	}
+	public void endVisit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, ClassScope scope) {
+		endVisit(parameterizedQualifiedTypeReference);
+	}
+	public void endVisit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, BlockScope scope) {
+		endVisit(parameterizedSingleTypeReference);
+	}
+	public void endVisit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, ClassScope scope) {
+		endVisit(parameterizedSingleTypeReference);
+	}
 	public void endVisit(PostfixExpression postfixExpression, BlockScope scope) {
 		endVisit(postfixExpression);
 	}
@@ -200,6 +212,18 @@
 	public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) {
 		return this.visit(or_or_Expression);
 	}
+	public boolean visit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, BlockScope scope) {
+		return this.visit(parameterizedQualifiedTypeReference);
+	}
+	public boolean visit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, ClassScope scope) {
+		return this.visit(parameterizedQualifiedTypeReference);
+	}
+	public boolean visit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, BlockScope scope) {
+		return this.visit(parameterizedSingleTypeReference);
+	}
+	public boolean visit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, ClassScope scope) {
+		return this.visit(parameterizedSingleTypeReference);
+	}
 	public boolean visit(PostfixExpression postfixExpression, BlockScope scope) {
 		return this.visit(postfixExpression);
 	}
@@ -244,18 +268,18 @@
 	}
 	
 	private void endVisit(ASTNode astNode) {
-		if(result && parent == null && astNode != searchedNode) {
-			if(!(astNode instanceof AllocationExpression && ((AllocationExpression) astNode).type == searchedNode)
-				&& !(astNode instanceof ConditionalExpression && ((ConditionalExpression) astNode).valueIfTrue == searchedNode)
-				&& !(astNode instanceof ConditionalExpression && ((ConditionalExpression) astNode).valueIfFalse == searchedNode)) {
-				parent = astNode;	
+		if(this.result && this.parent == null && astNode != this.searchedNode) {
+			if(!(astNode instanceof AllocationExpression && ((AllocationExpression) astNode).type == this.searchedNode)
+				&& !(astNode instanceof ConditionalExpression && ((ConditionalExpression) astNode).valueIfTrue == this.searchedNode)
+				&& !(astNode instanceof ConditionalExpression && ((ConditionalExpression) astNode).valueIfFalse == this.searchedNode)) {
+				this.parent = astNode;	
 			}
 		}
 	}
 	private boolean visit(ASTNode astNode) {
-		if(astNode == searchedNode) {
-			result = true;
+		if(astNode == this.searchedNode) {
+			this.result = true;
 		}
-		return !result;
+		return !this.result;
 	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeFound.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeFound.java
index ed49fc0..43e6d33 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeFound.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeFound.java
@@ -15,9 +15,13 @@
 import org.eclipse.jdt.internal.compiler.lookup.Scope;
 
 public class CompletionNodeFound extends RuntimeException {
+	
 	public ASTNode astNode;
 	public Binding qualifiedBinding;
 	public Scope scope;
+
+	private static final long serialVersionUID = 6981437684184091462L; // backward compatible
+	
 public CompletionNodeFound() {
 	this(null, null, null); // we found a problem in the completion node
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnAnnotationOfType.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnAnnotationOfType.java
new file mode 100644
index 0000000..9bf48e9
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnAnnotationOfType.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.complete;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+
+public class CompletionOnAnnotationOfType extends TypeDeclaration {
+	public CompletionOnAnnotationOfType(CompilationResult compilationResult, Annotation annotation){
+		super(compilationResult);
+		this.sourceEnd = annotation.sourceEnd;
+		this.sourceStart = annotation.sourceEnd;
+		this.name = CharOperation.NO_CHAR;
+		this.annotations = new Annotation[]{annotation};
+	}
+	
+	public StringBuffer print(int indent, StringBuffer output) {
+		return this.annotations[0].print(indent, output);
+	}
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnArgumentName.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnArgumentName.java
index f5a087b..bfe8798 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnArgumentName.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnArgumentName.java
@@ -40,11 +40,11 @@
 		
 		printIndent(indent, output);
 		output.append("<CompleteOnArgumentName:"); //$NON-NLS-1$
-		if (type != null) type.print(0, output).append(' ');
+		if (this.type != null) this.type.print(0, output).append(' ');
 		output.append(this.realName);
-		if (initialization != null) {
+		if (this.initialization != null) {
 			output.append(" = "); //$NON-NLS-1$
-			initialization.printExpression(0, output);
+			this.initialization.printExpression(0, output);
 		}
 		return output.append('>');
 	}	
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassLiteralAccess.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassLiteralAccess.java
index 124276e..9e5e4fa 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassLiteralAccess.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassLiteralAccess.java
@@ -48,7 +48,7 @@
 	public StringBuffer printExpression(int indent, StringBuffer output) {
 		
 		output.append("<CompleteOnClassLiteralAccess:"); //$NON-NLS-1$
-		return type.print(0, output).append('.').append(completionIdentifier).append('>');
+		return this.type.print(0, output).append('.').append(this.completionIdentifier).append('>');
 	}
 	
 	public TypeBinding resolveType(BlockScope scope) {
@@ -56,6 +56,6 @@
 		if (super.resolveType(scope) == null)
 			throw new CompletionNodeFound();
 		else
-			throw new CompletionNodeFound(this, targetType, scope);
+			throw new CompletionNodeFound(this, this.targetType, scope);
 	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassReference.java
index 842a387..3613f5e 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassReference.java
@@ -19,6 +19,6 @@
 
 	public StringBuffer printExpression(int indent, StringBuffer output) {
 		
-		return output.append("<CompleteOnClass:").append(token).append('>'); //$NON-NLS-1$
+		return output.append("<CompleteOnClass:").append(this.token).append('>'); //$NON-NLS-1$
 	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java
index d178c14..c424dc4 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java
@@ -45,6 +45,6 @@
 
 	public StringBuffer printExpression(int indent, StringBuffer output) {
 		
-		return output.append("<CompleteOnException:").append(token).append('>'); //$NON-NLS-1$
+		return output.append("<CompleteOnException:").append(this.token).append('>'); //$NON-NLS-1$
 	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExplicitConstructorCall.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExplicitConstructorCall.java
index 18d7f8a..234d7ba 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExplicitConstructorCall.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExplicitConstructorCall.java
@@ -45,16 +45,16 @@
 		
 		printIndent(tab, output);
 		output.append("<CompleteOnExplicitConstructorCall:"); //$NON-NLS-1$
-		if (qualification != null) qualification.printExpression(0, output).append('.');
-		if (accessMode == This) {
+		if (this.qualification != null) this.qualification.printExpression(0, output).append('.');
+		if (this.accessMode == This) {
 			output.append("this("); //$NON-NLS-1$
 		} else {
 			output.append("super("); //$NON-NLS-1$
 		}
-		if (arguments != null) {
-			for (int i = 0; i < arguments.length; i++) {
+		if (this.arguments != null) {
+			for (int i = 0; i < this.arguments.length; i++) {
 				if (i > 0) output.append(", "); //$NON-NLS-1$
-				arguments[i].printExpression(0, output);
+				this.arguments[i].printExpression(0, output);
 			}
 		}
 		return output.append(")>;"); //$NON-NLS-1$
@@ -64,13 +64,13 @@
 
 		ReferenceBinding receiverType = scope.enclosingSourceType();
 		
-		if (arguments != null) {
-			int argsLength = arguments.length;
+		if (this.arguments != null) {
+			int argsLength = this.arguments.length;
 			for (int a = argsLength; --a >= 0;)
-				arguments[a].resolveType(scope);
+				this.arguments[a].resolveType(scope);
 		}
 	
-		if (accessMode != This && receiverType != null) {
+		if (this.accessMode != This && receiverType != null) {
 			if (receiverType.isHierarchyInconsistent())
 				throw new CompletionNodeFound();
 			receiverType = receiverType.superclass();
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnFieldType.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnFieldType.java
index b2730fc..32debe3 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnFieldType.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnFieldType.java
@@ -33,7 +33,6 @@
  
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class CompletionOnFieldType extends FieldDeclaration {
 	public boolean isLocalVariable;
@@ -45,15 +44,12 @@
 	this.type = type;
 	this.name = CharOperation.NO_CHAR;
 	this.isLocalVariable = isLocalVariable;
+	if (type instanceof CompletionOnSingleTypeReference) {
+	    ((CompletionOnSingleTypeReference) type).fieldTypeCompletionNode = this;
+	}
 }
-public TypeBinding getTypeBinding(Scope scope) {
-	if(type instanceof CompletionOnSingleTypeReference)
-		throw new CompletionNodeFound(this, scope);
-	else // handle the qualified type ref directly
-		return type.getTypeBinding(scope);
-}
-public StringBuffer printStatement(int tab, StringBuffer output) {
 
+public StringBuffer printStatement(int tab, StringBuffer output) {
 	return type.print(tab, output).append(';'); 
 }
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword1.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword1.java
index 84dd7be..7625f7a 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword1.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword1.java
@@ -32,7 +32,7 @@
 	public void aboutToResolve(Scope scope) {
 		getTypeBinding(scope);
 	}
-	public TypeBinding getTypeBinding(Scope scope) {
+	protected TypeBinding getTypeBinding(Scope scope) {
 		throw new CompletionNodeFound(this, scope);
 	}
 	public StringBuffer printExpression(int indent, StringBuffer output){
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMarkerAnnotationName.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMarkerAnnotationName.java
new file mode 100644
index 0000000..eb42584
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMarkerAnnotationName.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.complete;
+
+import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+public class CompletionOnMarkerAnnotationName extends MarkerAnnotation {
+	public CompletionOnMarkerAnnotationName(TypeReference type, int sourceStart){
+		super(type, sourceStart);
+	}
+	
+	public TypeBinding resolveType(BlockScope scope) {
+		throw new CompletionNodeFound(this, null, scope);
+	}
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMessageSend.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMessageSend.java
index c25ec60..c52ca37 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMessageSend.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMessageSend.java
@@ -47,13 +47,13 @@
 		if (receiver.isImplicitThis())
 			throw new CompletionNodeFound(this, null, scope);
 
-		this.receiverType = receiver.resolveType(scope);
-		if (this.receiverType == null || this.receiverType.isBaseType())
+		this.actualReceiverType = receiver.resolveType(scope);
+		if (this.actualReceiverType == null || this.actualReceiverType.isBaseType())
 			throw new CompletionNodeFound();
 
-		if (this.receiverType.isArrayType())
-			this.receiverType = scope.getJavaLangObject();
-		throw new CompletionNodeFound(this, this.receiverType, scope);
+		if (this.actualReceiverType.isArrayType())
+			this.actualReceiverType = scope.getJavaLangObject();
+		throw new CompletionNodeFound(this, this.actualReceiverType, scope);
 	}
 
 	public StringBuffer printExpression(int indent, StringBuffer output) {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMethodTypeParameter.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMethodTypeParameter.java
new file mode 100644
index 0000000..15ecbc2
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMethodTypeParameter.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.complete;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
+
+public class CompletionOnMethodTypeParameter extends MethodDeclaration {
+	public CompletionOnMethodTypeParameter(TypeParameter[] typeParameters, CompilationResult compilationResult){
+		super(compilationResult);
+		this.selector = CharOperation.NO_CHAR;
+		this.typeParameters = typeParameters;
+		this.sourceStart = typeParameters[0].sourceStart;
+		this.sourceEnd = typeParameters[typeParameters.length - 1].sourceEnd;
+	}
+	
+	public void resolveStatements() {
+			throw new CompletionNodeFound(this, this.scope);
+	}
+	
+	public StringBuffer print(int tab, StringBuffer output) {
+		printIndent(tab, output);
+		output.append('<');//$NON-NLS-1$
+		int max = typeParameters.length - 1;
+		for (int j = 0; j < max; j++) {
+			typeParameters[j].print(0, output);
+			output.append(", ");//$NON-NLS-1$
+		}
+		typeParameters[max].print(0, output);
+		output.append('>');
+		return output;
+	}
+
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnParameterizedQualifiedTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnParameterizedQualifiedTypeReference.java
new file mode 100644
index 0000000..09c798d
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnParameterizedQualifiedTypeReference.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce a type reference containing the completion identifier as part
+ * of a parameterized qualified name.
+ * e.g.
+ *
+ *	class X extends Y<Z>.W[cursor]
+ *
+ *	---> class X extends <CompleteOnType:Y<Z>.W>
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+
+public class CompletionOnParameterizedQualifiedTypeReference extends ParameterizedQualifiedTypeReference {
+	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;
+	/**
+	 * @param tokens
+	 * @param typeArguments
+	 * @param positions
+	 */
+	public CompletionOnParameterizedQualifiedTypeReference(char[][] tokens,	TypeReference[][] typeArguments, char[] completionIdentifier, long[] positions) {
+		this(tokens, typeArguments, completionIdentifier, positions, K_TYPE);
+	}
+	
+	/**
+	 * @param tokens
+	 * @param typeArguments
+	 * @param positions
+	 * @param kind
+	 */
+	public CompletionOnParameterizedQualifiedTypeReference(char[][] tokens,	TypeReference[][] typeArguments, char[] completionIdentifier, long[] positions, int kind) {
+		super(tokens, typeArguments, 0, positions);
+		this.completionIdentifier = completionIdentifier;
+		this.kind = kind;
+	}
+	
+	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 TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
+		super.resolveType(scope, checkBounds);
+		throw new CompletionNodeFound(this, this.resolvedType, scope);
+	}
+	
+	public TypeBinding resolveType(ClassScope scope) {
+		super.resolveType(scope);
+		throw new CompletionNodeFound(this, this.resolvedType, scope);
+	}
+	
+	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;
+		}
+		int length = tokens.length;
+		for (int i = 0; i < length - 1; i++) {
+			output.append(tokens[i]);
+			TypeReference[] typeArgument = typeArguments[i];
+			if (typeArgument != null) {
+				output.append('<');//$NON-NLS-1$
+				int max = typeArgument.length - 1;
+				for (int j = 0; j < max; j++) {
+					typeArgument[j].print(0, output);
+					output.append(", ");//$NON-NLS-1$
+				}
+				typeArgument[max].print(0, output);
+				output.append('>');
+			}
+			output.append('.');
+		}
+		output.append(tokens[length - 1]);
+		TypeReference[] typeArgument = typeArguments[length - 1];
+		if (typeArgument != null) {
+			output.append('<');//$NON-NLS-1$
+			int max = typeArgument.length - 1;
+			for (int j = 0; j < max; j++) {
+				typeArgument[j].print(0, output);
+				output.append(", ");//$NON-NLS-1$
+			}
+			typeArgument[max].print(0, output);
+			output.append('>');
+		}
+		output.append('.').append(completionIdentifier).append('>'); 
+		return output;
+	}	
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java
index 61a6e23..9c6cb99 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java
@@ -56,7 +56,7 @@
 		if (this.resolvedType.isInterface()) // handle the anonymous class definition case
 			this.resolvedType = scope.getJavaLangObject();
 	} else {
-		this.resolvedType = type.resolveType(scope);
+		this.resolvedType = type.resolveType(scope, true /* check bounds*/);
 		if (!(this.resolvedType instanceof ReferenceBinding))
 			throw new CompletionNodeFound(); // no need to continue if its an array or base type
 	}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
index 91349ff..5ebb6bc 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
@@ -42,7 +42,7 @@
 public TypeReference copyDims(int dim){
 	return this;
 }
-public TypeBinding getTypeBinding(Scope scope) {
+protected TypeBinding getTypeBinding(Scope scope) {
 	// it can be a package, type or member type
 	Binding binding = scope.parent.getTypeOrPackage(tokens); // step up from the ClassScope
 	if (!binding.isValidBinding()) {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
index 18833f6..aadb11d 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
@@ -29,6 +29,8 @@
 
 public class CompletionOnSingleTypeReference extends SingleTypeReference {
 public boolean isCompletionNode;
+public CompletionOnFieldType fieldTypeCompletionNode;
+
 public CompletionOnSingleTypeReference(char[] source, long pos) {
 	super(source, pos);
 	isCompletionNode = true;
@@ -42,7 +44,10 @@
 public TypeReference copyDims(int dim){
 	return this;
 }
-public TypeBinding getTypeBinding(Scope scope) {
+protected TypeBinding getTypeBinding(Scope scope) {
+    if (this.fieldTypeCompletionNode != null) {
+		throw new CompletionNodeFound(this.fieldTypeCompletionNode, scope);
+    }
 	if(isCompletionNode) {
 		throw new CompletionNodeFound(this, scope);
 	} else {
@@ -53,6 +58,9 @@
 	return output.append("<CompleteOnType:").append(token).append('>'); //$NON-NLS-1$
 }
 public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
+    if (this.fieldTypeCompletionNode != null) {
+		throw new CompletionNodeFound(this.fieldTypeCompletionNode, scope);
+    }
 	if(isCompletionNode) {
 		throw new CompletionNodeFound(this, enclosingType, scope);
 	} else {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
index f57041b..b3d2efa 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
@@ -62,6 +62,10 @@
 	protected static final int K_BETWEEN_CASE_AND_COLON = COMPLETION_PARSER + 26;
 	protected static final int K_BETWEEN_DEFAULT_AND_COLON = COMPLETION_PARSER + 27;
 	protected static final int K_BETWEEN_LEFT_AND_RIGHT_BRACKET = COMPLETION_PARSER + 28;
+	protected static final int K_EXTENDS_KEYWORD = COMPLETION_PARSER + 29;
+	protected static final int K_PARAMETERIZED_METHOD_INVOCATION = COMPLETION_PARSER + 30;
+	protected static final int K_PARAMETERIZED_ALLOCATION = COMPLETION_PARSER + 31;
+	protected static final int K_PARAMETERIZED_CAST = COMPLETION_PARSER + 32;
 	
 
 	/* public fields */
@@ -141,7 +145,23 @@
 			if (recoveredType.foundOpeningBrace) {
 				/* generate a pseudo field with a completion on type reference */	
 				if (orphan instanceof TypeReference){
-					CompletionOnFieldType fieldDeclaration = new CompletionOnFieldType((TypeReference)orphan, false);
+					TypeReference fieldType;
+					
+					int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
+					int info = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
+					if(kind == K_BINARY_OPERATOR && info == LESS && this.identifierPtr > -1) {
+						if(this.genericsLengthStack[this.genericsLengthPtr] > 0) {
+							this.consumeTypeArguments();
+						}
+						this.pushOnGenericsStack(orphan);
+						this.consumeTypeArguments();
+						fieldType = getTypeReference(0);
+						this.assistNodeParent = fieldType;
+					} else {
+						fieldType = (TypeReference)orphan;
+					}
+					
+					CompletionOnFieldType fieldDeclaration = new CompletionOnFieldType(fieldType, false);
 
 					// retrieve available modifiers if any
 					if (intPtr >= 2 && intStack[intPtr-1] == this.lastModifiersStart && intStack[intPtr-2] == this.lastModifiers){
@@ -168,6 +188,14 @@
 			}
 		}
 
+		if(orphan instanceof Annotation) {
+				TypeDeclaration fakeType =
+					new CompletionOnAnnotationOfType(
+							this.compilationUnit.compilationResult(),
+							(Annotation)orphan);
+				currentElement.add(fakeType, 0);
+				return;
+		}
 		// add the completion node to the method declaration or constructor declaration
 		if (orphan instanceof Statement) {
 			/* check for completion at the beginning of method body
@@ -186,12 +214,89 @@
 			return;
 		} 
 	}
+	if(this.currentElement instanceof RecoveredType || this.currentElement instanceof RecoveredMethod) {
+		if(this.currentElement instanceof RecoveredType) {
+			RecoveredType recoveredType = (RecoveredType)this.currentElement;
+			if(recoveredType.foundOpeningBrace && this.genericsPtr > -1) {
+				if(this.genericsStack[this.genericsPtr] instanceof TypeParameter) {
+					TypeParameter typeParameter = (TypeParameter) this.genericsStack[this.genericsPtr];
+					CompletionNodeDetector detector =  new CompletionNodeDetector(this.assistNode, typeParameter);
+					if(detector.containsCompletionNode()) {
+						this.currentElement.add(new CompletionOnMethodTypeParameter(new TypeParameter[]{typeParameter},this.compilationUnit.compilationResult()), 0);
+					}
+					return;
+				}
+			}
+		}
+		
+		if ((!isInsideMethod() && !isInsideFieldInitialization())) { 
+			if(this.genericsPtr > -1 && this.genericsLengthPtr > -1 && this.genericsIdentifiersLengthPtr > -1) {
+				int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
+				int info = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
+				if(kind == K_BINARY_OPERATOR && info == LESS) {
+					this.consumeTypeArguments();
+				}
+				int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr];
+				int genPtr = this.genericsPtr;
+				done : for(int i = 0; i <= this.identifierLengthPtr && numberOfIdentifiers > 0; i++){
+					int identifierLength = this.identifierLengthStack[this.identifierLengthPtr - i];
+					int length = this.genericsLengthStack[this.genericsLengthPtr - i];
+					for(int j = 0; j < length; j++) {
+						ASTNode node = this.genericsStack[genPtr - j];
+						CompletionNodeDetector detector = new CompletionNodeDetector(this.assistNode, node);
+						if(detector.containsCompletionNode()) {
+							if(node == this.assistNode){
+								if(this.identifierLengthPtr > -1 &&	this.identifierLengthStack[this.identifierLengthPtr]!= 0) {
+									TypeReference ref = this.getTypeReference(0);
+									this.assistNodeParent = ref;
+								}
+							} else {
+								this.assistNodeParent = detector.getCompletionNodeParent();
+							}
+							break done;
+						}
+					}
+					genPtr -= length;
+					numberOfIdentifiers -= identifierLength;
+				}
+				if(this.assistNodeParent != null && this.assistNodeParent instanceof TypeReference) {
+					if(this.currentElement instanceof RecoveredType) {
+						this.currentElement = this.currentElement.add(new CompletionOnFieldType((TypeReference)this.assistNodeParent, false), 0);
+					} else {
+						this.currentElement = this.currentElement.add((TypeReference)this.assistNodeParent, 0);
+					}
+				}
+			}
+		}
+	}
 	
 	// the following code applies only in methods, constructors or initializers
 	if ((!isInsideMethod() && !isInsideFieldInitialization())) { 
 		return;
 	}
 	
+	if(this.genericsPtr > -1) {
+		ASTNode node = this.genericsStack[this.genericsPtr];
+		CompletionNodeDetector detector = new CompletionNodeDetector(this.assistNode, node);
+		if(detector.containsCompletionNode()) {
+			/* check for completion at the beginning of method body
+				behind an invalid signature
+			 */
+			RecoveredMethod method = this.currentElement.enclosingMethod();
+			if (method != null){
+				AbstractMethodDeclaration methodDecl = method.methodDeclaration;
+				if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
+					&& (this.scanner.getLineNumber(node.sourceStart) == this.scanner.getLineNumber(methodDecl.sourceEnd))){
+					return;
+				}
+			}
+			if(node == this.assistNode ||
+					((Wildcard)node).bound == this.assistNode){
+				buildMoreGenericsCompletionContext(node);
+			}
+		}
+	}
+	
 	// push top expression on ast stack if it contains the completion node
 	Expression expression;
 	if (this.expressionPtr > -1) {
@@ -303,12 +408,17 @@
 						if(invocType == ALLOCATION) {
 							AllocationExpression allocationExpr = new AllocationExpression();
 							allocationExpr.arguments = arguments;
+							pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
+							pushOnGenericsLengthStack(0);
 							allocationExpr.type = getTypeReference(0);
 							assistNodeParent = allocationExpr;
 						} else {
 							QualifiedAllocationExpression allocationExpr = new QualifiedAllocationExpression();
 							allocationExpr.enclosingInstance = this.expressionStack[qualifierExprPtr];
 							allocationExpr.arguments = arguments;
+							pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
+							pushOnGenericsLengthStack(0);
+							
 							allocationExpr.type = getTypeReference(0);
 							assistNodeParent = allocationExpr;
 						}
@@ -393,6 +503,8 @@
 				
 				if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, 1) == K_ARRAY_CREATION) {
 					ArrayAllocationExpression allocationExpression = new ArrayAllocationExpression();
+					pushOnGenericsLengthStack(0);
+					pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
 					allocationExpression.type = getTypeReference(0);
 					int length = expressionLengthStack[expressionLengthPtr];
 					allocationExpression.dimensions = new Expression[length];
@@ -505,7 +617,39 @@
 		}
 	}
 }
-
+private void buildMoreGenericsCompletionContext(ASTNode node) {
+	int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
+	if(kind != 0) {
+		int info = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
+		nextElement : switch (kind) {
+			case K_BINARY_OPERATOR :
+				int prevKind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, 1);
+				switch (prevKind) {
+					case K_PARAMETERIZED_ALLOCATION :
+						if(this.invocationType == ALLOCATION || this.invocationType == QUALIFIED_ALLOCATION) {
+							currentElement = currentElement.add((TypeReference)node, 0);
+						}
+						break nextElement;
+					case K_PARAMETERIZED_METHOD_INVOCATION :
+						currentElement = currentElement.add((TypeReference)node, 0);
+						break nextElement;
+				}
+				if(info == LESS && node instanceof TypeReference) {
+					if(this.identifierLengthPtr > -1 && this.identifierLengthStack[this.identifierLengthPtr]!= 0) {
+						this.consumeTypeArguments();
+						TypeReference ref = this.getTypeReference(0);
+						if(prevKind == K_PARAMETERIZED_CAST) {
+							ref = computeQualifiedGenericsFromRightSide(ref, 0);
+						}
+						currentElement = currentElement.add(ref, 0);
+					} else if (currentElement.enclosingMethod().methodDeclaration.isConstructor()) {
+						currentElement = currentElement.add((TypeReference)node, 0);
+					}
+				}
+				break;
+		}
+	}
+}
 public int bodyEnd(AbstractMethodDeclaration method){
 	return cursorLocation;
 }
@@ -535,22 +679,27 @@
  */
 private boolean checkClassInstanceCreation() {
 	if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_NEW_AND_LEFT_BRACKET) {
+		int length = identifierLengthStack[identifierLengthPtr];
+		int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr];
+		if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
+			// no class instance creation with a parameterized type
+			return true;
+		}
+		
 		// completion on type inside an allocation expression
 		
 		TypeReference type;
-		if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, 1) == K_INSIDE_THROW_STATEMENT
-			&& topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 1) == this.bracketDepth) {
-			pushOnElementStack(K_NEXT_TYPEREF_IS_EXCEPTION);
-			type = getTypeReference(0);
-			popElement(K_NEXT_TYPEREF_IS_EXCEPTION);
-		} else {
-			type = getTypeReference(0);
-		}
-		this.assistNode = type;
-		this.lastCheckPoint = type.sourceEnd + 1;
 		if (this.invocationType == ALLOCATION) {
 			// non qualified allocation expression
 			AllocationExpression allocExpr = new AllocationExpression();
+			if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, 1) == K_INSIDE_THROW_STATEMENT
+				&& topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 1) == this.bracketDepth) {
+				pushOnElementStack(K_NEXT_TYPEREF_IS_EXCEPTION);
+				type = getTypeReference(0);
+				popElement(K_NEXT_TYPEREF_IS_EXCEPTION);
+			} else {
+				type = getTypeReference(0);
+			}
 			allocExpr.type = type;
 			allocExpr.sourceStart = type.sourceStart;
 			allocExpr.sourceEnd = type.sourceEnd;
@@ -559,6 +708,16 @@
 		} else {
 			// qualified allocation expression
 			QualifiedAllocationExpression allocExpr = new QualifiedAllocationExpression();
+			pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
+			pushOnGenericsLengthStack(0);
+			if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, 1) == K_INSIDE_THROW_STATEMENT
+				&& topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 1) == this.bracketDepth) {
+				pushOnElementStack(K_NEXT_TYPEREF_IS_EXCEPTION);
+				type = getTypeReference(0);
+				popElement(K_NEXT_TYPEREF_IS_EXCEPTION);
+			} else {
+				type = getTypeReference(0);
+			}
 			allocExpr.type = type;
 			allocExpr.enclosingInstance = this.expressionStack[this.qualifier];
 			allocExpr.sourceStart = this.intStack[this.intPtr--];
@@ -566,6 +725,9 @@
 			this.expressionStack[this.qualifier] = allocExpr; // attach it now (it replaces the qualifier expression)
 			this.isOrphanCompletionNode = false;
 		}
+		this.assistNode = type;
+		this.lastCheckPoint = type.sourceEnd + 1;
+		
 		popElement(K_BETWEEN_NEW_AND_LEFT_BRACKET);
 		return true;
 	}
@@ -616,6 +778,9 @@
 			this.identifierLengthPtr--; // it can only be a simple identifier (so its length is one)
 			
 			// get the type reference
+			pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
+			pushOnGenericsLengthStack(0);
+
 			TypeReference typeRef = getTypeReference(this.intStack[this.intPtr--]);
 			
 			// build the completion on class literal access node
@@ -832,6 +997,8 @@
 				// creates an allocation expression 
 				CompletionOnQualifiedAllocationExpression allocExpr = new CompletionOnQualifiedAllocationExpression();
 				allocExpr.arguments = arguments;
+				pushOnGenericsLengthStack(0);
+				pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
 				allocExpr.type = super.getTypeReference(0); // we don't want a completion node here, so call super
 				if (invocType == QUALIFIED_ALLOCATION) {
 					allocExpr.enclosingInstance = this.expressionStack[qualifierExprPtr];
@@ -882,6 +1049,33 @@
 	this.isOrphanCompletionNode = true;
 	return true;
 }
+private boolean checkParemeterizedType() {
+	if(this.identifierLengthPtr > -1 && this.genericsLengthPtr > -1 && this.genericsIdentifiersLengthPtr > -1) {
+		int length = this.identifierLengthStack[this.identifierLengthPtr];
+		int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr];
+		if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
+			this.genericsIdentifiersLengthPtr--;
+			this.identifierLengthPtr--;
+			// generic type
+			this.assistNode = getAssistTypeReferenceForGenericType(0, length, numberOfIdentifiers);
+			this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+			this.isOrphanCompletionNode = true;
+			return true;
+		} else if(this.genericsPtr > -1 && this.genericsStack[this.genericsPtr] instanceof TypeReference) {
+			// type of a cast expression
+			numberOfIdentifiers++;
+			
+			this.genericsIdentifiersLengthPtr--;
+			this.identifierLengthPtr--;
+			// generic type
+			this.assistNode = getAssistTypeReferenceForGenericType(0, length, numberOfIdentifiers);
+			this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+			this.isOrphanCompletionNode = true;
+			return true;
+		}
+	}
+	return false;
+}
 /**
  * Checks if the completion is in the context of a method and on the type of one of its arguments
  * Returns whether we found a completion node.
@@ -931,10 +1125,26 @@
 		RecoveredType recoveredType = (RecoveredType)currentElement;
 		/* filter out cases where scanner is still inside type header */
 		if (recoveredType.foundOpeningBrace) {
+			// complete generics stack if necessary
+			if(this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr] <= this.identifierPtr) {
+				pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+				pushOnGenericsLengthStack(0); // handle type arguments
+			}
 			this.assistNode = this.getTypeReference(0);
 			this.lastCheckPoint = this.assistNode.sourceEnd + 1;
 			this.isOrphanCompletionNode = true;
 			return true;
+		} else {
+			if(recoveredType.typeDeclaration.superclass == null &&
+					this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_EXTENDS_KEYWORD) {
+				this.consumeClassOrInterfaceName();
+				this.pushOnElementStack(K_NEXT_TYPEREF_IS_CLASS);
+				this.assistNode = this.getTypeReference(0);
+				this.popElement(K_NEXT_TYPEREF_IS_CLASS);
+				this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+				this.isOrphanCompletionNode = true;
+				return true;
+			}
 		}
 	}
 	return false;
@@ -993,6 +1203,7 @@
 	// (NB: Put this check before checkNameCompletion() because the selector of the invocation can be on the identifier stack)
 	if (checkInvocation()) return;
 
+	if (checkParemeterizedType()) return;
 	if (checkNameCompletion()) return;
 }
 protected void consumeArrayCreationExpressionWithInitializer() {
@@ -1025,13 +1236,24 @@
 		}
 	}
 }
+protected void consumeBinaryExpressionWithName(int op) {
+	super.consumeBinaryExpressionWithName(op);
+	popElement(K_BINARY_OPERATOR);
+	
+	if(expressionStack[expressionPtr] instanceof BinaryExpression) {
+		BinaryExpression exp = (BinaryExpression) expressionStack[expressionPtr];
+		if(assistNode != null && exp.right == assistNode) {
+			assistNodeParent = exp;
+		}
+	}
+}
 protected void consumeCaseLabel() {
 	super.consumeCaseLabel();
 	if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) != K_SWITCH_LABEL) {
 		pushOnElementStack(K_SWITCH_LABEL);
 	}
 }
-protected void consumeCastExpression() {
+protected void consumeCastExpressionWithPrimitiveType() {
 	popElement(K_CAST_STATEMENT);
 	
 	Expression exp, cast, castType;
@@ -1041,6 +1263,39 @@
 	cast.sourceStart = castType.sourceStart - 1;
 	cast.sourceEnd = exp.sourceEnd;
 }
+protected void consumeCastExpressionWithGenericsArray() {
+	popElement(K_CAST_STATEMENT);
+	
+	Expression exp, cast, castType;
+	expressionPtr--;
+	expressionLengthPtr--;
+	this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr + 1], castType = this.expressionStack[this.expressionPtr]);
+	cast.sourceStart = castType.sourceStart - 1;
+	cast.sourceEnd = exp.sourceEnd;
+}
+
+protected void consumeCastExpressionWithQualifiedGenericsArray() {
+	popElement(K_CAST_STATEMENT);
+	
+	Expression exp, cast, castType;
+	expressionPtr--;
+	expressionLengthPtr--;
+	this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr + 1], castType = this.expressionStack[this.expressionPtr]);
+	cast.sourceStart = castType.sourceStart - 1;
+	cast.sourceEnd = exp.sourceEnd;
+}
+protected void consumeCastExpressionWithNameArray() {
+	// CastExpression ::= PushLPAREN Name Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus
+	popElement(K_CAST_STATEMENT);
+
+	Expression exp, cast, castType;
+		
+	expressionPtr--;
+	expressionLengthPtr--;
+	expressionStack[expressionPtr] = cast = new CastExpression(exp = expressionStack[expressionPtr+1], castType = this.expressionStack[this.expressionPtr]);
+	cast.sourceStart = castType.sourceStart - 1;
+	cast.sourceEnd = exp.sourceEnd;
+}
 protected void consumeCastExpressionLL1() {
 	popElement(K_CAST_STATEMENT);
 	super.consumeCastExpressionLL1();
@@ -1054,8 +1309,8 @@
 	popElement(K_SELECTOR_INVOCATION_TYPE);
 	super.consumeClassBodyopt();
 }
-protected void consumeClassHeaderName() {
-	super.consumeClassHeaderName();
+protected void consumeClassHeaderName1() {
+	super.consumeClassHeaderName1();
 
 	if (currentElement != null
 		&& currentToken == TokenNameIdentifier
@@ -1088,6 +1343,7 @@
 						identifierStack[ptr],
 						identifierPositionStack[ptr],
 						keywords);
+					type.superclass.bits |= ASTNode.IsSuperType;
 					this.assistNode = type.superclass;
 					this.lastCheckPoint = type.superclass.sourceEnd + 1;
 				}
@@ -1099,6 +1355,7 @@
 	pushOnElementStack(K_NEXT_TYPEREF_IS_CLASS);
 	super.consumeClassHeaderExtends();
 	popElement(K_NEXT_TYPEREF_IS_CLASS);
+	popElement(K_EXTENDS_KEYWORD);
 	
 	if (currentElement != null
 		&& currentToken == TokenNameIdentifier
@@ -1119,6 +1376,7 @@
 						identifierStack[ptr],
 						identifierPositionStack[ptr],
 						Keywords.IMPLEMENTS);
+					type.superclass.bits |= ASTNode.IsSuperType;
 					this.assistNode = type.superclass;
 					this.lastCheckPoint = type.superclass.sourceEnd + 1;
 				}
@@ -1135,6 +1393,10 @@
 	popElement(K_CONDITIONAL_OPERATOR);
 	super.consumeConditionalExpression(op);
 }
+protected void consumeConditionalExpressionWithName(int op) {
+	popElement(K_CONDITIONAL_OPERATOR);
+	super.consumeConditionalExpressionWithName(op);
+}
 protected void consumeConstructorBody() {
 	popElement(K_BLOCK_DELIMITER);
 	super.consumeConstructorBody();
@@ -1155,6 +1417,8 @@
 	if (currentElement == null){
 		this.hasReportedError = true; // do not report any error
 	}
+	pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+	pushOnGenericsLengthStack(0); // handle type arguments
 	this.restartRecovery = true;
 }
 protected void consumeDefaultLabel() {
@@ -1173,6 +1437,11 @@
 	popElement(K_SELECTOR_INVOCATION_TYPE);
 	super.consumeEnterAnonymousClassBody();
 }
+protected void consumeEnterAnonymousClassBodySimpleName() {
+	popElement(K_SELECTOR_QUALIFIER);
+	popElement(K_SELECTOR_INVOCATION_TYPE);
+	super.consumeEnterAnonymousClassBodySimpleName();
+}
 protected void consumeEnterVariable() {
 	identifierPtr--;
 	identifierLengthPtr--;
@@ -1219,7 +1488,8 @@
 			if(!checkKeyword() && !(currentElement instanceof RecoveredUnit && ((RecoveredUnit)currentElement).typeCount == 0)) {
 				int nameSourceStart = (int)(identifierPositionStack[identifierPtr] >>> 32);
 				intPtr--;
-				
+//				pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
+//				pushOnGenericsLengthStack(0);
 				TypeReference type = getTypeReference(intStack[intPtr--]);
 				intPtr--;
 				
@@ -1251,6 +1521,15 @@
 		assistNodeParent = exp;
 	}
 }
+protected void consumeEqualityExpressionWithName(int op) {
+	super.consumeEqualityExpressionWithName(op);
+	popElement(K_BINARY_OPERATOR);
+	
+	BinaryExpression exp = (BinaryExpression) expressionStack[expressionPtr];
+	if(assistNode != null && exp.right == assistNode) {
+		assistNodeParent = exp;
+	}
+}
 protected void consumeExitVariableWithInitialization() {
 	super.consumeExitVariableWithInitialization();
 	
@@ -1293,15 +1572,29 @@
 		pushOnElementStack(K_LOCAL_INITIALIZER_DELIMITER);
 	}
 }
-protected void consumeFormalParameter() {
+protected void consumeFormalParameter(boolean isVarArgs) {
 	if (this.indexOfAssistIdentifier() < 0) {
-		super.consumeFormalParameter();
+		super.consumeFormalParameter(isVarArgs);
 	} else {
 
 		identifierLengthPtr--;
 		char[] identifierName = identifierStack[identifierPtr];
 		long namePositions = identifierPositionStack[identifierPtr--];
-		TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
+		int extendedDimensions = this.intStack[this.intPtr--];
+		int endOfEllipsis = 0;
+		if (isVarArgs) {
+			endOfEllipsis = this.intStack[this.intPtr--];
+		}
+		int firstDimensions = this.intStack[this.intPtr--];
+		final int typeDimensions = firstDimensions + extendedDimensions;
+		TypeReference type = getTypeReference(typeDimensions);
+		if (isVarArgs) {
+			type = type.copyDims(typeDimensions + 1);
+			if (extendedDimensions == 0) {
+				type.sourceEnd = endOfEllipsis;
+			}
+			type.bits |= ASTNode.IsVarArgs; // set isVarArgs
+		}
 		intPtr -= 2;
 		CompletionOnArgumentName arg = 
 			new CompletionOnArgumentName(
@@ -1309,6 +1602,16 @@
 				namePositions, 
 				type, 
 				intStack[intPtr + 1] & ~AccDeprecated); // modifiers
+		// consume annotations
+		int length;
+		if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+			System.arraycopy(
+				this.expressionStack, 
+				(this.expressionPtr -= length) + 1, 
+				arg.annotations = new Annotation[length], 
+				0, 
+				length); 
+		}
 				
 		arg.isCatchArgument = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_CATCH_AND_RIGHT_PAREN;
 		pushOnAstStack(arg);
@@ -1324,6 +1627,12 @@
 }
 protected void consumeInsideCastExpression() {
 	int end = intStack[intPtr--];
+	if(this.identifierLengthStack[this.identifierLengthPtr] > 0) {
+		pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+		if(this.genericsLengthPtr < 0) {
+			pushOnGenericsLengthStack(0);
+		}
+	}
 	Expression castType = getTypeReference(intStack[intPtr--]);
 	castType.sourceEnd = end - 1;
 	castType.sourceStart = intStack[intPtr--] + 1;
@@ -1335,6 +1644,20 @@
 	super.consumeInsideCastExpressionLL1();
 	pushOnElementStack(K_CAST_STATEMENT);
 }
+protected void consumeInsideCastExpressionWithQualifiedGenerics() {
+	Expression castType;
+	int end = this.intStack[this.intPtr--];
+
+	int dim = this.intStack[this.intPtr--];
+	TypeReference rightSide = getTypeReference(0);
+
+	castType = computeQualifiedGenericsFromRightSide(rightSide, dim);
+	castType.sourceEnd = end - 1;
+	castType.sourceStart = this.intStack[this.intPtr--] + 1;
+	pushOnExpressionStack(castType);
+	
+	pushOnElementStack(K_CAST_STATEMENT);
+}
 protected void consumeInstanceOfExpression(int op) {
 	super.consumeInstanceOfExpression(op);
 	popElement(K_BINARY_OPERATOR);
@@ -1344,8 +1667,17 @@
 		assistNodeParent = exp;
 	}
 }
-protected void consumeInterfaceHeaderName() {
-	super.consumeInterfaceHeaderName();
+protected void consumeInstanceOfExpressionWithName(int op) {
+	super.consumeInstanceOfExpressionWithName(op);
+	popElement(K_BINARY_OPERATOR);
+	
+	InstanceOfExpression exp = (InstanceOfExpression) expressionStack[expressionPtr];
+	if(assistNode != null && exp.type == assistNode) {
+		assistNodeParent = exp;
+	}
+}
+protected void consumeInterfaceHeaderName1() {
+	super.consumeInterfaceHeaderName1();
 	
 	if (currentElement != null
 		&& currentToken == TokenNameIdentifier
@@ -1367,6 +1699,7 @@
 						identifierPositionStack[ptr],
 						Keywords.EXTENDS);
 					type.superInterfaces = new TypeReference[]{completionOnKeyword};
+					type.superInterfaces[0].bits |= ASTNode.IsSuperType;
 					this.assistNode = completionOnKeyword;
 					this.lastCheckPoint = completionOnKeyword.sourceEnd + 1;
 				}
@@ -1374,6 +1707,10 @@
 		}
 	}
 }
+protected void consumeInterfaceHeaderExtends() {
+	super.consumeInterfaceHeaderExtends();
+	popElement(K_EXTENDS_KEYWORD);
+}
 protected void consumeInterfaceType() {
 	pushOnElementStack(K_NEXT_TYPEREF_IS_INTERFACE);
 	super.consumeInterfaceType();
@@ -1394,14 +1731,15 @@
 	popElement(K_SELECTOR_INVOCATION_TYPE);
 	super.consumeMethodInvocationSuper();
 }
-protected void consumeMethodHeaderName() {
+protected void consumeMethodHeaderName(boolean isAnnotationMethod) {
 	if(this.indexOfAssistIdentifier() < 0) {
 		identifierPtr--;
 		identifierLengthPtr--;
-		if(this.indexOfAssistIdentifier() != 0) {
+		if(this.indexOfAssistIdentifier() != 0 ||
+			this.identifierLengthStack[this.identifierLengthPtr] != this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr]) {
 			identifierPtr++;
 			identifierLengthPtr++;
-			super.consumeMethodHeaderName();
+			super.consumeMethodHeaderName(isAnnotationMethod);
 		} else {
 			restartRecovery = true;
 			
@@ -1420,6 +1758,16 @@
 				
 				if(scanner.getLineNumber(type.sourceStart) != scanner.getLineNumber((int) (selectorSource >>> 32))) {
 					FieldDeclaration completionFieldDecl = new CompletionOnFieldType(type, false);
+					// consume annotations
+					int length;
+					if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+						System.arraycopy(
+							this.expressionStack, 
+							(this.expressionPtr -= length) + 1, 
+							completionFieldDecl.annotations = new Annotation[length], 
+							0, 
+							length); 
+					}
 					completionFieldDecl.modifiers = mod;
 					assistNode = completionFieldDecl;
 					lastCheckPoint = type.sourceEnd + 1;
@@ -1427,6 +1775,16 @@
 					lastIgnoredToken = -1;
 				} else {
 					CompletionOnMethodReturnType md = new CompletionOnMethodReturnType(type, this.compilationUnit.compilationResult);
+					// consume annotations
+					int length;
+					if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+						System.arraycopy(
+							this.expressionStack, 
+							(this.expressionPtr -= length) + 1, 
+							md.annotations = new Annotation[length], 
+							0, 
+							length); 
+					}
 					md.selector = selector;
 					md.declarationSourceStart = declarationSourceStart;
 					md.modifiers = mod;
@@ -1455,6 +1813,16 @@
 		//modifiers
 		md.declarationSourceStart = intStack[intPtr--];
 		md.modifiers = intStack[intPtr--];
+		// consume annotations
+		int length;
+		if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+			System.arraycopy(
+				this.expressionStack, 
+				(this.expressionPtr -= length) + 1, 
+				md.annotations = new Annotation[length], 
+				0, 
+				length); 
+		}
 		// javadoc
 		md.javadoc = this.javadoc;
 		this.javadoc = null;
@@ -1485,8 +1853,8 @@
 		}
 	}
 }
-protected void consumeMethodHeaderParameters() {
-	super.consumeMethodHeaderParameters();
+protected void consumeMethodHeaderRightParen() {
+	super.consumeMethodHeaderRightParen();
 	
 	if (currentElement != null
 		&& currentToken == TokenNameIdentifier
@@ -1550,7 +1918,63 @@
 		}
 	}
 }
+protected void consumeAnnotationName() {
+	int index;
+	
+	if ((index = this.indexOfAssistIdentifier()) < 0) {
+		super.consumeAnnotationName();
+		return;
+	} 
+	
+	MarkerAnnotation markerAnnotation = null;
+	int length = this.identifierLengthStack[this.identifierLengthPtr];
+	TypeReference typeReference;
 
+	/* retrieve identifiers subset and whole positions, the assist node positions
+		should include the entire replaced source. */
+	
+	char[][] subset = identifierSubSet(index);
+	identifierLengthPtr--;
+	identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(
+		identifierPositionStack, 
+		identifierPtr + 1, 
+		positions, 
+		0, 
+		length); 
+
+	/* build specific assist on type reference */
+	
+	if (index == 0) {
+		/* assist inside first identifier */
+		typeReference = this.createSingleAssistTypeReference(
+						assistIdentifier(), 
+						positions[0]);
+	} else {
+		/* assist inside subsequent identifier */
+		typeReference =	this.createQualifiedAssistTypeReference(
+						subset,  
+						assistIdentifier(), 
+						positions);
+	}
+
+	markerAnnotation = new CompletionOnMarkerAnnotationName(typeReference, typeReference.sourceStart);
+	int sourceStart = this.intStack[this.intPtr--];
+	if (this.modifiersSourceStart < 0) {
+		this.modifiersSourceStart = sourceStart;
+	} else if (this.modifiersSourceStart > sourceStart) {
+		this.modifiersSourceStart = sourceStart;
+	}
+	markerAnnotation.declarationSourceEnd = markerAnnotation.sourceEnd;
+	pushOnExpressionStack(markerAnnotation);
+	
+	assistNode = markerAnnotation;
+	this.isOrphanCompletionNode = true;
+	this.restartRecovery = true;
+	
+	this.lastCheckPoint = markerAnnotation.sourceEnd + 1;
+}
 protected void consumeMethodBody() {
 	popElement(K_BLOCK_DELIMITER);
 	super.consumeMethodBody();
@@ -1894,6 +2318,14 @@
 				pushOnElementStack(K_BINARY_OPERATOR, UNSIGNED_RIGHT_SHIFT);
 				break;
 			case TokenNameLESS:
+				switch(previous) {
+					case TokenNameDOT :
+						pushOnElementStack(K_PARAMETERIZED_METHOD_INVOCATION);
+						break;
+					case TokenNamenew :
+						pushOnElementStack(K_PARAMETERIZED_ALLOCATION);
+						break;
+				}
 				pushOnElementStack(K_BINARY_OPERATOR, LESS);
 				break;
 			case TokenNameGREATER:
@@ -1942,7 +2374,9 @@
 				pushOnElementStack(K_BINARY_OPERATOR, INSTANCEOF);
 				break;
 			case TokenNameQUESTION:
-				pushOnElementStack(K_CONDITIONAL_OPERATOR, QUESTION);
+				if(previous != TokenNameLESS) {
+					pushOnElementStack(K_CONDITIONAL_OPERATOR, QUESTION);
+				}
 				break;
 			case TokenNameCOLON:
 				if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_CONDITIONAL_OPERATOR
@@ -1981,9 +2415,126 @@
 			case TokenNamedefault :
 				pushOnElementStack(K_BETWEEN_DEFAULT_AND_COLON);
 				break;
+			case TokenNameextends:
+				pushOnElementStack(K_EXTENDS_KEYWORD);
+				break;
+		}
+	} else {
+		switch(token) {
+			case TokenNameextends:
+				pushOnElementStack(K_EXTENDS_KEYWORD);
+				break;
+			case TokenNameLESS:
+				pushOnElementStack(K_BINARY_OPERATOR, LESS);
+				break;
+			case TokenNameGREATER:
+				pushOnElementStack(K_BINARY_OPERATOR, GREATER);
+				break;
+			case TokenNameRIGHT_SHIFT:
+				pushOnElementStack(K_BINARY_OPERATOR, RIGHT_SHIFT);
+				break;
+			case TokenNameUNSIGNED_RIGHT_SHIFT:
+				pushOnElementStack(K_BINARY_OPERATOR, UNSIGNED_RIGHT_SHIFT);
+				break;
+			
 		}
 	}
 }
+protected void consumeOnlyTypeArguments() {
+	super.consumeOnlyTypeArguments();
+	popElement(K_BINARY_OPERATOR);
+	if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_PARAMETERIZED_METHOD_INVOCATION) {
+		popElement(K_PARAMETERIZED_METHOD_INVOCATION);
+	} else {
+		popElement(K_PARAMETERIZED_ALLOCATION);
+	}
+}
+protected void consumeOnlyTypeArgumentsForCastExpression() {
+	super.consumeOnlyTypeArgumentsForCastExpression();
+	pushOnElementStack(K_PARAMETERIZED_CAST);
+}
+protected void consumeRightParen() {
+	super.consumeRightParen();
+	if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_PARAMETERIZED_CAST) {
+		popElement(K_PARAMETERIZED_CAST);
+	}
+}
+protected void consumeReferenceType1() {
+	super.consumeReferenceType1();
+	popElement(K_BINARY_OPERATOR);
+}
+protected void consumeReferenceType2() {
+	super.consumeReferenceType2();
+	popElement(K_BINARY_OPERATOR);
+}
+protected void consumeReferenceType3() {
+	super.consumeReferenceType3();
+	popElement(K_BINARY_OPERATOR);
+}
+protected void consumeTypeArgumentReferenceType1() {
+	super.consumeTypeArgumentReferenceType1();
+	popElement(K_BINARY_OPERATOR);
+}
+protected void consumeTypeArgumentReferenceType2() {
+	super.consumeTypeArgumentReferenceType2();
+	popElement(K_BINARY_OPERATOR);
+}
+protected void consumeTypeArguments() {
+	super.consumeTypeArguments();
+	popElement(K_BINARY_OPERATOR);
+}
+protected void consumeTypeParameters() {
+	super.consumeTypeParameters();
+	popElement(K_BINARY_OPERATOR);
+}
+protected void consumeTypeParameters1() {
+	super.consumeTypeParameter1();
+	popElement(K_BINARY_OPERATOR);
+}
+protected void consumeTypeParameterWithExtends() {
+	super.consumeTypeParameterWithExtends();
+	popElement(K_EXTENDS_KEYWORD);
+}
+protected void consumeTypeParameterWithExtendsAndBounds() {
+	super.consumeTypeParameterWithExtendsAndBounds();
+	popElement(K_EXTENDS_KEYWORD);
+}
+protected void consumeTypeParameter1WithExtends() {
+	super.consumeTypeParameter1WithExtends();
+	popElement(K_EXTENDS_KEYWORD);
+}
+protected void consumeTypeParameter1WithExtendsAndBounds() {
+	super.consumeTypeParameter1WithExtendsAndBounds();
+	popElement(K_EXTENDS_KEYWORD);
+}
+protected void consumeWildcard1() {
+	super.consumeWildcard1();
+	popElement(K_BINARY_OPERATOR);
+}
+protected void consumeWildcard2() {
+	super.consumeWildcard2();
+	popElement(K_BINARY_OPERATOR);
+}
+protected void consumeWildcard3() {
+	super.consumeWildcard3();
+	popElement(K_BINARY_OPERATOR);
+}
+protected void consumeWildcardBoundsExtends() {
+	super.consumeWildcardBoundsExtends();
+	popElement(K_EXTENDS_KEYWORD);
+}
+protected void consumeWildcardBounds1Extends() {
+	super.consumeWildcardBounds1Extends();
+	popElement(K_EXTENDS_KEYWORD);
+}
+protected void consumeWildcardBounds2Extends() {
+	super.consumeWildcardBounds2Extends();
+	popElement(K_EXTENDS_KEYWORD);
+}
+protected void consumeWildcardBounds3Extends() {
+	super.consumeWildcardBounds3Extends();
+	popElement(K_EXTENDS_KEYWORD);
+}
 protected void consumeUnaryExpression(int op) {
 	super.consumeUnaryExpression(op);
 	popElement(K_UNARY_OPERATOR);
@@ -2031,6 +2582,47 @@
 			return new CompletionOnQualifiedTypeReference(previousIdentifiers, assistName, positions); 
 	}
 }
+public TypeReference createParameterizedQualifiedAssistTypeReference(char[][] previousIdentifiers, TypeReference[][] typeArguments, char[] assistName, TypeReference[] assistTypeArguments, long[] positions) {
+	boolean isParameterized = false;
+	for (int i = 0; i < typeArguments.length; i++) {
+		if(typeArguments[i] != null) {
+			isParameterized = true;
+		}
+	}
+	if(!isParameterized) {
+		return this.createQualifiedAssistTypeReference(previousIdentifiers, assistName, positions);
+	} else {
+		switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) {
+			case K_NEXT_TYPEREF_IS_EXCEPTION :
+				return new CompletionOnParameterizedQualifiedTypeReference(
+					previousIdentifiers,
+					typeArguments,
+					assistName,
+					positions,
+					CompletionOnParameterizedQualifiedTypeReference.K_EXCEPTION);
+			case K_NEXT_TYPEREF_IS_CLASS :
+				return new CompletionOnParameterizedQualifiedTypeReference(
+					previousIdentifiers,
+					typeArguments,
+					assistName,
+					positions,
+					CompletionOnParameterizedQualifiedTypeReference.K_CLASS);
+			case K_NEXT_TYPEREF_IS_INTERFACE :
+				return new CompletionOnParameterizedQualifiedTypeReference(
+					previousIdentifiers,
+					typeArguments,
+					assistName,
+					positions,
+					CompletionOnParameterizedQualifiedTypeReference.K_INTERFACE);
+			default :
+				return new CompletionOnParameterizedQualifiedTypeReference(
+					previousIdentifiers,
+					typeArguments,
+					assistName,
+					positions); 
+		}
+	}
+}
 public NameReference createSingleAssistNameReference(char[] assistName, long position) {
 	int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
 	if(!isInsideMethod()) {
@@ -2125,6 +2717,10 @@
 			return new CompletionOnSingleTypeReference(assistName, position); 
 	}
 }
+public TypeReference createParameterizedSingleAssistTypeReference(TypeReference[] typeArguments, char[] assistName, long position) {
+	return this.createSingleAssistTypeReference(assistName, position);
+}
+
 public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLoc) {
 
 	this.cursorLocation = cursorLoc;
@@ -2145,6 +2741,39 @@
 	completionScanner.completedIdentifierStart = 0;
 	completionScanner.completedIdentifierEnd = -1;
 }
+
+protected TypeReference getTypeReferenceForGenericType(int dim,	int identifierLength, int numberOfIdentifiers) {
+	TypeReference ref = super.getTypeReferenceForGenericType(dim, identifierLength, numberOfIdentifiers);
+
+	if(this.assistNode != null) {
+		if (identifierLength == 1 && numberOfIdentifiers == 1) {
+			ParameterizedSingleTypeReference singleRef = (ParameterizedSingleTypeReference) ref;
+			TypeReference[] typeArguments = singleRef.typeArguments;
+			for (int i = 0; i < typeArguments.length; i++) {
+				if(typeArguments[i] == this.assistNode) {
+					this.assistNodeParent = ref;
+					return ref;
+				}
+			}
+		} else {
+			ParameterizedQualifiedTypeReference qualifiedRef = (ParameterizedQualifiedTypeReference) ref;
+			TypeReference[][] typeArguments = qualifiedRef.typeArguments;
+			for (int i = 0; i < typeArguments.length; i++) {
+				if(typeArguments[i] != null) {
+					for (int j = 0; j < typeArguments[i].length; j++) {
+						if(typeArguments[i][j] == this.assistNode) {
+							this.assistNodeParent = ref;
+							return ref;
+						}
+					}
+				}
+			}
+			
+		}
+	}
+	
+	return ref;
+}
 protected NameReference getUnspecifiedReferenceOptimized() {
 	if (this.identifierLengthStack[this.identifierLengthPtr] > 1) { // reducing a qualified name
 		// potential receiver is being poped, so reset potential receiver
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java
index 03c9335..8b32d63 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java
@@ -161,26 +161,63 @@
 		this.diet = false;
 		return this.currentPosition > this.source.length ? TokenNameEOF : TokenNameRBRACE;
 	}
+	int whiteStart = 0;
 	try {
 		while (true) { //loop for jumping over comments
 			this.withoutUnicodePtr = 0;
 			//start with a new token (even comment written with unicode )
 
 			// ---------Consume white space and handles start position---------
-			int whiteStart = this.currentPosition;
-			boolean isWhiteSpace;
+			whiteStart = this.currentPosition;
+			boolean isWhiteSpace, hasWhiteSpaces = false;
+			int offset = 0;
 			do {
 				this.startPosition = this.currentPosition;
-				if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
-					&& (this.source[this.currentPosition] == 'u')) {
+				boolean checkIfUnicode = false;
+				try {
+					checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+						&& (this.source[this.currentPosition] == 'u');
+				} catch(IndexOutOfBoundsException e) {
+					if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
+						// reposition scanner in case we are interested by spaces as tokens
+						this.currentPosition--;
+						this.startPosition = whiteStart;
+						return TokenNameWHITESPACE;
+					}
+					if (this.currentPosition > this.eofPosition) {
+						/* might be completing at eof (e.g. behind a dot) */
+						if (this.completionIdentifier == null && 
+							this.startPosition == this.cursorLocation + 1){
+							// compute end of empty identifier.
+							// if the empty identifier is at the start of a next token the end of
+							// empty identifier is the end of the next token (eg. "<empty token>next").
+						 	while(getNextCharAsJavaIdentifierPart()){/*empty*/}
+						 	this.endOfEmptyToken = this.currentPosition - 1;
+							this.currentPosition = this.startPosition; // for being detected as empty free identifier
+							return TokenNameIdentifier;
+						}	
+						return TokenNameEOF;
+					}
+				}
+				if (checkIfUnicode) {
 					isWhiteSpace = jumpOverUnicodeWhiteSpace();
+					offset = 6;
 				} else {
-					if (this.recordLineSeparator
-						&& ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')))
-						pushLineSeparator();
+					offset = 1;
+					if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
+						//checkNonExternalizedString();
+						if (this.recordLineSeparator) {
+							pushLineSeparator();
+						} else {
+							this.currentLine = null;
+						}
+					}
 					isWhiteSpace = 
 						(this.currentCharacter == ' ') || CharOperation.isWhitespace(this.currentCharacter); 
 				}
+				if (isWhiteSpace) {
+					hasWhiteSpaces = true;
+				}
 				/* completion requesting strictly inside blanks */
 				if ((whiteStart != this.currentPosition)
 					//&& (previousToken == TokenNameDOT)
@@ -192,9 +229,9 @@
 					return TokenNameIdentifier;
 				}
 			} while (isWhiteSpace);
-			if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
+			if (this.tokenizeWhiteSpace && hasWhiteSpaces) {
 				// reposition scanner in case we are interested by spaces as tokens
-				this.currentPosition--;
+				this.currentPosition-=offset;
 				this.startPosition = whiteStart;
 				return TokenNameWHITESPACE;
 			}
@@ -217,6 +254,8 @@
 			// ---------Identify the next token-------------
 
 			switch (this.currentCharacter) {
+				case '@' :
+					return TokenNameAT;
 				case '(' :
 					return TokenNameLPAREN;
 				case ')' :
@@ -237,10 +276,22 @@
 					if (this.startPosition <= this.cursorLocation 
 					    && this.cursorLocation < this.currentPosition){
 					    	return TokenNameDOT; // completion inside .<|>12
-				    }
-					if (getNextCharAsDigit())
+				    }					
+					if (getNextCharAsDigit()) {
 						return scanNumber(true);
-					return TokenNameDOT;
+					}
+					int temp = this.currentPosition;
+					if (getNextChar('.')) {
+						if (getNextChar('.')) {
+							return TokenNameELLIPSIS;
+						} else {
+							this.currentPosition = temp;
+							return TokenNameDOT;
+						}
+					} else {
+						this.currentPosition = temp;
+						return TokenNameDOT;
+					}
 				case '+' :
 					{
 						int test;
@@ -288,6 +339,9 @@
 				case '>' :
 					{
 						int test;
+						if (this.returnOnlyGreater) {
+							return TokenNameGREATER;
+						}
 						if ((test = getNextChar('=', '>')) == 0)
 							return TokenNameGREATER_EQUAL;
 						if (test > 0) {
@@ -371,8 +425,15 @@
 						scanEscapeCharacter();
 					else { // consume next character
 						this.unicodeAsBackSlash = false;
-						if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
-							&& (this.source[this.currentPosition] == 'u')) {
+						boolean checkIfUnicode = false;
+						try {
+							checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+							&& (this.source[this.currentPosition] == 'u');
+						} catch(IndexOutOfBoundsException e) {
+							this.currentPosition--;
+							throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+						}
+						if (checkIfUnicode) {
 							getNextUnicodeChar();
 						} else {
 							if (this.withoutUnicodePtr != 0) {
@@ -398,9 +459,11 @@
 					try {
 						// consume next character
 						this.unicodeAsBackSlash = false;
+						boolean isUnicode = false;
 						if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
 							&& (this.source[this.currentPosition] == 'u')) {
 							getNextUnicodeChar();
+							isUnicode = true;
 						} else {
 							if (this.withoutUnicodePtr != 0) {
 							    this.unicodeStoreAt(++this.withoutUnicodePtr);
@@ -411,15 +474,29 @@
 							/**** \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
-								for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
-									if (this.currentPosition + lookAhead == this.source.length)
-										break;
-									if (this.source[this.currentPosition + lookAhead] == '\n')
-										break;
-									if (this.source[this.currentPosition + lookAhead] == '\"') {
-										this.currentPosition += lookAhead + 1;
-										break;
+								if (isUnicode) {
+									int start = this.currentPosition;
+									for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
+										if (this.currentPosition >= this.eofPosition) {
+											this.currentPosition = start;
+											break;
+										}
+										if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
+											isUnicode = true;
+											getNextUnicodeChar();
+										} else {
+											isUnicode = false;
+										}
+										if (!isUnicode && this.currentCharacter == '\n') {
+											this.currentPosition--; // set current position on new line character
+											break;
+										}
+										if (this.currentCharacter == '\"') {
+											throw new InvalidInputException(INVALID_CHAR_IN_STRING);
+										}
 									}
+								} else {
+									this.currentPosition--; // set current position on new line character
 								}
 								throw new InvalidInputException(INVALID_CHAR_IN_STRING);
 							}
@@ -454,6 +531,7 @@
 
 						}
 					} catch (IndexOutOfBoundsException e) {
+						this.currentPosition--;
 						throw new InvalidInputException(UNTERMINATED_STRING);
 					} catch (InvalidInputException e) {
 						if (e.getMessage().equals(INVALID_ESCAPE)) {
@@ -480,107 +558,7 @@
 					{
 						int test;
 						if ((test = getNextChar('/', '*')) == 0) { //line comment 
-							try {
-								//get the next char 
-								this.lastCommentLinePosition = this.currentPosition;
-								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
-									&& (this.source[this.currentPosition] == 'u')) {
-									//-------------unicode traitement ------------
-									int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
-									this.currentPosition++;
-									while (this.source[this.currentPosition] == 'u') {
-										this.currentPosition++;
-									}
-									if ((c1 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
-										|| c1 < 0
-										|| (c2 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
-										|| c2 < 0
-										|| (c3 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
-										|| c3 < 0
-										|| (c4 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
-										|| c4 < 0) {
-										throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
-									} else {
-										this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
-									}
-								}
-
-								//handle the \\u case manually into comment
-								if (this.currentCharacter == '\\') {
-									if (this.source[this.currentPosition] == '\\')
-										this.currentPosition++;
-								} //jump over the \\
-								while (this.currentCharacter != '\r' && this.currentCharacter != '\n') {
-									//get the next char 
-									this.lastCommentLinePosition = this.currentPosition;
-									if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
-										&& (this.source[this.currentPosition] == 'u')) {
-										//-------------unicode traitement ------------
-										int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
-										this.currentPosition++;
-										while (this.source[this.currentPosition] == 'u') {
-											this.currentPosition++;
-										}
-										if ((c1 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
-											|| c1 < 0
-											|| (c2 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
-											|| c2 < 0
-											|| (c3 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
-											|| c3 < 0
-											|| (c4 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
-											|| c4 < 0) {
-											throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
-										} else {
-											this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
-										}
-									}
-									//handle the \\u case manually into comment
-									if (this.currentCharacter == '\\') {
-										if (this.source[this.currentPosition] == '\\')
-											this.currentPosition++;
-									} //jump over the \\
-								}
-								recordComment(TokenNameCOMMENT_LINE);
-								if (this.startPosition <= this.cursorLocation && this.cursorLocation < this.currentPosition-1){
-									throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_COMMENT);
-								}
-								if (this.recordLineSeparator && ((this.currentCharacter == '\r') || (this.currentCharacter == '\n'))) {
-									pushLineSeparator();
-								}
-								if (this.tokenizeComments) {
-									this.currentPosition--; // reset one character behind
-									return TokenNameCOMMENT_LINE;
-								}
-							} catch (IndexOutOfBoundsException e) {
-								recordComment(TokenNameCOMMENT_LINE);
-								if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition-1);
-								if (this.tokenizeComments) {
-									this.currentPosition--; // reset one character behind
-									return TokenNameCOMMENT_LINE;
-								}
-							}
-							break;
-						}
-						if (test > 0) { //traditional and javadoc comment
-							boolean isJavadoc = false, star = false;
-							// consume next character
-							this.unicodeAsBackSlash = false;
-							if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
-								&& (this.source[this.currentPosition] == 'u')) {
-								getNextUnicodeChar();
-							} else {
-								if (this.withoutUnicodePtr != 0) {
-								    this.unicodeStoreAt(++this.withoutUnicodePtr);
-								}
-							}
-
-							if (this.currentCharacter == '*') {
-								isJavadoc = true;
-								star = true;
-							}
-							if (this.recordLineSeparator
-								&& ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')))
-								pushLineSeparator();
+							this.lastCommentLinePosition = this.currentPosition;
 							try { //get the next char 
 								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
 									&& (this.source[this.currentPosition] == 'u')) {
@@ -603,24 +581,20 @@
 										this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 									}
 								}
+
 								//handle the \\u case manually into comment
 								if (this.currentCharacter == '\\') {
 									if (this.source[this.currentPosition] == '\\')
 										this.currentPosition++;
 								} //jump over the \\
-								// empty comment is not a javadoc /**/
-								if (this.currentCharacter == '/') { 
-									isJavadoc = false;
-								}
-								//loop until end of comment */ 
-								while ((this.currentCharacter != '/') || (!star)) {
-									if (this.recordLineSeparator
-										&& ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')))
-										pushLineSeparator();
-									star = this.currentCharacter == '*';
-									//get next char
+								boolean isUnicode = false;
+								while (this.currentCharacter != '\r' && this.currentCharacter != '\n') {
+									this.lastCommentLinePosition = this.currentPosition;
+									//get the next char 
+									isUnicode = false;
 									if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
 										&& (this.source[this.currentPosition] == 'u')) {
+										isUnicode = true;
 										//-------------unicode traitement ------------
 										int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 										this.currentPosition++;
@@ -646,11 +620,159 @@
 											this.currentPosition++;
 									} //jump over the \\
 								}
+								/*
+								 * We need to completely consume the line break
+								 */
+								if (this.currentCharacter == '\r'
+								   && this.source.length > this.currentPosition) {
+								   	if (this.source[this.currentPosition] == '\n') {
+										this.currentPosition++;
+										this.currentCharacter = '\n';
+								   	} else if ((this.source[this.currentPosition] == '\\')
+										&& (this.source[this.currentPosition + 1] == 'u')) {
+										isUnicode = true;
+										char unicodeChar;
+										int index = this.currentPosition + 1;
+										index++;
+										while (this.source[index] == 'u') {
+											index++;
+										}
+										//-------------unicode traitement ------------
+										int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+										if ((c1 = Character.getNumericValue(this.source[index++])) > 15
+											|| c1 < 0
+											|| (c2 = Character.getNumericValue(this.source[index++])) > 15
+											|| c2 < 0
+											|| (c3 = Character.getNumericValue(this.source[index++])) > 15
+											|| c3 < 0
+											|| (c4 = Character.getNumericValue(this.source[index++])) > 15
+											|| c4 < 0) {
+											this.currentPosition = index;
+											throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+										} else {
+											unicodeChar = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+										}
+										if (unicodeChar == '\n') {
+											this.currentPosition = index;
+											this.currentCharacter = '\n';
+										}
+									}
+							   	}
+								recordComment(TokenNameCOMMENT_LINE);
+								if (this.startPosition <= this.cursorLocation && this.cursorLocation < this.currentPosition-1){
+									throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_COMMENT);
+								}
+								if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
+								if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
+									//checkNonExternalizedString();
+									if (this.recordLineSeparator) {
+										if (isUnicode) {
+											pushUnicodeLineSeparator();
+										} else {
+											pushLineSeparator();
+										}
+									} else {
+										this.currentLine = null;
+									}
+								}
+								if (this.tokenizeComments) {
+									return TokenNameCOMMENT_LINE;
+								}
+							} catch (IndexOutOfBoundsException e) {
+								this.currentPosition--;
+								recordComment(TokenNameCOMMENT_LINE);
+								if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
+								if (this.tokenizeComments) {
+									return TokenNameCOMMENT_LINE;
+								} else {
+									this.currentPosition++;
+								}
+							}
+							break;
+						}
+						if (test > 0) { //traditional and javadoc comment
+							try { //get the next char
+								boolean isJavadoc = false, star = false;
+								boolean isUnicode = false;
+								// consume next character
+								this.unicodeAsBackSlash = false;
+								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+									&& (this.source[this.currentPosition] == 'u')) {
+									getNextUnicodeChar();
+									isUnicode = true;
+								} else {
+									isUnicode = false;
+									if (this.withoutUnicodePtr != 0) {
+									    this.unicodeStoreAt(++this.withoutUnicodePtr);
+									}
+								}
+	
+								if (this.currentCharacter == '*') {
+									isJavadoc = true;
+									star = true;
+								}
+								if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
+									//checkNonExternalizedString();
+									if (this.recordLineSeparator) {
+										if (!isUnicode) {
+											pushLineSeparator();
+										}
+									} else {
+										this.currentLine = null;
+									}
+								}
+								isUnicode = false;
+								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+									&& (this.source[this.currentPosition] == 'u')) {
+									//-------------unicode traitement ------------
+									getNextUnicodeChar();
+									isUnicode = true;
+								} else {
+									isUnicode = false;
+								}
+								//handle the \\u case manually into comment
+								if (this.currentCharacter == '\\') {
+									if (this.source[this.currentPosition] == '\\')
+										this.currentPosition++;
+								} //jump over the \\
+								// empty comment is not a javadoc /**/
+								if (this.currentCharacter == '/') { 
+									isJavadoc = false;
+								}
+								//loop until end of comment */ 
+								while ((this.currentCharacter != '/') || (!star)) {
+									if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
+										//checkNonExternalizedString();
+										if (this.recordLineSeparator) {
+											if (!isUnicode) {
+												pushLineSeparator();
+											}
+										} else {
+											this.currentLine = null;
+										}
+									}
+									star = this.currentCharacter == '*';
+									//get next char
+									if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+										&& (this.source[this.currentPosition] == 'u')) {
+										//-------------unicode traitement ------------
+										getNextUnicodeChar();
+										isUnicode = true;
+									} else {
+										isUnicode = false;
+									}
+									//handle the \\u case manually into comment
+									if (this.currentCharacter == '\\') {
+										if (this.source[this.currentPosition] == '\\')
+											this.currentPosition++;
+									} //jump over the \\
+								}
 								int token = isJavadoc ? TokenNameCOMMENT_JAVADOC : TokenNameCOMMENT_BLOCK;
 								recordComment(token);
 								if (this.startPosition <= this.cursorLocation && this.cursorLocation < this.currentPosition-1){
 									throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_COMMENT);
 								}
+								if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
 								if (this.tokenizeComments) {
 									/*
 									if (isJavadoc)
@@ -660,6 +782,7 @@
 									return token;
 								}
 							} catch (IndexOutOfBoundsException e) {
+								this.currentPosition--;
 								throw new InvalidInputException(UNTERMINATED_COMMENT);
 							}
 							break;
@@ -677,14 +800,20 @@
 				default :
 					if (Character.isJavaIdentifierStart(this.currentCharacter))
 						return scanIdentifierOrKeyword();
-					if (Character.isDigit(this.currentCharacter))
+					if (isDigit(this.currentCharacter)) {
 						return scanNumber(false);
+					}
 					return TokenNameERROR;
 			}
 		}
 	} //-----------------end switch while try--------------------
 	catch (IndexOutOfBoundsException e) {
-		// eof reached
+		if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
+			// reposition scanner in case we are interested by spaces as tokens
+			this.currentPosition--;
+			this.startPosition = whiteStart;
+			return TokenNameWHITESPACE;
+		}
 	}
 	/* might be completing at very end of file (e.g. behind a dot) */
 	if (this.completionIdentifier == null && 
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/InvalidCursorLocation.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/InvalidCursorLocation.java
index c49cc7e..9c88e97 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/InvalidCursorLocation.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/InvalidCursorLocation.java
@@ -23,7 +23,9 @@
 	public static final String NO_COMPLETION_INSIDE_COMMENT = "No Completion Inside Comment";      //$NON-NLS-1$
 	public static final String NO_COMPLETION_INSIDE_STRING = "No Completion Inside String";        //$NON-NLS-1$
 	public static final String NO_COMPLETION_INSIDE_NUMBER = "No Completion Inside Number";        //$NON-NLS-1$
-    
+
+	private static final long serialVersionUID = -3443160725735779590L; // backward compatible
+	
 public InvalidCursorLocation(String irritant){
 	this.irritant = irritant;
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistOptions.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistOptions.java
index 345dfbf..278a383 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistOptions.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistOptions.java
@@ -38,10 +38,13 @@
 		"org.eclipse.jdt.core.codeComplete.localSuffixes"; 	//$NON-NLS-1$
 	public static final String OPTION_ArgumentSuffixes =
 		"org.eclipse.jdt.core.codeComplete.argumentSuffixes"; 	//$NON-NLS-1$
+	public static final String OPTION_PerformRestrictionsCheck =
+		"org.eclipse.jdt.core.codeComplete.restrictionsCheck"; 	//$NON-NLS-1$
 	public static final String ENABLED = "enabled"; //$NON-NLS-1$
 	public static final String DISABLED = "disabled"; //$NON-NLS-1$
 
 	public boolean checkVisibility = false;
+	public boolean checkRestrictions = false;
 	public boolean forceImplicitQualification = false;
 	public char[][] fieldPrefixes = null;
 	public char[][] staticFieldPrefixes = null;
@@ -165,5 +168,12 @@
 				}
 			}
 		}
+		if ((optionValue = optionsMap.get(OPTION_PerformRestrictionsCheck)) != null) {
+			if (ENABLED.equals(optionValue)) {
+				this.checkRestrictions = true;
+			} else if (DISABLED.equals(optionValue)) {
+				this.checkRestrictions = false;
+			}
+		}
 	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java
index 1669801..2de6406 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java
@@ -32,6 +32,7 @@
 import org.eclipse.jdt.internal.compiler.ast.NameReference;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.parser.Parser;
 import org.eclipse.jdt.internal.compiler.parser.RecoveredBlock;
 import org.eclipse.jdt.internal.compiler.parser.RecoveredElement;
@@ -117,7 +118,7 @@
 			for (int i = 0; i < type.fields.length; i++){
 				FieldDeclaration field = type.fields[i];					
 				if (field != null
-						&& !field.isField()
+						&& field.getKind() == AbstractVariableDeclaration.INITIALIZER
 						&& field.declarationSourceStart <= scanner.initialPosition
 						&& scanner.initialPosition <= field.declarationSourceEnd
 						&& scanner.eofPosition <= field.declarationSourceEnd+1){
@@ -140,6 +141,10 @@
 
 	for(int i = 0; i <= astPtr; i++){
 		ASTNode node = astStack[i];
+		
+		if(node instanceof ForeachStatement && ((ForeachStatement)node).action == null) {
+			node = ((ForeachStatement)node).elementVariable;
+		}
 
 		/* check for intermediate block creation, so recovery can properly close them afterwards */
 		int nodeStart = node.sourceStart;
@@ -240,6 +245,10 @@
 	
 	return element;
 }
+protected void consumeAnnotationTypeDeclarationHeader() {
+	super.consumeAnnotationTypeDeclarationHeader();
+	pushOnElementStack(K_TYPE_DELIMITER);
+}
 protected void consumeClassBodyDeclaration() {
 	popElement(K_METHOD_DELIMITER);
 	super.consumeClassBodyDeclaration();
@@ -265,6 +274,15 @@
 	popElement(K_SELECTOR);
 	pushOnElementStack(K_TYPE_DELIMITER);
 }
+protected void consumeEnterAnonymousClassBodySimpleName() {
+	super.consumeEnterAnonymousClassBodySimpleName();
+	popElement(K_SELECTOR);
+	pushOnElementStack(K_TYPE_DELIMITER);
+}
+protected void consumeEnumHeader() {
+	super.consumeEnumHeader();
+	pushOnElementStack(K_TYPE_DELIMITER);
+}
 protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
 	super.consumeExplicitConstructorInvocation(flag, recFlag);
 	popElement(K_SELECTOR);
@@ -297,6 +315,14 @@
 		this.lastCheckPoint = messageSend.sourceEnd + 1;
 	}
 }
+protected void consumeMethodInvocationNameWithTypeArguments() {
+	super.consumeMethodInvocationNameWithTypeArguments();
+	popElement(K_SELECTOR);
+	MessageSend messageSend = (MessageSend)expressionStack[expressionPtr];
+	if (messageSend == assistNode){
+		this.lastCheckPoint = messageSend.sourceEnd + 1;
+	}
+}
 protected void consumeMethodInvocationPrimary() {
 	super.consumeMethodInvocationPrimary();
 	popElement(K_SELECTOR);
@@ -305,6 +331,14 @@
 		this.lastCheckPoint = messageSend.sourceEnd + 1;
 	}
 }
+protected void consumeMethodInvocationPrimaryWithTypeArguments() {
+	super.consumeMethodInvocationPrimaryWithTypeArguments();
+	popElement(K_SELECTOR);
+	MessageSend messageSend = (MessageSend)expressionStack[expressionPtr];
+	if (messageSend == assistNode){
+		this.lastCheckPoint = messageSend.sourceEnd + 1;
+	}
+}
 protected void consumeMethodInvocationSuper() {
 	super.consumeMethodInvocationSuper();
 	popElement(K_SELECTOR);
@@ -313,6 +347,14 @@
 		this.lastCheckPoint = messageSend.sourceEnd + 1;
 	}
 }
+protected void consumeMethodInvocationSuperWithTypeArguments() {
+	super.consumeMethodInvocationSuperWithTypeArguments();
+	popElement(K_SELECTOR);
+	MessageSend messageSend = (MessageSend)expressionStack[expressionPtr];
+	if (messageSend == assistNode){
+		this.lastCheckPoint = messageSend.sourceEnd + 1;
+	}
+}
 protected void consumeNestedMethod() {
 	super.consumeNestedMethod();
 	if(!isInsideMethod()) pushOnElementStack(K_METHOD_DELIMITER);
@@ -378,6 +420,65 @@
 		restartRecovery = true; // used to avoid branching back into the regular automaton		
 	}	
 }
+protected void consumePackageDeclarationNameWithModifiers() {
+	// PackageDeclarationName ::= Modifiers 'package' PushRealModifiers Name
+	/* build an ImportRef build from the last name 
+	stored in the identifier stack. */
+
+	int index;
+
+	/* no need to take action if not inside assist identifiers */
+	if ((index = indexOfAssistIdentifier()) < 0) {
+		super.consumePackageDeclarationNameWithModifiers();
+		return;
+	}
+	/* retrieve identifiers subset and whole positions, the assist node positions
+		should include the entire replaced source. */
+	int length = identifierLengthStack[identifierLengthPtr];
+	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
+	identifierLengthPtr--;
+	identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(
+		identifierPositionStack, 
+		identifierPtr + 1, 
+		positions, 
+		0, 
+		length); 
+
+	this.intPtr--; // we don't need the modifiers start
+	this.intPtr--; // we don't need the package modifiers
+	ImportReference reference = this.createAssistPackageReference(subset, positions);
+	// consume annotations
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			reference.annotations = new Annotation[length], 
+			0, 
+			length); 
+	}	
+	/* build specific assist node on package statement */
+	assistNode = reference;
+	this.lastCheckPoint = reference.sourceEnd + 1;
+	compilationUnit.currentPackage = reference; 
+
+	if (currentToken == TokenNameSEMICOLON){
+		reference.declarationSourceEnd = scanner.currentPosition - 1;
+	} else {
+		reference.declarationSourceEnd = (int) positions[length-1];
+	}
+	//endPosition is just before the ;
+	reference.declarationSourceStart = intStack[intPtr--];
+	// flush comments defined prior to import statements
+	reference.declarationSourceEnd = this.flushCommentsDefinedPriorTo(reference.declarationSourceEnd);
+
+	// recovery
+	if (currentElement != null){
+		lastCheckPoint = reference.declarationSourceEnd+1;
+		restartRecovery = true; // used to avoid branching back into the regular automaton		
+	}	
+}
 protected void consumeRestoreDiet() {
 	super.consumeRestoreDiet();
 	// if we are not in a method (ie. we were not in a local variable initializer)
@@ -386,6 +487,57 @@
 		popElement(K_FIELD_INITIALIZER_DELIMITER);
 	}
 }
+protected void consumeSingleStaticImportDeclarationName() {
+	// SingleTypeImportDeclarationName ::= 'import' 'static' Name
+	/* push an ImportRef build from the last name 
+	stored in the identifier stack. */
+
+	int index;
+
+	/* no need to take action if not inside assist identifiers */
+	if ((index = indexOfAssistIdentifier()) < 0) {
+		super.consumeSingleStaticImportDeclarationName();
+		return;
+	}
+	/* retrieve identifiers subset and whole positions, the assist node positions
+		should include the entire replaced source. */
+	int length = identifierLengthStack[identifierLengthPtr];
+	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
+	identifierLengthPtr--;
+	identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(
+		identifierPositionStack, 
+		identifierPtr + 1, 
+		positions, 
+		0, 
+		length); 
+
+	/* build specific assist node on import statement */
+	ImportReference reference = this.createAssistImportReference(subset, positions, AccStatic);
+	assistNode = reference;
+	this.lastCheckPoint = reference.sourceEnd + 1;
+
+	pushOnAstStack(reference);
+
+	if (currentToken == TokenNameSEMICOLON){
+		reference.declarationSourceEnd = scanner.currentPosition - 1;
+	} else {
+		reference.declarationSourceEnd = (int) positions[length-1];
+	}
+	//endPosition is just before the ;
+	reference.declarationSourceStart = intStack[intPtr--];
+	// flush annotations defined prior to import statements
+	reference.declarationSourceEnd = this.flushCommentsDefinedPriorTo(reference.declarationSourceEnd);
+
+	// recovery
+	if (currentElement != null){
+		lastCheckPoint = reference.declarationSourceEnd+1;
+		currentElement = currentElement.add(reference, 0);
+		lastIgnoredToken = -1;
+		restartRecovery = true; // used to avoid branching back into the regular automaton		
+	}
+}
 protected void consumeSingleTypeImportDeclarationName() {
 	// SingleTypeImportDeclarationName ::= 'import' Name
 	/* push an ImportRef build from the last name 
@@ -437,6 +589,58 @@
 		restartRecovery = true; // used to avoid branching back into the regular automaton		
 	}
 }
+protected void consumeStaticImportOnDemandDeclarationName() {
+	// TypeImportOnDemandDeclarationName ::= 'import' 'static' Name '.' '*'
+	/* push an ImportRef build from the last name 
+	stored in the identifier stack. */
+
+	int index;
+
+	/* no need to take action if not inside assist identifiers */
+	if ((index = indexOfAssistIdentifier()) < 0) {
+		super.consumeStaticImportOnDemandDeclarationName();
+		return;
+	}
+	/* retrieve identifiers subset and whole positions, the assist node positions
+		should include the entire replaced source. */
+	int length = identifierLengthStack[identifierLengthPtr];
+	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
+	identifierLengthPtr--;
+	identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(
+		identifierPositionStack, 
+		identifierPtr + 1, 
+		positions, 
+		0, 
+		length); 
+
+	/* build specific assist node on import statement */
+	ImportReference reference = this.createAssistImportReference(subset, positions, AccStatic);
+	reference.onDemand = true;
+	assistNode = reference;
+	this.lastCheckPoint = reference.sourceEnd + 1;
+
+	pushOnAstStack(reference);
+
+	if (currentToken == TokenNameSEMICOLON){
+		reference.declarationSourceEnd = scanner.currentPosition - 1;
+	} else {
+		reference.declarationSourceEnd = (int) positions[length-1];
+	}
+	//endPosition is just before the ;
+	reference.declarationSourceStart = intStack[intPtr--];
+	// flush annotations defined prior to import statements
+	reference.declarationSourceEnd = this.flushCommentsDefinedPriorTo(reference.declarationSourceEnd);
+
+	// recovery
+	if (currentElement != null){
+		lastCheckPoint = reference.declarationSourceEnd+1;
+		currentElement = currentElement.add(reference, 0);
+		lastIgnoredToken = -1;
+		restartRecovery = true; // used to avoid branching back into the regular automaton		
+	}
+}
 protected void consumeStaticInitializer() {
 	super.consumeStaticInitializer();
 	popElement(K_METHOD_DELIMITER);
@@ -540,8 +744,10 @@
 public abstract ImportReference createAssistPackageReference(char[][] tokens, long[] positions);
 public abstract NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] assistName, long[] positions);
 public abstract TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions);
+public abstract TypeReference createParameterizedQualifiedAssistTypeReference(char[][] previousIdentifiers, TypeReference[][] typeArguments, char[] asistIdentifier, TypeReference[] assistTypeArguments, long[] positions);
 public abstract NameReference createSingleAssistNameReference(char[] assistName, long position);
 public abstract TypeReference createSingleAssistTypeReference(char[] assistName, long position);
+public abstract TypeReference createParameterizedSingleAssistTypeReference(TypeReference[] typeArguments, char[] assistName, long position);
 /*
  * Flush parser/scanner state regarding to code assist
  */
@@ -563,38 +769,142 @@
 	int index;
 
 	/* no need to take action if not inside completed identifiers */
-	if ((index = indexOfAssistIdentifier()) < 0) {
+	if ((index = indexOfAssistIdentifier(true)) < 0) {
 		return super.getTypeReference(dim);
 	}
-
-	/* retrieve identifiers subset and whole positions, the assist node positions
-		should include the entire replaced source. */
 	int length = identifierLengthStack[identifierLengthPtr];
-	char[][] subset = identifierSubSet(index);
-	identifierLengthPtr--;
-	identifierPtr -= length;
-	long[] positions = new long[length];
-	System.arraycopy(
-		identifierPositionStack, 
-		identifierPtr + 1, 
-		positions, 
-		0, 
-		length); 
-
-	/* build specific assist on type reference */
 	TypeReference reference;
-	if (index == 0) {
-		/* assist inside first identifier */
-		reference = this.createSingleAssistTypeReference(
-						assistIdentifier(), 
-						positions[0]);
+	int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr--];
+	if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
+		identifierLengthPtr--;
+		// generic type
+		reference = getAssistTypeReferenceForGenericType(dim, length, numberOfIdentifiers);
 	} else {
-		/* assist inside subsequent identifier */
-		reference =	this.createQualifiedAssistTypeReference(
-						subset,  
-						assistIdentifier(), 
-						positions);
+		/* retrieve identifiers subset and whole positions, the assist node positions
+			should include the entire replaced source. */
+		
+		char[][] subset = identifierSubSet(index);
+		identifierLengthPtr--;
+		identifierPtr -= length;
+		long[] positions = new long[length];
+		System.arraycopy(
+			identifierPositionStack, 
+			identifierPtr + 1, 
+			positions, 
+			0, 
+			length); 
+	
+		/* build specific assist on type reference */
+		
+		if (index == 0) {
+//			genericsIdentifiersLengthPtr--;
+			genericsLengthPtr--;
+			/* assist inside first identifier */
+			reference = this.createSingleAssistTypeReference(
+							assistIdentifier(), 
+							positions[0]);
+		} else {
+//			genericsIdentifiersLengthPtr--;
+			genericsLengthPtr--;
+			/* assist inside subsequent identifier */
+			reference =	this.createQualifiedAssistTypeReference(
+							subset,  
+							assistIdentifier(), 
+							positions);
+		}
+		assistNode = reference;
+		this.lastCheckPoint = reference.sourceEnd + 1;
 	}
+	return reference;
+}
+protected TypeReference getAssistTypeReferenceForGenericType(int dim, int identifierLength, int numberOfIdentifiers) {
+	/* no need to take action if not inside completed identifiers */
+	if (/*(indexOfAssistIdentifier()) < 0 ||*/ (identifierLength == 1 && numberOfIdentifiers == 1)) {
+		int currentTypeArgumentsLength = this.genericsLengthStack[this.genericsLengthPtr--];
+		TypeReference[] typeArguments = new TypeReference[currentTypeArgumentsLength];
+		this.genericsPtr -= currentTypeArgumentsLength;
+		System.arraycopy(this.genericsStack, this.genericsPtr + 1, typeArguments, 0, currentTypeArgumentsLength);
+		long[] positions = new long[identifierLength];
+		System.arraycopy(
+			identifierPositionStack, 
+			identifierPtr, 
+			positions, 
+			0, 
+			identifierLength); 
+		
+		this.identifierPtr--;
+				
+		TypeReference reference = this.createParameterizedSingleAssistTypeReference(
+				typeArguments,
+				assistIdentifier(),
+				positions[0]);
+		
+		this.assistNode = reference;
+		this.lastCheckPoint = reference.sourceEnd + 1;
+		return reference;
+	}
+	
+	TypeReference[][] typeArguments = new TypeReference[numberOfIdentifiers][];
+	char[][] tokens = new char[numberOfIdentifiers][];
+	long[] positions = new long[numberOfIdentifiers];
+	int index = numberOfIdentifiers;
+	int currentIdentifiersLength = identifierLength;
+	while (index > 0) {
+		int currentTypeArgumentsLength = this.genericsLengthStack[this.genericsLengthPtr--];
+		if (currentTypeArgumentsLength != 0) {
+			this.genericsPtr -= currentTypeArgumentsLength;
+			System.arraycopy(this.genericsStack, this.genericsPtr + 1, typeArguments[index - 1] = new TypeReference[currentTypeArgumentsLength], 0, currentTypeArgumentsLength);
+		}
+		switch(currentIdentifiersLength) {
+			case 1 :
+				// we are in a case A<B>.C<D> or A<B>.C<D>
+				tokens[index - 1] = this.identifierStack[this.identifierPtr];
+				positions[index - 1] = this.identifierPositionStack[this.identifierPtr--];
+				break;
+			default:
+				// we are in a case A.B.C<B>.C<D> or A.B.C<B>...
+				this.identifierPtr -= currentIdentifiersLength;
+				System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, index - currentIdentifiersLength, currentIdentifiersLength);
+				System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, index - currentIdentifiersLength, currentIdentifiersLength);
+		}
+		index -= currentIdentifiersLength;
+		if (index > 0) {
+			currentIdentifiersLength = this.identifierLengthStack[this.identifierLengthPtr--];
+		}
+	}
+	
+	// remove completion token
+	int realLength = numberOfIdentifiers;
+	for (int i = 0; i < numberOfIdentifiers; i++) {
+		if(tokens[i] == assistIdentifier()) {
+			realLength = i;
+		}
+	}
+	TypeReference reference;
+	if(realLength == 0) {
+		if(typeArguments[0] != null && typeArguments[0].length > 0) {
+			reference = this.createParameterizedSingleAssistTypeReference(typeArguments[0], assistIdentifier(), positions[0]);
+		} else {
+			reference = this.createSingleAssistTypeReference(assistIdentifier(), positions[0]);
+		}
+	} else {
+		TypeReference[] assistTypeArguments = typeArguments[realLength];
+		System.arraycopy(tokens, 0, tokens = new char[realLength][], 0, realLength);
+		System.arraycopy(typeArguments, 0, typeArguments = new TypeReference[realLength][], 0, realLength);
+		
+		boolean isParameterized = false;
+		for (int i = 0; i < typeArguments.length; i++) {
+			if(typeArguments[i] != null) {
+				isParameterized = true;
+			}
+		}
+		if(isParameterized || (assistTypeArguments != null && assistTypeArguments.length > 0)) {
+			reference = this.createParameterizedQualifiedAssistTypeReference(tokens, typeArguments, assistIdentifier(), assistTypeArguments, positions);
+		} else {
+			reference = this.createQualifiedAssistTypeReference(tokens, assistIdentifier(), positions);
+		}
+	}
+
 	assistNode = reference;
 	this.lastCheckPoint = reference.sourceEnd + 1;
 	return reference;
@@ -638,7 +948,7 @@
 		reference = this.createQualifiedAssistNameReference(subset, assistIdentifier(), positions);
 	}
 	reference.bits &= ~ASTNode.RestrictiveFlagMASK;
-	reference.bits |= LOCAL | FIELD;
+	reference.bits |= Binding.LOCAL | Binding.FIELD;
 	
 	assistNode = reference;
 	lastCheckPoint = reference.sourceEnd + 1;
@@ -678,6 +988,10 @@
 		subsetLength);
 	return subset;
 }
+
+protected int indexOfAssistIdentifier(){
+	return this.indexOfAssistIdentifier(false);
+}
 /*
  * Iterate the most recent group of awaiting identifiers (grouped for qualified name reference (eg. aa.bb.cc)
  * so as to check whether one of them is the assist identifier.
@@ -685,7 +999,7 @@
  *	eg. aa(0).bb(1).cc(2)
  * If no assist identifier was found, answers -1.
  */
-protected int indexOfAssistIdentifier(){
+protected int indexOfAssistIdentifier(boolean useGenericsStack){
 
 	if (identifierLengthPtr < 0){
 		return -1; // no awaiting identifier
@@ -698,6 +1012,9 @@
 
 	// iterate awaiting identifiers backwards
 	int length = identifierLengthStack[identifierLengthPtr];
+	if(useGenericsStack && length > 0 && this.genericsIdentifiersLengthPtr > -1 ) {
+		length = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr];
+	}
 	for (int i = 0; i < length; i++){ 
 		if (identifierStack[identifierPtr - i] == assistIdentifier){
 			return length - i - 1;
@@ -1109,15 +1426,22 @@
 protected boolean resumeAfterRecovery() {
 
 	// reset internal stacks 
-	astPtr = -1;
-	astLengthPtr = -1;
-	expressionPtr = -1;
-	expressionLengthPtr = -1;
-	identifierPtr = -1;	
-	identifierLengthPtr	= -1;
-	intPtr = -1;
-	dimensions = 0 ;
-	recoveredStaticInitializerStart = 0;
+	this.astPtr = -1;
+	this.astLengthPtr = -1;
+	this.expressionPtr = -1;
+	this.expressionLengthPtr = -1;
+	this.identifierPtr = -1;	
+	this.identifierLengthPtr	= -1;
+	this.intPtr = -1;
+	this.dimensions = 0 ;
+	this.recoveredStaticInitializerStart = 0;
+	
+	this.genericsIdentifiersLengthPtr = -1;
+	this.genericsLengthPtr = -1;
+	this.genericsPtr = -1;
+	
+	this.modifiers = AccDefault;
+	this.modifiersSourceStart = -1;
 
 	// if in diet mode, reset the diet counter because we're going to restart outside an initializer.
 	if (diet) dietInt = 0;
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java
index fbafe17..55cf2a7 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java
@@ -13,7 +13,6 @@
 import java.util.Map;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.codeassist.ISearchableNameEnvironment;
 import org.eclipse.jdt.internal.compiler.*;
 import org.eclipse.jdt.internal.compiler.env.*;
 
@@ -21,13 +20,14 @@
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.parser.*;
 import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.core.SearchableEnvironment;
 
 public abstract class Engine implements ITypeRequestor {
 
 	public LookupEnvironment lookupEnvironment;
 	
 	protected CompilationUnitScope unitScope;
-	protected ISearchableNameEnvironment nameEnvironment;
+	protected SearchableEnvironment nameEnvironment;
 
 	public AssistOptions options;
 	public CompilerOptions compilerOptions; 
@@ -40,19 +40,19 @@
 	/**
 	 * Add an additional binary type
 	 */
-	public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
-		lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
+	public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+		lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
 	}
 
 	/**
 	 * Add an additional compilation unit.
 	 */
-	public void accept(ICompilationUnit sourceUnit) {
+	public void accept(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
 		CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
 		CompilationUnitDeclaration parsedUnit =
 			this.getParser().dietParse(sourceUnit, result);
 
-		lookupEnvironment.buildTypeBindings(parsedUnit);
+		lookupEnvironment.buildTypeBindings(parsedUnit, accessRestriction);
 		lookupEnvironment.completeTypeBindings(parsedUnit, true);
 	}
 
@@ -60,7 +60,7 @@
 	 * Add additional source types (the first one is the requested type, the rest is formed by the
 	 * secondary types defined in the same compilation unit).
 	 */
-	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
+	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
 		CompilationResult result =
 			new CompilationResult(sourceTypes[0].getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
 		CompilationUnitDeclaration unit =
@@ -73,7 +73,7 @@
 				result);
 
 		if (unit != null) {
-			lookupEnvironment.buildTypeBindings(unit);
+			lookupEnvironment.buildTypeBindings(unit, accessRestriction);
 			lookupEnvironment.completeTypeBindings(unit, true);
 		}
 	}
@@ -137,8 +137,7 @@
 			TypeDeclaration type = unit.types[i];
 			if (type.declarationSourceStart < position
 				&& type.declarationSourceEnd >= position) {
-				getParser().scanner.setSource(
-					unit.compilationResult.compilationUnit.getContents());
+				getParser().scanner.setSource(unit.compilationResult);
 				return parseBlockStatements(type, unit, position);
 			}
 		}
@@ -170,7 +169,12 @@
 				AbstractMethodDeclaration method = methods[i];
 				if (method.bodyStart > position)
 					continue;
+				
+				if(method.isDefaultConstructor())
+					continue;
+				
 				if (method.declarationSourceEnd >= position) {
+					
 					getParser().parseBlockStatements(method, unit);
 					return method;
 				}
@@ -198,4 +202,32 @@
 	protected void reset() {
 		lookupEnvironment.reset();
 	}
+	
+	public static char[] getSignature(Binding binding) {
+		char[] result = null;
+		if ((binding.kind() & Binding.TYPE) != 0) {
+			TypeBinding typeBinding = (TypeBinding)binding;
+			if(typeBinding.isLocalType()) {
+				LocalTypeBinding localTypeBinding = (LocalTypeBinding)typeBinding;
+				if(localTypeBinding.isAnonymousType()) {
+					typeBinding = localTypeBinding.superclass();
+				} else {
+					localTypeBinding.setConstantPoolName(typeBinding.sourceName());
+				}
+			}
+			result = typeBinding.genericTypeSignature();
+		} else if ((binding.kind() & Binding.METHOD) != 0) {
+			MethodBinding methodBinding = (MethodBinding)binding;
+			int oldMod = methodBinding.modifiers;
+			//TODO remove the next line when method from binary type will be able to generate generic siganute
+			methodBinding.modifiers |= CompilerModifiers.AccGenericSignature;
+			result = methodBinding.genericSignature(); 
+			if(result == null) {
+				result = methodBinding.signature();
+			}
+			methodBinding.modifiers = oldMod;
+		}
+		result = CharOperation.replaceOnCopy(result, '/', '.');
+		return result;
+	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionNodeFound.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionNodeFound.java
index 7feb67e..5b9d33f 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionNodeFound.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionNodeFound.java
@@ -13,10 +13,13 @@
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class SelectionNodeFound extends RuntimeException {
+	
 	public Binding binding;
 	public boolean isDeclaration;
+	private static final long serialVersionUID = -7335444736618092295L; // backward compatible
+	
 public SelectionNodeFound() {
-	this(null); // we found a problem in the selection node
+	this(null, false); // we found a problem in the selection node
 }
 public SelectionNodeFound(Binding binding) {
 	this(binding, false);
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnNameOfMemberValuePair.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnNameOfMemberValuePair.java
new file mode 100644
index 0000000..ec3ecd9
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnNameOfMemberValuePair.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.select;
+
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+
+public class SelectionOnNameOfMemberValuePair extends MemberValuePair {
+	
+	public SelectionOnNameOfMemberValuePair(char[] token, int sourceStart, int sourceEnd, Expression value) {
+		super(token, sourceStart, sourceEnd, value);
+	}
+	
+	public StringBuffer print(int indent, StringBuffer output) {
+		output.append("<SelectOnName:"); //$NON-NLS-1$
+		output.append(name);
+		output.append(">"); //$NON-NLS-1$
+		return output;
+	}
+	
+	public void resolveTypeExpecting(BlockScope scope, TypeBinding requiredType) {
+		super.resolveTypeExpecting(scope, requiredType);
+		
+		if(this.binding != null) {
+			throw new SelectionNodeFound(this.binding);
+		}
+		throw new SelectionNodeFound();
+	}
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedQualifiedTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedQualifiedTypeReference.java
new file mode 100644
index 0000000..05d7095
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedQualifiedTypeReference.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.select;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnParameterizedQualifiedTypeReference extends ParameterizedQualifiedTypeReference {
+	public SelectionOnParameterizedQualifiedTypeReference(char[][] previousIdentifiers, char[] selectionIdentifier, TypeReference[][] typeArguments, TypeReference[] assistTypeArguments, long[] positions) {
+		super(
+			CharOperation.arrayConcat(previousIdentifiers, selectionIdentifier),
+			typeArguments,
+			0,
+			positions);
+		int length =  this.typeArguments.length;
+		System.arraycopy(this.typeArguments, 0, this.typeArguments = new TypeReference[length + 1][], 0, length);
+		this.typeArguments[length] = assistTypeArguments;
+	}
+	
+	public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
+		super.resolveType(scope, checkBounds);
+		if(this.resolvedType != null && this.resolvedType.isRawType()) {
+			ParameterizedTypeBinding parameterizedTypeBinding = scope.createParameterizedType(((RawTypeBinding)this.resolvedType).type, new TypeBinding[0], this.resolvedType.enclosingType());
+			throw new SelectionNodeFound(parameterizedTypeBinding);
+		}
+		throw new SelectionNodeFound(this.resolvedType);
+	}
+	
+	public TypeBinding resolveType(ClassScope scope) {
+		super.resolveType(scope);
+		if(this.resolvedType != null && this.resolvedType.isRawType()) {
+			ParameterizedTypeBinding parameterizedTypeBinding = scope.createParameterizedType(((RawTypeBinding)this.resolvedType).type, new TypeBinding[0], this.resolvedType.enclosingType());
+			throw new SelectionNodeFound(parameterizedTypeBinding);
+		}
+		throw new SelectionNodeFound(this.resolvedType);
+	}
+	
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+		output.append("<SelectOnType:");//$NON-NLS-1$
+		int length = tokens.length;
+		for (int i = 0; i < length; i++) {
+			if(i != 0) {
+				output.append('.');
+			}
+			output.append(tokens[i]);
+			TypeReference[] typeArgument = typeArguments[i];
+			if (typeArgument != null) {
+				output.append('<');//$NON-NLS-1$
+				int max = typeArgument.length - 1;
+				for (int j = 0; j < max; j++) {
+					typeArgument[j].print(0, output);
+					output.append(", ");//$NON-NLS-1$
+				}
+				typeArgument[max].print(0, output);
+				output.append('>');
+			}
+			
+		}
+		output.append('>'); 
+		return output;
+	}
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedSingleTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedSingleTypeReference.java
new file mode 100644
index 0000000..e23ef75
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedSingleTypeReference.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.select;
+
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnParameterizedSingleTypeReference extends ParameterizedSingleTypeReference {
+	public SelectionOnParameterizedSingleTypeReference(char[] name, TypeReference[] typeArguments, long pos){
+		super(name, typeArguments, 0, pos);
+	}
+	
+	public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
+		super.resolveType(scope, checkBounds);
+		throw new SelectionNodeFound(this.resolvedType);
+	}
+	
+	public TypeBinding resolveType(ClassScope scope) {
+		super.resolveType(scope);
+		throw new SelectionNodeFound(this.resolvedType);
+	}
+	
+	public StringBuffer printExpression(int indent, StringBuffer output){
+		output.append("<SelectOnType:");//$NON-NLS-1$
+		output.append(token);
+		output.append('<');
+		int max = typeArguments.length - 1;
+		for (int i= 0; i < max; i++) {
+			typeArguments[i].print(0, output);
+			output.append(", ");//$NON-NLS-1$
+		}
+		typeArguments[max].print(0, output);
+		output.append('>');
+		output.append('>'); 
+		return output;
+	}
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedAllocationExpression.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedAllocationExpression.java
index 022f037..6acaf09 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedAllocationExpression.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedAllocationExpression.java
@@ -45,7 +45,7 @@
 	}
 	
 	public SelectionOnQualifiedAllocationExpression(TypeDeclaration anonymous) {
-		anonymousType = anonymous ;
+		super(anonymous);
 	}
 	
 	public StringBuffer printExpression(int indent, StringBuffer output) {
@@ -73,7 +73,7 @@
 		// super interface (if extending an interface)
 		if (anonymousType.binding.superInterfaces == NoSuperInterfaces) {
 			// find the constructor binding inside the super constructor call
-			ConstructorDeclaration constructor = (ConstructorDeclaration) anonymousType.declarationOf(binding);
+			ConstructorDeclaration constructor = (ConstructorDeclaration) anonymousType.declarationOf(binding.original());
 			throw new SelectionNodeFound(constructor.constructorCall.binding);
 		} else {
 			// open on the only superinterface
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedTypeReference.java
index f2bb372..d1d4137 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedTypeReference.java
@@ -38,7 +38,7 @@
 public void aboutToResolve(Scope scope) {
 	getTypeBinding(scope.parent); // step up from the ClassScope
 }
-public TypeBinding getTypeBinding(Scope scope) {
+protected TypeBinding getTypeBinding(Scope scope) {
 	// it can be a package, type or member type
 	Binding binding = scope.getTypeOrPackage(tokens);
 	if (!binding.isValidBinding()) {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSingleNameReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSingleNameReference.java
index dc26a6f..2b92677 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSingleNameReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSingleNameReference.java
@@ -30,6 +30,7 @@
  */
 
 import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
@@ -43,7 +44,7 @@
 }
 public TypeBinding resolveType(BlockScope scope) {
 	// it can be a package, type, member type, local variable or field
-	binding = scope.getBinding(token, VARIABLE | TYPE | PACKAGE, this, true /*resolve*/);
+	binding = scope.getBinding(token, Binding.VARIABLE | Binding.TYPE | Binding.PACKAGE, this, true /*resolve*/);
 	if (!binding.isValidBinding()) {
 		if (binding instanceof ProblemFieldBinding) {
 			// tolerate some error cases
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSingleTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSingleTypeReference.java
index f566779..236b2cd 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSingleTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSingleTypeReference.java
@@ -21,7 +21,6 @@
  *	---> class X extends <SelectOnType:Object>
  *
  */
- 
 import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
@@ -37,14 +36,13 @@
 public void aboutToResolve(Scope scope) {
 	getTypeBinding(scope.parent); // step up from the ClassScope
 }
-public TypeBinding getTypeBinding(Scope scope) {
+protected TypeBinding getTypeBinding(Scope scope) {
 	// it can be a package, type or member type
 	Binding binding = scope.getTypeOrPackage(new char[][] {token});
 	if (!binding.isValidBinding()) {
 		scope.problemReporter().invalidType(this, (TypeBinding) binding);
 		throw new SelectionNodeFound();
 	}
-
 	throw new SelectionNodeFound(binding);
 }
 public StringBuffer printExpression(int indent, StringBuffer output) {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
index d6785f2..d80e28b 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
@@ -91,7 +91,7 @@
 	}
 	return false;
 }
-protected void classInstanceCreation(boolean alwaysQualified) {
+protected void classInstanceCreation(boolean hasClassBody) {
 	
 	// ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
 
@@ -103,7 +103,7 @@
 		&& (astStack[astPtr] == null)) {
 
 		if (this.indexOfAssistIdentifier() < 0) {
-			super.classInstanceCreation(alwaysQualified);
+			super.classInstanceCreation(hasClassBody);
 			return;
 		}
 		QualifiedAllocationExpression alloc;
@@ -123,8 +123,9 @@
 		}
 		// trick to avoid creating a selection on type reference
 		char [] oldIdent = this.assistIdentifier();
-		this.setAssistIdentifier(null);			
+		this.setAssistIdentifier(null);
 		alloc.type = getTypeReference(0);
+		
 		this.setAssistIdentifier(oldIdent);
 		
 		//the default constructor with the correct number of argument
@@ -140,7 +141,7 @@
 		}
 		this.isOrphanCompletionNode = true;
 	} else {
-		super.classInstanceCreation(alwaysQualified);
+		super.classInstanceCreation(hasClassBody);
 	}
 }
 protected void consumeArrayCreationExpressionWithoutInitializer() {
@@ -158,9 +159,7 @@
 		this.isOrphanCompletionNode = true;
 	}
 }
-
 protected void consumeArrayCreationExpressionWithInitializer() {
-	// ArrayCreationWithArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializer
 	// ArrayCreationWithArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializer
 
 	super.consumeArrayCreationExpressionWithInitializer();
@@ -174,6 +173,126 @@
 		this.isOrphanCompletionNode = true;
 	}
 }
+protected void consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() {
+	// ClassInstanceCreationExpression ::= Primary '.' 'new' TypeArguments SimpleName '(' ArgumentListopt ')' ClassBodyopt
+	// ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' TypeArguments SimpleName '(' ArgumentListopt ')' ClassBodyopt
+
+	QualifiedAllocationExpression alloc;
+	int length;
+	if (((length = this.astLengthStack[this.astLengthPtr]) == 1) && (this.astStack[this.astPtr] == null)) {
+		
+		if (this.indexOfAssistIdentifier() < 0) {
+			super.consumeClassInstanceCreationExpressionQualifiedWithTypeArguments();
+			return;
+		}
+		
+		//NO ClassBody
+		this.astPtr--;
+		this.astLengthPtr--;
+		alloc = new SelectionOnQualifiedAllocationExpression();
+		alloc.sourceEnd = this.endPosition; //the position has been stored explicitly
+
+		if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+			this.expressionPtr -= length;
+			System.arraycopy(
+				this.expressionStack, 
+				this.expressionPtr + 1, 
+				alloc.arguments = new Expression[length], 
+				0, 
+				length); 
+		}
+		
+		// trick to avoid creating a selection on type reference
+		char [] oldIdent = this.assistIdentifier();
+		this.setAssistIdentifier(null);
+		alloc.type = getTypeReference(0);
+		
+		this.setAssistIdentifier(oldIdent);
+
+		length = this.genericsLengthStack[this.genericsLengthPtr--];
+		this.genericsPtr -= length;
+		System.arraycopy(this.genericsStack, this.genericsPtr + 1, alloc.typeArguments = new TypeReference[length], 0, length);
+		intPtr--; // remove the position of the '<'
+
+		//the default constructor with the correct number of argument
+		//will be created and added by the TC (see createsInternalConstructorWithBinding)
+		alloc.sourceStart = this.intStack[this.intPtr--];
+		pushOnExpressionStack(alloc);
+		
+		this.assistNode = alloc;
+		this.lastCheckPoint = alloc.sourceEnd + 1;
+		if (!diet){
+			this.restartRecovery	= true;	// force to restart in recovery mode
+			this.lastIgnoredToken = -1;	
+		}
+		this.isOrphanCompletionNode = true;
+	} else {
+		super.consumeClassInstanceCreationExpressionQualifiedWithTypeArguments();
+	}
+
+	this.expressionLengthPtr--;
+	QualifiedAllocationExpression qae = 
+		(QualifiedAllocationExpression) this.expressionStack[this.expressionPtr--]; 
+	qae.enclosingInstance = this.expressionStack[this.expressionPtr];
+	this.expressionStack[this.expressionPtr] = qae;
+	qae.sourceStart = qae.enclosingInstance.sourceStart;
+}
+protected void consumeClassInstanceCreationExpressionWithTypeArguments() {
+	// ClassInstanceCreationExpression ::= 'new' TypeArguments ClassType '(' ArgumentListopt ')' ClassBodyopt
+	AllocationExpression alloc;
+	int length;
+	if (((length = this.astLengthStack[this.astLengthPtr]) == 1)
+		&& (this.astStack[this.astPtr] == null)) {
+		
+		if (this.indexOfAssistIdentifier() < 0) {
+			super.consumeClassInstanceCreationExpressionWithTypeArguments();
+			return;
+		}
+		
+		//NO ClassBody
+		this.astPtr--;
+		this.astLengthPtr--;
+		alloc = new SelectionOnQualifiedAllocationExpression();
+		alloc.sourceEnd = this.endPosition; //the position has been stored explicitly
+
+		if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+			this.expressionPtr -= length;
+			System.arraycopy(
+				this.expressionStack, 
+				this.expressionPtr + 1, 
+				alloc.arguments = new Expression[length], 
+				0, 
+				length); 
+		}
+		
+		// trick to avoid creating a selection on type reference
+		char [] oldIdent = this.assistIdentifier();
+		this.setAssistIdentifier(null);
+		alloc.type = getTypeReference(0);
+		
+		this.setAssistIdentifier(oldIdent);
+
+		length = this.genericsLengthStack[this.genericsLengthPtr--];
+		this.genericsPtr -= length;
+		System.arraycopy(this.genericsStack, this.genericsPtr + 1, alloc.typeArguments = new TypeReference[length], 0, length);
+		intPtr--; // remove the position of the '<'
+		
+		//the default constructor with the correct number of argument
+		//will be created and added by the TC (see createsInternalConstructorWithBinding)
+		alloc.sourceStart = this.intStack[this.intPtr--];
+		pushOnExpressionStack(alloc);
+		
+		this.assistNode = alloc;
+		this.lastCheckPoint = alloc.sourceEnd + 1;
+		if (!diet){
+			this.restartRecovery	= true;	// force to restart in recovery mode
+			this.lastIgnoredToken = -1;	
+		}
+		this.isOrphanCompletionNode = true;
+	} else {
+		super.consumeClassInstanceCreationExpressionWithTypeArguments();
+	}
+}
 protected void consumeEnterAnonymousClassBody() {
 	// EnterAnonymousClassBody ::= $empty
 
@@ -181,11 +300,17 @@
 		super.consumeEnterAnonymousClassBody();
 		return;
 	}
-	QualifiedAllocationExpression alloc;
+	
+	// trick to avoid creating a selection on type reference
+	char [] oldIdent = this.assistIdentifier();
+	this.setAssistIdentifier(null);		
+	TypeReference typeReference = getTypeReference(0);
+	this.setAssistIdentifier(oldIdent);		
+
 	TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult); 
-		anonymousType.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
-		anonymousType.bits |= ASTNode.AnonymousAndLocalMask;
-		alloc = anonymousType.allocation = new SelectionOnQualifiedAllocationExpression(anonymousType); 
+	anonymousType.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
+	anonymousType.bits |= ASTNode.AnonymousAndLocalMask;
+	QualifiedAllocationExpression alloc = new SelectionOnQualifiedAllocationExpression(anonymousType); 
 	markEnclosingMemberWithLocalType();
 	pushOnAstStack(anonymousType);
 
@@ -200,11 +325,68 @@
 			0, 
 			argumentLength); 
 	}
+
+	alloc.type = typeReference;	
+
+	anonymousType.sourceEnd = alloc.sourceEnd;
+	//position at the type while it impacts the anonymous declaration
+	anonymousType.sourceStart = anonymousType.declarationSourceStart = alloc.type.sourceStart;
+	alloc.sourceStart = intStack[intPtr--];
+	pushOnExpressionStack(alloc);
+
+	assistNode = alloc;
+	this.lastCheckPoint = alloc.sourceEnd + 1;
+	if (!diet){
+		this.restartRecovery	= true;	// force to restart in recovery mode
+		this.lastIgnoredToken = -1;
+		currentToken = 0; // opening brace already taken into account
+		hasReportedError = true;
+	}
+
+	anonymousType.bodyStart = scanner.currentPosition;
+	listLength = 0; // will be updated when reading super-interfaces
+	// recovery
+	if (currentElement != null){
+		lastCheckPoint = anonymousType.bodyStart;
+		currentElement = currentElement.add(anonymousType, 0);
+		currentToken = 0; // opening brace already taken into account
+		lastIgnoredToken = -1;		
+	}
+}
+protected void consumeEnterAnonymousClassBodySimpleName() {
+	// EnterAnonymousClassBody ::= $empty
+
+	if (this.indexOfAssistIdentifier() < 0) {
+		super.consumeEnterAnonymousClassBodySimpleName();
+		return;
+	}
+	pushOnGenericsLengthStack(0);
+	pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
 	// trick to avoid creating a selection on type reference
 	char [] oldIdent = this.assistIdentifier();
-	this.setAssistIdentifier(null);			
-	alloc.type = getTypeReference(0);
-	this.setAssistIdentifier(oldIdent);		
+	this.setAssistIdentifier(null);		
+	TypeReference typeReference = getTypeReference(0);
+	this.setAssistIdentifier(oldIdent);	
+
+	TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult); 
+	anonymousType.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
+	anonymousType.bits |= ASTNode.AnonymousAndLocalMask;
+	QualifiedAllocationExpression alloc = new SelectionOnQualifiedAllocationExpression(anonymousType); 
+	markEnclosingMemberWithLocalType();
+	pushOnAstStack(anonymousType);
+
+	alloc.sourceEnd = rParenPos; //the position has been stored explicitly
+	int argumentLength;
+	if ((argumentLength = expressionLengthStack[expressionLengthPtr--]) != 0) {
+		expressionPtr -= argumentLength;
+		System.arraycopy(
+			expressionStack, 
+			expressionPtr + 1, 
+			alloc.arguments = new Expression[argumentLength], 
+			0, 
+			argumentLength); 
+	}
+	alloc.type = typeReference;
 
 	anonymousType.sourceEnd = alloc.sourceEnd;
 	//position at the type while it impacts the anonymous declaration
@@ -292,9 +474,9 @@
 	}
 	this.isOrphanCompletionNode = true;	
 }
-protected void consumeFormalParameter() {
+protected void consumeFormalParameter(boolean isVarArgs) {
 	if (this.indexOfAssistIdentifier() < 0) {
-		super.consumeFormalParameter();
+		super.consumeFormalParameter(isVarArgs);
 		if((!diet || dietInt != 0) && astPtr > -1) {
 			Argument argument = (Argument) astStack[astPtr];
 			if(argument.type == assistNode) {
@@ -304,11 +486,24 @@
 			}
 		}
 	} else {
-
 		identifierLengthPtr--;
 		char[] identifierName = identifierStack[identifierPtr];
 		long namePositions = identifierPositionStack[identifierPtr--];
-		TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
+		int extendedDimensions = this.intStack[this.intPtr--];
+		int endOfEllipsis = 0;
+		if (isVarArgs) {
+			endOfEllipsis = this.intStack[this.intPtr--];
+		}
+		int firstDimensions = this.intStack[this.intPtr--];
+		final int typeDimensions = firstDimensions + extendedDimensions;
+		TypeReference type = getTypeReference(typeDimensions);
+		if (isVarArgs) {
+			type = type.copyDims(typeDimensions + 1);
+			if (extendedDimensions == 0) {
+				type.sourceEnd = endOfEllipsis;
+			}
+			type.bits |= ASTNode.IsVarArgs; // set isVarArgs
+		}
 		int modifierPositions = intStack[intPtr--];
 		intPtr--;
 		Argument arg = 
@@ -344,6 +539,16 @@
 		this.lastIgnoredToken = -1;
 	}
 }
+protected void consumeInstanceOfExpressionWithName(int op) {
+	if (indexOfAssistIdentifier() < 0) {
+		super.consumeInstanceOfExpressionWithName(op);
+	} else {
+		getTypeReference(intStack[intPtr--]);
+		this.isOrphanCompletionNode = true;
+		this.restartRecovery = true;
+		this.lastIgnoredToken = -1;
+	}
+}
 protected void consumeLocalVariableDeclarationStatement() {
 	super.consumeLocalVariableDeclarationStatement();
 	
@@ -357,6 +562,80 @@
 		}
 	}
 }
+protected void consumeMarkerAnnotation() {
+	int index;
+	
+	if ((index = this.indexOfAssistIdentifier()) < 0) {
+		super.consumeMarkerAnnotation();
+		return;
+	} 
+	
+	MarkerAnnotation markerAnnotation = null;
+	int length = this.identifierLengthStack[this.identifierLengthPtr];
+	TypeReference typeReference;
+
+	/* retrieve identifiers subset and whole positions, the assist node positions
+		should include the entire replaced source. */
+	
+	char[][] subset = identifierSubSet(index);
+	identifierLengthPtr--;
+	identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(
+		identifierPositionStack, 
+		identifierPtr + 1, 
+		positions, 
+		0, 
+		length); 
+
+	/* build specific assist on type reference */
+	
+	if (index == 0) {
+		/* assist inside first identifier */
+		typeReference = this.createSingleAssistTypeReference(
+						assistIdentifier(), 
+						positions[0]);
+	} else {
+		/* assist inside subsequent identifier */
+		typeReference =	this.createQualifiedAssistTypeReference(
+						subset,  
+						assistIdentifier(), 
+						positions);
+	}
+	assistNode = typeReference;
+	this.lastCheckPoint = typeReference.sourceEnd + 1;
+
+	markerAnnotation = new MarkerAnnotation(typeReference, this.intStack[this.intPtr--]);
+	int sourceStart = markerAnnotation.sourceStart;
+	if (this.modifiersSourceStart < 0) {
+		this.modifiersSourceStart = sourceStart;
+	} else if (this.modifiersSourceStart > sourceStart) {
+		this.modifiersSourceStart = sourceStart;
+	}
+	markerAnnotation.declarationSourceEnd = markerAnnotation.sourceEnd;
+	pushOnExpressionStack(markerAnnotation);
+}
+protected void consumeMemberValuePair() {
+	if (this.indexOfAssistIdentifier() < 0) {
+		super.consumeMemberValuePair();
+		return;
+	} 
+	
+	char[] simpleName = this.identifierStack[this.identifierPtr];
+	long position = this.identifierPositionStack[this.identifierPtr--];
+	this.identifierLengthPtr--;
+	int end = (int) position;
+	int start = (int) (position >>> 32);
+	Expression value = this.expressionStack[this.expressionPtr--];
+	this.expressionLengthPtr--;
+	MemberValuePair memberValuePair = new SelectionOnNameOfMemberValuePair(simpleName, start, end, value);
+	pushOnAstStack(memberValuePair);
+	
+	assistNode = memberValuePair;
+	this.lastCheckPoint = memberValuePair.sourceEnd + 1;
+	
+	
+}
 protected void consumeMethodInvocationName() {
 	// MethodInvocation ::= Name '(' ArgumentListopt ')'
 
@@ -456,6 +735,174 @@
 	this.lastCheckPoint = constructorCall.sourceEnd + 1;
 	this.isOrphanCompletionNode = true;
 }
+protected void consumeNormalAnnotation() {
+	int index;
+	
+	if ((index = this.indexOfAssistIdentifier()) < 0) {
+		super.consumeNormalAnnotation();
+		return;
+	} 
+	
+	NormalAnnotation normalAnnotation = null;
+	int length = this.identifierLengthStack[this.identifierLengthPtr];
+	TypeReference typeReference;
+	
+	/* retrieve identifiers subset and whole positions, the assist node positions
+		should include the entire replaced source. */
+	
+	char[][] subset = identifierSubSet(index);
+	identifierLengthPtr--;
+	identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(
+		identifierPositionStack, 
+		identifierPtr + 1, 
+		positions, 
+		0, 
+		length); 
+
+	/* build specific assist on type reference */
+	
+	if (index == 0) {
+		/* assist inside first identifier */
+		typeReference = this.createSingleAssistTypeReference(
+						assistIdentifier(), 
+						positions[0]);
+	} else {
+		/* assist inside subsequent identifier */
+		typeReference =	this.createQualifiedAssistTypeReference(
+						subset,  
+						assistIdentifier(), 
+						positions);
+	}
+	assistNode = typeReference;
+	this.lastCheckPoint = typeReference.sourceEnd + 1;
+		
+	normalAnnotation = new NormalAnnotation(typeReference, this.intStack[this.intPtr--]);
+	if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.astStack, 
+			(this.astPtr -= length) + 1, 
+			normalAnnotation.memberValuePairs = new MemberValuePair[length], 
+			0, 
+			length); 
+	}
+	int sourceStart = normalAnnotation.sourceStart;
+	if (this.modifiersSourceStart < 0) {
+		this.modifiersSourceStart = sourceStart;
+	} else if (this.modifiersSourceStart > sourceStart) {
+		this.modifiersSourceStart = sourceStart;
+	}
+	normalAnnotation.declarationSourceEnd = this.rParenPos;
+	pushOnExpressionStack(normalAnnotation);
+}
+protected void consumeSingleMemberAnnotation() {
+	int index;
+	
+	if ((index = this.indexOfAssistIdentifier()) < 0) {
+		super.consumeSingleMemberAnnotation();
+		return;
+	} 
+	
+	SingleMemberAnnotation singleMemberAnnotation = null;
+	int length = this.identifierLengthStack[this.identifierLengthPtr];
+	TypeReference typeReference;
+	
+	/* retrieve identifiers subset and whole positions, the assist node positions
+		should include the entire replaced source. */
+	
+	char[][] subset = identifierSubSet(index);
+	identifierLengthPtr--;
+	identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(
+		identifierPositionStack, 
+		identifierPtr + 1, 
+		positions, 
+		0, 
+		length); 
+
+	/* build specific assist on type reference */
+	
+	if (index == 0) {
+		/* assist inside first identifier */
+		typeReference = this.createSingleAssistTypeReference(
+						assistIdentifier(), 
+						positions[0]);
+	} else {
+		/* assist inside subsequent identifier */
+		typeReference =	this.createQualifiedAssistTypeReference(
+						subset,  
+						assistIdentifier(), 
+						positions);
+	}
+	assistNode = typeReference;
+	this.lastCheckPoint = typeReference.sourceEnd + 1;
+
+	singleMemberAnnotation = new SingleMemberAnnotation(typeReference, this.intStack[this.intPtr--]);
+	singleMemberAnnotation.memberValue = this.expressionStack[this.expressionPtr--];
+	this.expressionLengthPtr--;
+	int sourceStart = singleMemberAnnotation.sourceStart;
+	if (this.modifiersSourceStart < 0) {
+		this.modifiersSourceStart = sourceStart;
+	} else if (this.modifiersSourceStart > sourceStart) {
+		this.modifiersSourceStart = sourceStart;
+	}
+	singleMemberAnnotation.declarationSourceEnd = this.rParenPos;
+	pushOnExpressionStack(singleMemberAnnotation);
+}
+protected void consumeStaticImportOnDemandDeclarationName() {
+	// TypeImportOnDemandDeclarationName ::= 'import' 'static' Name '.' '*'
+	/* push an ImportRef build from the last name 
+	stored in the identifier stack. */
+
+	int index;
+
+	/* no need to take action if not inside assist identifiers */
+	if ((index = indexOfAssistIdentifier()) < 0) {
+		super.consumeStaticImportOnDemandDeclarationName();
+		return;
+	}
+	/* retrieve identifiers subset and whole positions, the assist node positions
+		should include the entire replaced source. */
+	int length = identifierLengthStack[identifierLengthPtr];
+	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
+	identifierLengthPtr--;
+	identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(
+		identifierPositionStack, 
+		identifierPtr + 1, 
+		positions, 
+		0, 
+		length); 
+
+	/* build specific assist node on import statement */
+	ImportReference reference = this.createAssistImportReference(subset, positions, AccStatic);
+	reference.onDemand = true;
+	assistNode = reference;
+	this.lastCheckPoint = reference.sourceEnd + 1;
+	
+	pushOnAstStack(reference);
+
+	if (currentToken == TokenNameSEMICOLON){
+		reference.declarationSourceEnd = scanner.currentPosition - 1;
+	} else {
+		reference.declarationSourceEnd = (int) positions[length-1];
+	}
+	//endPosition is just before the ;
+	reference.declarationSourceStart = intStack[intPtr--];
+	// flush annotations defined prior to import statements
+	reference.declarationSourceEnd = this.flushCommentsDefinedPriorTo(reference.declarationSourceEnd);
+
+	// recovery
+	if (currentElement != null){
+		lastCheckPoint = reference.declarationSourceEnd+1;
+		currentElement = currentElement.add(reference, 0);
+		lastIgnoredToken = -1;
+		restartRecovery = true; // used to avoid branching back into the regular automaton		
+	}
+}
 protected void consumeTypeImportOnDemandDeclarationName() {
 	// TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
 	/* push an ImportRef build from the last name 
@@ -536,12 +983,20 @@
 					assistName, 
 					positions); 	
 }
+public TypeReference createParameterizedQualifiedAssistTypeReference(
+		char[][] tokens, TypeReference[][] typeArguments, char[] assistname, TypeReference[] assistTypeArguments, long[] positions) {
+	return new SelectionOnParameterizedQualifiedTypeReference(tokens, assistname, typeArguments, assistTypeArguments, positions);
+
+}
 public NameReference createSingleAssistNameReference(char[] assistName, long position) {
 	return new SelectionOnSingleNameReference(assistName, position);
 }
 public TypeReference createSingleAssistTypeReference(char[] assistName, long position) {
 	return new SelectionOnSingleTypeReference(assistName, position);
 }
+public TypeReference createParameterizedSingleAssistTypeReference(TypeReference[] typeArguments, char[] assistName, long position) {
+	return new SelectionOnParameterizedSingleTypeReference(assistName, typeArguments, position);
+}
 public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int start, int end) {
 
 	this.selectionStart = start;
@@ -569,6 +1024,8 @@
 			// discard 'super' from identifier stacks
 			identifierLengthStack[identifierLengthPtr] = completionIndex;
 			int ptr = identifierPtr -= (length - completionIndex);
+			pushOnGenericsLengthStack(0);
+			pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
 			reference = 
 				new SelectionOnQualifiedSuperReference(
 					getTypeReference(0), 
@@ -670,6 +1127,31 @@
 	this.isOrphanCompletionNode = true;
 	return messageSend;
 }
+protected MessageSend newMessageSendWithTypeArguments() {
+	char[] selector = identifierStack[identifierPtr];
+	if (selector != this.assistIdentifier()){
+		return super.newMessageSendWithTypeArguments();
+	}	
+	MessageSend messageSend = new SelectionOnMessageSend();
+	int length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		this.expressionPtr -= length;
+		System.arraycopy(
+			this.expressionStack, 
+			this.expressionPtr + 1, 
+			messageSend.arguments = new Expression[length], 
+			0, 
+			length); 
+	}
+	assistNode = messageSend;
+	if (!diet){
+		this.restartRecovery	= true;	// force to restart in recovery mode
+		this.lastIgnoredToken = -1;	
+	}
+	
+	this.isOrphanCompletionNode = true;
+	return messageSend;
+}
 public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int start, int end) {
 
 	if (end == -1) return super.parse(sourceUnit, compilationResult, start, end);
@@ -742,4 +1224,19 @@
 	*/
 	this.recoveryTokenCheck();
 }
+
+public  String toString() {
+	String s = ""; //$NON-NLS-1$
+	s = s + "elementKindStack : int[] = {"; //$NON-NLS-1$
+	for (int i = 0; i <= elementPtr; i++) {
+		s = s + String.valueOf(elementKindStack[i]) + ","; //$NON-NLS-1$ //$NON-NLS-2$
+	}
+	s = s + "}\n"; //$NON-NLS-1$
+	s = s + "elementInfoStack : int[] = {"; //$NON-NLS-1$
+	for (int i = 0; i <= elementPtr; i++) {
+		s = s + String.valueOf(elementInfoStack[i]) + ","; //$NON-NLS-1$ //$NON-NLS-2$
+	}
+	s = s + "}\n"; //$NON-NLS-1$
+	return s + super.toString();
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java
index 07d23e3..b21cdf4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java
@@ -28,6 +28,12 @@
 	public static final char[][] NO_CHAR_CHAR = new char[0][];
 	
 	/**
+	 * Constant for an empty String array.
+	 * @since 3.1
+	 */
+	public static final String[] NO_STRINGS = new String[0];
+	
+	/**
 	 * Answers a new array with appending the suffix character at the end of the array.
 	 * <br>
 	 * <br>
@@ -171,13 +177,14 @@
 	 * @since 3.0
 	 */
 	public static String[] charArrayToStringArray(char[][] charArrays) {
-		if (charArrays == null) {
+		if (charArrays == null)
 			return null;
-		}
-		String[] strings= new String[charArrays.length];
-		for (int i= 0; i < charArrays.length; i++) {
+		int length = charArrays.length;
+		if (length == 0)
+			return NO_STRINGS;
+		String[] strings= new String[length];
+		for (int i= 0; i < length; i++)
 			strings[i]= new String(charArrays[i]);
-		}
 		return strings;
 	}
 	/**
@@ -490,7 +497,7 @@
 
 	/**
 	 * Answers the concatenation of the three arrays inserting the sep1 character between the 
-	 * two arrays and sep2 between the last two.
+	 * first two arrays and sep2 between the last two.
 	 * It answers null if the three arrays are null.
 	 * If the first array is null, then it answers the concatenation of second and third inserting
 	 * the sep2 character between them.
@@ -867,6 +874,40 @@
 				return true;
 		return false;
 	}
+
+	/**
+	 * Answers true if the array contains an occurrence of one of the characters, false otherwise.
+	 * 
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    characters = { 'c', 'd' }
+	 *    array = { 'a', ' b'  }
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    characters = { 'c', 'd' }
+	 *    array = { 'a', ' b', 'c'  }
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param characters the characters to search
+	 * @param array the array in which the search is done
+	 * @return true if the array contains an occurrence of one of the characters, false otherwise.
+	 * @throws NullPointerException if array is null.
+	 */
+	public static final boolean contains(char[] characters, char[] array) {
+		for (int i = array.length; --i >= 0;)
+			for (int j = characters.length; --j >= 0;)
+				if (array[i] == characters[j])
+					return true;
+		return false;
+	}
 	
 	/**
 	 * Answers a deep copy of the toCopy array.
@@ -2269,6 +2310,58 @@
 		System.arraycopy(array, inStart, result, outStart, max - inStart);
 		return result;
 	}
+	
+	/**
+	 * Replace all occurrence of the character to be replaced with the remplacement character 
+	 * in a copy of the given array. Returns the given array if no occurrences of the character
+	 * to be replaced are found.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    toBeReplaced = 'b'
+	 *    replacementChar = 'a'
+	 *    result => A new array that is equals to { 'a' , 'a', 'a', 'a', 'a', 'a' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    toBeReplaced = 'c'
+	 *    replacementChar = 'a'
+	 *    result => The original array that remains unchanged.
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param array the given array
+	 * @param toBeReplaced the character to be replaced
+	 * @param replacementChar the replacement character
+	 * @throws NullPointerException if the given array is null
+	 * @since 3.1
+	 */
+	public static final char[] replaceOnCopy(
+		char[] array,
+		char toBeReplaced,
+		char replacementChar) {
+		
+		char[] result = null;
+		for (int i = 0, length = array.length; i < length; i++) {
+			char c = array[i];
+			if (c == toBeReplaced) {
+				if (result == null) {
+					result = new char[length];
+					System.arraycopy(array, 0, result, 0, i);
+				}
+				result[i] = replacementChar;
+			} else if (result != null) {
+				result[i] = c;
+			}
+		}
+		if (result == null) return array;
+		return result;
+	}
 
 	/**
 	 * Return a new array which is the split of the given array using the given divider and triming each subarray to remove
@@ -2677,7 +2770,9 @@
 	 * @since 3.0
 	 */
 	final static public String[] toStrings(char[][] array) {
+		if (array == null) return NO_STRINGS;
 		int length = array.length;
+		if (length == 0) return NO_STRINGS;
 		String[] result = new String[length];
 		for (int i = 0; i < length; i++)
 			result[i] = new String(array[i]);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
index 7be59f1..9092b81 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
@@ -69,6 +69,9 @@
  *								   JavadocInvalidTag
  *								   JavadocMessagePrefix
  *								   EmptyControlFlowStatement
+ *     IBM Corporation - added the following constants
+ *								   IllegalUsageOfQualifiedTypeReference
+ *								   InvalidDigit
  ****************************************************************************/
 package org.eclipse.jdt.core.compiler;
  
@@ -229,7 +232,7 @@
 	int InternalTypeNameProvided = TypeRelated + 6;
 	/** @since 2.1 */
 	int UnusedPrivateType = Internal + TypeRelated + 7;
-	
+
 	int IncompatibleTypesInEqualityOperator = TypeRelated + 15;
 	int IncompatibleTypesInConditionalOperator = TypeRelated + 16;
 	int TypeMismatch = TypeRelated + 17;
@@ -301,42 +304,21 @@
 	int DuplicateBlankFinalFieldInitialization = FieldRelated + 82;
 
 	// variable hiding
-	/**
-	 * The local variable {0} is hiding another local variable defined in an enclosing type scope 
-	 * @since 3.0
-	 */
+	/** @since 3.0 */
 	int LocalVariableHidingLocalVariable = Internal + 90;		
-
-	/**
-	 * The local variable {0} is hiding the field {1}.{2} 
-	 * @since 3.0
-	 */
+	/** @since 3.0 */
 	int LocalVariableHidingField = Internal + FieldRelated + 91;		
-	 
-	/**
-	 * The field {0}.{1} is hiding another local variable defined in an enclosing type scope
-	 * @since 3.0 
-	 */
+	/** @since 3.0 */
 	int FieldHidingLocalVariable = Internal + FieldRelated + 92;		
-
-	/**
-	 * The field {0}.{1} is hiding the field {2}.{3}
-	 * @since 3.0 
-	 */
+	/** @since 3.0 */
 	int FieldHidingField = Internal + FieldRelated + 93;		
-
-	/**
-	 * The argument {0} is hiding another local variable defined in an enclosing type scope
-	 * @since 3.0 
-	 */
+	/** @since 3.0 */
 	int ArgumentHidingLocalVariable = Internal + 94;		
-
-	/**
-	 * The argument {0} is hiding the field {2}.{3}
-	 * @since 3.0 
-	 */
+	/** @since 3.0 */
 	int ArgumentHidingField = Internal + 95;		
-
+	/** @since 3.1 */
+	int MissingSerialVersion = Internal + 96;
+	
 	// methods
 	int UndefinedMethod = MethodRelated + 100;
 	int NotVisibleMethod = MethodRelated + 101;
@@ -361,7 +343,6 @@
 	/** @since 3.0 */
 	int IndirectAccessToStaticMethod = Internal + MethodRelated + 119;
 
-	    
 	// constructors
 	int UndefinedConstructor = ConstructorRelated + 130;
 	int NotVisibleConstructor = ConstructorRelated + 131;
@@ -445,7 +426,7 @@
 	/** @since 3.0 */
 	int UnusedConstructorDeclaredThrownException = Internal + 186;	
 	/** @since 3.0 */
-	int InvalidCatchBlockSequence = Internal + TypeRelated + 187;	
+	int InvalidCatchBlockSequence = Internal + TypeRelated + 187;
 	/** @since 3.0 */
 	int EmptyControlFlowStatement = Internal + TypeRelated + 188;	
 	/** @since 3.0 */
@@ -462,6 +443,9 @@
 	int InheritedFieldHidesEnclosingName = FieldRelated + 196;
 	int InheritedTypeHidesEnclosingName = TypeRelated + 197;
 
+	/** @since 3.1 */
+	int IllegalUsageOfQualifiedTypeReference = Internal + Syntax + 198;
+
 	// miscellaneous
 	int ThisInStaticContext = Internal + 200;
 	int StaticMethodRequested = Internal + MethodRelated + 201;
@@ -526,6 +510,8 @@
 	int NullSourceString = Syntax + Internal + 258;
 	int UnterminatedString = Syntax + Internal + 259;
 	int UnterminatedComment = Syntax + Internal + 260;
+	/** @since 3.1 */
+	int InvalidDigit = Syntax + Internal + 262;	
 
 	// type related problems
 	int InterfaceCannotHaveInitializers = TypeRelated + 300;
@@ -535,7 +521,8 @@
 	int IllegalModifierForMemberClass = TypeRelated + 304;
 	int IllegalModifierForMemberInterface = TypeRelated + 305;
 	int IllegalModifierForLocalClass = TypeRelated + 306;
-
+	/** @since 3.1 */
+	int ForbiddenReference = TypeRelated + 307;
 	int IllegalModifierCombinationFinalAbstractForClass = TypeRelated + 308;
 	int IllegalVisibilityModifierForInterfaceMemberType = TypeRelated + 309;
 	int IllegalVisibilityModifierCombinationForMemberType = TypeRelated + 310;
@@ -559,19 +546,29 @@
 	int PackageIsNotExpectedPackage = 328;
 	/** @since 2.1 */
 	int ObjectCannotHaveSuperTypes = 329;
+	/** @since 3.1 */
+	int ObjectMustBeClass = 330;
 
-	// int InvalidSuperclassBase = TypeRelated + 329; // reserved to 334 included
+	/** @deprecated - problem is no longer generated, UndefinedType is used instead */
 	int SuperclassNotFound =  TypeRelated + 329 + ProblemReasons.NotFound; // TypeRelated + 330
+	/** @deprecated - problem is no longer generated, NotVisibleType is used instead */
 	int SuperclassNotVisible =  TypeRelated + 329 + ProblemReasons.NotVisible; // TypeRelated + 331
+	/** @deprecated - problem is no longer generated, use AmbiguousType is used instead */
 	int SuperclassAmbiguous =  TypeRelated + 329 + ProblemReasons.Ambiguous; // TypeRelated + 332
+	/** @deprecated - problem is no longer generated, use InternalTypeNameProvided is used instead */
 	int SuperclassInternalNameProvided =  TypeRelated + 329 + ProblemReasons.InternalNameProvided; // TypeRelated + 333
+	/** @deprecated - problem is no longer generated, use InheritedTypeHidesEnclosingName is used instead */
 	int SuperclassInheritedNameHidesEnclosingName =  TypeRelated + 329 + ProblemReasons.InheritedNameHidesEnclosingName; // TypeRelated + 334
 
-	// int InvalidInterfaceBase = TypeRelated + 334; // reserved to 339 included
+	/** @deprecated - problem is no longer generated, UndefinedType is used instead */
 	int InterfaceNotFound =  TypeRelated + 334 + ProblemReasons.NotFound; // TypeRelated + 335
+	/** @deprecated - problem is no longer generated, NotVisibleType is used instead */
 	int InterfaceNotVisible =  TypeRelated + 334 + ProblemReasons.NotVisible; // TypeRelated + 336
+	/** @deprecated - problem is no longer generated, use AmbiguousType is used instead */
 	int InterfaceAmbiguous =  TypeRelated + 334 + ProblemReasons.Ambiguous; // TypeRelated + 337
+	/** @deprecated - problem is no longer generated, use InternalTypeNameProvided is used instead */
 	int InterfaceInternalNameProvided =  TypeRelated + 334 + ProblemReasons.InternalNameProvided; // TypeRelated + 338
+	/** @deprecated - problem is no longer generated, use InheritedTypeHidesEnclosingName is used instead */
 	int InterfaceInheritedNameHidesEnclosingName =  TypeRelated + 334 + ProblemReasons.InheritedNameHidesEnclosingName; // TypeRelated + 339
 
 	// field related problems
@@ -583,11 +580,15 @@
 	int IllegalModifierCombinationFinalVolatileForField = FieldRelated + 345;
 	int UnexpectedStaticModifierForField = FieldRelated + 346;
 
-	// int FieldTypeProblemBase = FieldRelated + 349; //reserved to 354
+	/** @deprecated - problem is no longer generated, UndefinedType is used instead */
 	int FieldTypeNotFound =  FieldRelated + 349 + ProblemReasons.NotFound; // FieldRelated + 350
+	/** @deprecated - problem is no longer generated, NotVisibleType is used instead */
 	int FieldTypeNotVisible =  FieldRelated + 349 + ProblemReasons.NotVisible; // FieldRelated + 351
+	/** @deprecated - problem is no longer generated, use AmbiguousType is used instead */
 	int FieldTypeAmbiguous =  FieldRelated + 349 + ProblemReasons.Ambiguous; // FieldRelated + 352
+	/** @deprecated - problem is no longer generated, use InternalTypeNameProvided is used instead */
 	int FieldTypeInternalNameProvided =  FieldRelated + 349 + ProblemReasons.InternalNameProvided; // FieldRelated + 353
+	/** @deprecated - problem is no longer generated, use InheritedTypeHidesEnclosingName is used instead */
 	int FieldTypeInheritedNameHidesEnclosingName =  FieldRelated + 349 + ProblemReasons.InheritedNameHidesEnclosingName; // FieldRelated + 354
 	
 	// method related problems
@@ -606,25 +607,37 @@
 	int NativeMethodsCannotBeStrictfp = MethodRelated + 367;
 	int DuplicateModifierForArgument = MethodRelated + 368;
 
-	//	int ArgumentProblemBase = MethodRelated + 369; // reserved to 374 included.
+	/** @deprecated - problem is no longer generated, UndefinedType is used instead */
 	int ArgumentTypeNotFound =  MethodRelated + 369 + ProblemReasons.NotFound; // MethodRelated + 370
+	/** @deprecated - problem is no longer generated, NotVisibleType is used instead */
 	int ArgumentTypeNotVisible =  MethodRelated + 369 + ProblemReasons.NotVisible; // MethodRelated + 371
+	/** @deprecated - problem is no longer generated, use AmbiguousType is used instead */
 	int ArgumentTypeAmbiguous =  MethodRelated + 369 + ProblemReasons.Ambiguous; // MethodRelated + 372
+	/** @deprecated - problem is no longer generated, use InternalTypeNameProvided is used instead */
 	int ArgumentTypeInternalNameProvided =  MethodRelated + 369 + ProblemReasons.InternalNameProvided; // MethodRelated + 373
+	/** @deprecated - problem is no longer generated, use InheritedTypeHidesEnclosingName is used instead */
 	int ArgumentTypeInheritedNameHidesEnclosingName =  MethodRelated + 369 + ProblemReasons.InheritedNameHidesEnclosingName; // MethodRelated + 374
 
-	//	int ExceptionTypeProblemBase = MethodRelated + 374; // reserved to 379 included.
+	/** @deprecated - problem is no longer generated, UndefinedType is used instead */
 	int ExceptionTypeNotFound =  MethodRelated + 374 + ProblemReasons.NotFound; // MethodRelated + 375
+	/** @deprecated - problem is no longer generated, NotVisibleType is used instead */
 	int ExceptionTypeNotVisible =  MethodRelated + 374 + ProblemReasons.NotVisible; // MethodRelated + 376
+	/** @deprecated - problem is no longer generated, use AmbiguousType is used instead */
 	int ExceptionTypeAmbiguous =  MethodRelated + 374 + ProblemReasons.Ambiguous; // MethodRelated + 377
+	/** @deprecated - problem is no longer generated, use InternalTypeNameProvided is used instead */
 	int ExceptionTypeInternalNameProvided =  MethodRelated + 374 + ProblemReasons.InternalNameProvided; // MethodRelated + 378
+	/** @deprecated - problem is no longer generated, use InheritedTypeHidesEnclosingName is used instead */
 	int ExceptionTypeInheritedNameHidesEnclosingName =  MethodRelated + 374 + ProblemReasons.InheritedNameHidesEnclosingName; // MethodRelated + 379
 
-	//	int ReturnTypeProblemBase = MethodRelated + 379;
+	/** @deprecated - problem is no longer generated, UndefinedType is used instead */
 	int ReturnTypeNotFound =  MethodRelated + 379 + ProblemReasons.NotFound; // MethodRelated + 380
+	/** @deprecated - problem is no longer generated, NotVisibleType is used instead */
 	int ReturnTypeNotVisible =  MethodRelated + 379 + ProblemReasons.NotVisible; // MethodRelated + 381
+	/** @deprecated - problem is no longer generated, use AmbiguousType is used instead */
 	int ReturnTypeAmbiguous =  MethodRelated + 379 + ProblemReasons.Ambiguous; // MethodRelated + 382
+	/** @deprecated - problem is no longer generated, use InternalTypeNameProvided is used instead */
 	int ReturnTypeInternalNameProvided =  MethodRelated + 379 + ProblemReasons.InternalNameProvided; // MethodRelated + 383
+	/** @deprecated - problem is no longer generated, use InheritedTypeHidesEnclosingName is used instead */
 	int ReturnTypeInheritedNameHidesEnclosingName =  MethodRelated + 379 + ProblemReasons.InheritedNameHidesEnclosingName; // MethodRelated + 384
 
 	// import related problems
@@ -633,16 +646,26 @@
 	int CannotImportPackage = ImportRelated + 387;
 	int UnusedImport = ImportRelated + 388;
 
-	//	int ImportProblemBase = ImportRelated + 389;
 	int ImportNotFound =  ImportRelated + 389 + ProblemReasons.NotFound; // ImportRelated + 390
+	/** @deprecated - problem is no longer generated, NotVisibleType is used instead */
 	int ImportNotVisible =  ImportRelated + 389 + ProblemReasons.NotVisible; // ImportRelated + 391
+	/** @deprecated - problem is no longer generated, use AmbiguousType is used instead */
 	int ImportAmbiguous =  ImportRelated + 389 + ProblemReasons.Ambiguous; // ImportRelated + 392
+	/** @deprecated - problem is no longer generated, use InternalTypeNameProvided is used instead */
 	int ImportInternalNameProvided =  ImportRelated + 389 + ProblemReasons.InternalNameProvided; // ImportRelated + 393
+	/** @deprecated - problem is no longer generated, use InheritedTypeHidesEnclosingName is used instead */
 	int ImportInheritedNameHidesEnclosingName =  ImportRelated + 389 + ProblemReasons.InheritedNameHidesEnclosingName; // ImportRelated + 394
 
+	/** @since 3.1 */
+	int InvalidTypeForStaticImport =  ImportRelated + 391;
+
 	// local variable related problems
 	int DuplicateModifierForVariable = MethodRelated + 395;
 	int IllegalModifierForVariable = MethodRelated + 396;
+	/** @since 3.1 */
+	int LocalVariableCannotBeNull = MethodRelated + 397;
+	/** @since 3.1 */
+	int LocalVariableCanOnlyBeNull = MethodRelated + 398;
 
 	// method verifier problems
 	int AbstractMethodMustBeImplemented = MethodRelated + 400;
@@ -662,7 +685,9 @@
 	int IncompatibleReturnTypeForNonInheritedInterfaceMethod = MethodRelated + 413;
 	/** @since 2.1 */
 	int IncompatibleExceptionInThrowsClauseForNonInheritedInterfaceMethod = MethodRelated + 414;
-	
+	/** @since 3.0 */
+	int IllegalVararg = MethodRelated + 415;
+
 	// code snippet support
 	int CodeSnippetMissingClass = Internal + 420;
 	int CodeSnippetMissingMethod = Internal + 421;
@@ -684,6 +709,9 @@
 	// assertion warning
 	int UseAssertAsAnIdentifier = Internal + 440;
 	
+	// 1.5 features
+	int UseEnumAsAnIdentifier = Internal + 441;
+	
 	// detected task
 	/** @since 2.1 */
 	int Task = Internal + 450;
@@ -720,9 +748,9 @@
 	/** @since 3.0 */
 	int JavadocInvalidThrowsClassName = Javadoc + Internal + 481;
 	/** @since 3.0 */
-	int JavadocMissingSeeReference = Javadoc + Internal + 482;
+	int JavadocMissingReference = Javadoc + Internal + 482;
 	/** @since 3.0 */
-	int JavadocInvalidSeeReference = Javadoc + Internal + 483;
+	int JavadocInvalidReference = Javadoc + Internal + 483;
 	/** @since 3.0 */
 	int JavadocInvalidSeeHref = Javadoc + Internal + 484;
 	/** @since 3.0 */
@@ -794,7 +822,243 @@
 	/** @since 3.0 */
 	int JavadocUnterminatedInlineTag = Javadoc + Internal + 512;
 	/** @since 3.0 */
-	int JavadocMalformedSeeReference = Javadoc + Internal + 513;
+	int JavadocMissingHashCharacter = Javadoc + Internal + 513;
 	/** @since 3.0 */
-	int JavadocMessagePrefix = Internal + 515;
-}
+	int JavadocMalformedSeeReference = Javadoc + Internal + 514;
+	/** @since 3.0 */
+	int JavadocEmptyReturnTag = Javadoc + Internal + 515;
+	/** @since 3.1 */
+	int JavadocInvalidValueReference = Javadoc + Internal + 516;
+	/** @since 3.1 */
+	int JavadocUnexpectedText = Javadoc + Internal + 517;
+	/** @since 3.1 */
+	int JavadocInvalidParamTagName = Javadoc + Internal + 518;
+	/** @since 3.1 */
+	int JavadocInvalidParamTagTypeParameter = Javadoc + Internal + 469;
+	/** @since 3.0 */
+	int JavadocMessagePrefix = Internal + 519;
+
+	/**
+	 * Generics
+	 */
+	/** @since 3.1 */
+	int DuplicateTypeVariable = Internal + 520;
+	/** @since 3.1 */
+	int IllegalTypeVariableSuperReference = Internal + 521;
+	/** @since 3.1 */
+	int TypeVariableReferenceFromStaticContext = Internal + 522;
+	/** @since 3.1 */
+	int ObjectCannotBeGeneric = Internal + 523;
+	/** @since 3.1 */
+	int NonGenericType = TypeRelated + 524;
+	/** @since 3.1 */
+	int IncorrectArityForParameterizedType = TypeRelated + 525;
+	/** @since 3.1 */
+	int TypeArgumentMismatch = TypeRelated + 526;
+	/** @since 3.1 */
+	int DuplicateMethodErasure = TypeRelated + 527;
+	/** @since 3.1 */
+	int ReferenceToForwardTypeVariable = TypeRelated + 528;
+    /** @since 3.1 */
+	int BoundsMustBeAnInterface = TypeRelated + 529;	
+    /** @since 3.1 */
+	int UnsafeRawConstructorInvocation = TypeRelated + 530;
+    /** @since 3.1 */
+	int UnsafeRawMethodInvocation = TypeRelated + 531;
+    /** @since 3.1 */
+	int UnsafeRawConversion = TypeRelated + 532;
+    /** @since 3.1 */
+	int InvalidTypeVariableExceptionType = TypeRelated + 533;
+	/** @since 3.1 */
+	int InvalidParameterizedExceptionType = TypeRelated + 534;
+	/** @since 3.1 */
+	int IllegalGenericArray = TypeRelated + 535;
+	/** @since 3.1 */
+	int UnsafeRawFieldAssignment = TypeRelated + 536;
+	/** @since 3.1 */
+	int FinalBoundForTypeVariable = TypeRelated + 537;
+	/** @since 3.1 */
+	int UndefinedTypeVariable = Internal + 538;
+	/** @since 3.1 */
+	int SuperInterfacesCollide = TypeRelated + 539;
+	/** @since 3.1 */
+	int WildcardConstructorInvocation = TypeRelated + 540;
+	/** @since 3.1 */
+	int WildcardMethodInvocation = TypeRelated + 541;
+	/** @since 3.1 */
+	int WildcardFieldAssignment = TypeRelated + 542;
+	/** @since 3.1 */
+	int GenericMethodTypeArgumentMismatch = TypeRelated + 543;
+	/** @since 3.1 */
+	int GenericConstructorTypeArgumentMismatch = TypeRelated + 544;
+	/** @since 3.1 */
+	int UnsafeGenericCast = TypeRelated + 545;
+	/** @since 3.1 */
+	int IllegalInstanceofParameterizedType = Internal + 546;
+	/** @since 3.1 */
+	int IllegalInstanceofTypeParameter = Internal + 547;
+	/** @since 3.1 */
+	int NonGenericMethod = TypeRelated + 548;
+	/** @since 3.1 */
+	int IncorrectArityForParameterizedMethod = TypeRelated + 549;
+	/** @since 3.1 */
+	int ParameterizedMethodArgumentTypeMismatch = TypeRelated + 550;
+	/** @since 3.1 */
+	int NonGenericConstructor = TypeRelated + 551;
+	/** @since 3.1 */
+	int IncorrectArityForParameterizedConstructor = TypeRelated + 552;
+	/** @since 3.1 */
+	int ParameterizedConstructorArgumentTypeMismatch = TypeRelated + 553;
+	/** @since 3.1 */
+	int TypeArgumentsForRawGenericMethod = TypeRelated + 554;
+	/** @since 3.1 */
+	int TypeArgumentsForRawGenericConstructor = TypeRelated + 555;
+	/** @since 3.1 */
+	int SuperTypeUsingWildcard = TypeRelated + 556;
+	/** @since 3.1 */
+	int GenericTypeCannotExtendThrowable = TypeRelated + 557;
+	/** @since 3.1 */
+	int IllegalClassLiteralForTypeVariable = TypeRelated + 558;
+	/** @since 3.1 */
+	int UnsafeReturnTypeOverride = MethodRelated + 559;
+	/** @since 3.1 */
+	int MethodNameClash = MethodRelated + 560;
+	/** @since 3.1 */
+	int RawMemberTypeCannotBeParameterized = TypeRelated + 561;
+	/** @since 3.1 */
+	int MissingArgumentsForParameterizedMemberType = TypeRelated + 562;	
+	/** @since 3.1 */
+	int StaticMemberOfParameterizedType = TypeRelated + 563;	
+    /** @since 3.1 */
+	int BoundHasConflictingArguments = TypeRelated + 564;	
+    /** @since 3.1 */
+	int DuplicateParameterizedMethods = MethodRelated + 565;
+
+	/**
+	 * Foreach
+	 */
+	/** @since 3.1 */	
+	int IncompatibleTypesInForeach = TypeRelated + 580;	
+	/** @since 3.1 */
+	int InvalidTypeForCollection = Internal + 581;
+	
+	/**
+	 * 1.5 Syntax errors (when source level < 1.5)
+	 */
+	/** @since 3.1 */
+    int InvalidUsageOfTypeParameters = Syntax + Internal + 590;
+    /** @since 3.1 */
+    int InvalidUsageOfStaticImports = Syntax + Internal + 591;
+    /** @since 3.1 */
+    int InvalidUsageOfForeachStatements = Syntax + Internal + 592;
+    /** @since 3.1 */
+    int InvalidUsageOfTypeArguments = Syntax + Internal + 593;
+    /** @since 3.1 */
+    int InvalidUsageOfEnumDeclarations = Syntax + Internal + 594;
+    /** @since 3.1 */
+    int InvalidUsageOfVarargs = Syntax + Internal + 595;
+    /** @since 3.1 */
+    int InvalidUsageOfAnnotations = Syntax + Internal + 596;
+    /** @since 3.1 */
+    int InvalidUsageOfAnnotationDeclarations = Syntax + Internal + 597;
+    
+    /**
+     * Annotation
+     */
+	/** @since 3.1 */
+	int IllegalModifierForAnnotationMethod = MethodRelated + 600;
+    /** @since 3.1 */
+    int IllegalExtendedDimensions = MethodRelated + 601;
+    /** @since 3.1 */
+	int InvalidFileNameForPackageAnnotations = Syntax + Internal + 602;
+    /** @since 3.1 */
+	int IllegalModifierForAnnotationType = TypeRelated + 603;
+    /** @since 3.1 */
+	int IllegalModifierForAnnotationMemberType = TypeRelated + 604;
+    /** @since 3.1 */
+	int InvalidAnnotationMemberType = TypeRelated + 605;	
+    /** @since 3.1 */
+	int AnnotationCircularitySelfReference = TypeRelated + 606;
+    /** @since 3.1 */
+	int AnnotationCircularity = TypeRelated + 607;
+	/** @since 3.1 */
+	int DuplicateAnnotation = TypeRelated + 608;
+	/** @since 3.1 */
+	int MissingValueForAnnotationMember = TypeRelated + 609;
+	/** @since 3.1 */
+	int DuplicateAnnotationMember = Internal + 610;
+	/** @since 3.1 */
+	int UndefinedAnnotationMember = MethodRelated + 611;
+	/** @since 3.1 */
+	int AnnotationValueMustBeClassLiteral = Internal + 612;
+	/** @since 3.1 */
+	int AnnotationValueMustBeConstant = Internal + 613;
+	/** @since 3.1 */
+	int AnnotationFieldNeedConstantInitialization = Internal + 614;
+	/** @since 3.1 */
+	int IllegalModifierForAnnotationField = Internal + 615;
+	/** @since 3.1 */
+	int AnnotationCannotOverrideMethod = MethodRelated + 616;
+	/** @since 3.1 */
+	int AnnotationMembersCannotHaveParameters = Syntax + Internal + 617;
+	/** @since 3.1 */
+	int AnnotationMembersCannotHaveTypeParameters = Syntax + Internal + 618;
+	/** @since 3.1 */
+	int AnnotationTypeDeclarationCannotHaveSuperclass = Syntax + Internal + 619;
+	/** @since 3.1 */
+	int AnnotationTypeDeclarationCannotHaveSuperinterfaces = Syntax + Internal + 620;
+	/** @since 3.1 */
+	int DuplicateTargetInTargetAnnotation = Internal + 621;
+	/** @since 3.1 */
+	int DisallowedTargetForAnnotation = TypeRelated + 622;
+	/** @since 3.1 */
+	int MethodMustOverride = TypeRelated + 623;
+	/** @since 3.1 */
+	int AnnotationTypeDeclarationCannotHaveConstructor = Syntax + Internal + 624;
+		
+	/**
+	 * Corrupted binaries
+	 */
+	/** @since 3.1 */
+	int CorruptedSignature = Internal + 700;
+
+	/**
+	 * Autoboxing
+	 */
+	/** @since 3.1 */
+	int BoxingConversion = Internal + 720;
+	/** @since 3.1 */
+	int UnboxingConversion = Internal + 721;
+	
+	/**
+	 * Enum
+	 */
+	/** @since 3.1 */
+	int IllegalModifierForEnum = TypeRelated + 750;
+	/** @since 3.1 */
+	int IllegalModifierForEnumConstant = FieldRelated + 751;	
+	/** @since 3.1 */
+	int IllegalModifierForLocalEnum = TypeRelated + 752;
+	/** @since 3.1 */
+	int IllegalModifierForMemberEnum = TypeRelated + 753;
+	/** @since 3.1 */
+	int CannotDeclareEnumSpecialMethod = MethodRelated + 754;
+	/** @since 3.1 */
+	int IllegalQualifiedEnumConstantLabel = FieldRelated + 755;
+	/** @since 3.1 */
+	int CannotExtendEnum = TypeRelated + 756;
+	/** @since 3.1 */
+	int CannotInvokeSuperConstructorInEnum = MethodRelated + 757;
+	/** @since 3.1 */
+	int EnumAbstractMethodMustBeImplemented = MethodRelated + 758;
+
+	/**
+	 * Var args
+	 */
+	/** @since 3.1 */
+	int IllegalExtendedDimensionsForVarArgs = Syntax + Internal + 800;
+	/** @since 3.1 */
+	int MethodVarargsArgumentNeedCast = MethodRelated + 801;
+	/** @since 3.1 */
+	int ConstructorVarargsArgumentNeedCast = ConstructorRelated + 802;
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/InvalidInputException.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/InvalidInputException.java
index 27ec81d..508f522 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/InvalidInputException.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/InvalidInputException.java
@@ -16,6 +16,8 @@
  */
 public class InvalidInputException extends Exception {
 
+	private static final long serialVersionUID = 2909732853499731592L; // backward compatible
+	
 	/**
 	 * Creates a new exception with no detail message.
 	 */
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java
index 9e1166d..1a105fb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java
@@ -30,33 +30,11 @@
 	public void endVisit(AND_AND_Expression and_and_Expression, BlockScope scope) {
 		// do nothing by default
 	}
-	public void endVisit(JavadocArrayQualifiedTypeReference typeRef, BlockScope scope) {
-		// do nothing by default
-	}
-	public void endVisit(JavadocArraySingleTypeReference typeRef, BlockScope scope) {
-		// do nothing by default
-	}
-	public void endVisit(JavadocArgumentExpression expression, BlockScope scope) {
-		// do nothing by default
-	}
-	public void endVisit(JavadocFieldReference fieldRef, BlockScope scope) {
-		// do nothing by default
-	}
-	public void endVisit(JavadocMessageSend messageSend, BlockScope scope) {
-		// do nothing by default
-	}
-	public void endVisit(JavadocQualifiedTypeReference typeRef, BlockScope scope) {
-		// do nothing by default
-	}
-	public void endVisit(JavadocReturnStatement statement, BlockScope scope) {
-		// do nothing by default
-	}
-	public void endVisit(JavadocSingleNameReference argument, BlockScope scope) {
-		// do nothing by default
-	}
-	public void endVisit(JavadocSingleTypeReference typeRef, BlockScope scope) {
-		// do nothing by default
-	}
+	public void endVisit(
+			AnnotationMethodDeclaration annotationTypeDeclaration,
+			ClassScope classScope) {
+			// do nothing by default
+	}	
 	public void endVisit(Argument argument, BlockScope scope) {
 		// do nothing by default
 	}
@@ -87,10 +65,10 @@
 	public void endVisit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
 		// do nothing by default
 	}
-	public void endVisit(Assignment assignment, BlockScope scope) {
+	public void endVisit(AssertStatement assertStatement, BlockScope scope) {
 		// do nothing by default
 	}
-	public void endVisit(AssertStatement assertStatement, BlockScope scope) {
+	public void endVisit(Assignment assignment, BlockScope scope) {
 		// do nothing by default
 	}
 	public void endVisit(BinaryExpression binaryExpression, BlockScope scope) {
@@ -144,6 +122,9 @@
 	public void endVisit(DoubleLiteral doubleLiteral, BlockScope scope) {
 		// do nothing by default
 	}
+	public void endVisit(EmptyStatement emptyStatement, BlockScope scope) {
+		// do nothing by default
+	}
 	public void endVisit(EqualExpression equalExpression, BlockScope scope) {
 		// do nothing by default
 	}
@@ -169,7 +150,7 @@
 	public void endVisit(FloatLiteral floatLiteral, BlockScope scope) {
 		// do nothing by default
 	}
-	public void endVisit(EmptyStatement emptyStatement, BlockScope scope) {
+	public void endVisit(ForeachStatement forStatement, BlockScope scope) {
 		// do nothing by default
 	}
 	public void endVisit(ForStatement forStatement, BlockScope scope) {
@@ -192,6 +173,33 @@
 	public void endVisit(IntLiteral intLiteral, BlockScope scope) {
 		// do nothing by default
 	}
+	public void endVisit(JavadocArgumentExpression expression, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocArrayQualifiedTypeReference typeRef, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocArraySingleTypeReference typeRef, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocFieldReference fieldRef, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocMessageSend messageSend, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocQualifiedTypeReference typeRef, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocReturnStatement statement, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocSingleNameReference argument, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocSingleTypeReference typeRef, BlockScope scope) {
+		// do nothing by default
+	}
 	public void endVisit(LabeledStatement labeledStatement, BlockScope scope) {
 		// do nothing by default
 	}
@@ -201,6 +209,36 @@
 	public void endVisit(LongLiteral longLiteral, BlockScope scope) {
 		// do nothing by default
 	}
+	/**
+	 * @param annotation
+	 * @param scope
+	 * @since 3.1
+	 */
+	public void endVisit(MarkerAnnotation annotation, BlockScope scope) {
+		// do nothing by default
+	}
+	/**
+	 * @param annotation
+	 * @param scope
+	 * @since 3.1
+	 */
+	public void endVisit(MarkerAnnotation annotation, CompilationUnitScope scope) {
+		// do nothing by default
+	}
+	/**
+	 * @param pair
+	 * @param scope
+	 */
+	public void endVisit(MemberValuePair pair, BlockScope scope) {
+		// do nothing by default
+	}
+	/**
+	 * @param pair
+	 * @param scope
+	 */
+	public void endVisit(MemberValuePair pair, CompilationUnitScope scope) {
+		// do nothing by default
+	}
 	public void endVisit(MessageSend messageSend, BlockScope scope) {
 		// do nothing by default
 	}
@@ -210,12 +248,40 @@
 	public void endVisit(StringLiteralConcatenation literal, BlockScope scope) {
 		// do nothing by default
 	}
+	/**
+	 * @param annotation
+	 * @param scope
+	 * @since 3.1
+	 */
+	public void endVisit(NormalAnnotation annotation, BlockScope scope) {
+		// do nothing by default
+	}
+	/**
+	 * @param annotation
+	 * @param scope
+	 * @since 3.1
+	 */
+	public void endVisit(NormalAnnotation annotation, CompilationUnitScope scope) {
+		// do nothing by default
+	}
 	public void endVisit(NullLiteral nullLiteral, BlockScope scope) {
 		// do nothing by default
 	}
 	public void endVisit(OR_OR_Expression or_or_Expression, BlockScope scope) {
 		// do nothing by default
 	}
+	public void endVisit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, ClassScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, ClassScope scope) {
+		// do nothing by default
+	}
 	public void endVisit(PostfixExpression postfixExpression, BlockScope scope) {
 		// do nothing by default
 	}
@@ -255,6 +321,22 @@
 	public void endVisit(ReturnStatement returnStatement, BlockScope scope) {
 		// do nothing by default
 	}
+	/**
+	 * @param annotation
+	 * @param scope
+	 * @since 3.1
+	 */
+	public void endVisit(SingleMemberAnnotation annotation, BlockScope scope) {
+		// do nothing by default
+	}
+	/**
+	 * @param annotation
+	 * @param scope
+	 * @since 3.1
+	 */
+	public void endVisit(SingleMemberAnnotation annotation, CompilationUnitScope scope) {
+		// do nothing by default
+	}
 	public void endVisit(
 		SingleNameReference singleNameReference,
 		BlockScope scope) {
@@ -311,48 +393,37 @@
 		CompilationUnitScope scope) {
 		// do nothing by default
 	}	
+	public void endVisit(TypeParameter typeParameter, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(TypeParameter typeParameter, ClassScope scope) {
+		// do nothing by default
+	}
 	public void endVisit(UnaryExpression unaryExpression, BlockScope scope) {
 		// do nothing by default
 	}
 	public void endVisit(WhileStatement whileStatement, BlockScope scope) {
 		// do nothing by default
 	}
+	public void endVisit(Wildcard wildcard, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(Wildcard wildcard, ClassScope scope) {
+		// do nothing by default
+	}
 	public boolean visit(
 		AllocationExpression allocationExpression,
 		BlockScope scope) {
 		return true; // do nothing by default, keep traversing
-		// do nothing by default
 	}
 	public boolean visit(AND_AND_Expression and_and_Expression, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
-	public boolean visit(JavadocArrayQualifiedTypeReference typeRef, BlockScope scope) {
+	public boolean visit(
+			AnnotationMethodDeclaration annotationTypeDeclaration,
+			ClassScope classScope) {
 		return true; // do nothing by default, keep traversing
-	}
-	public boolean visit(JavadocArraySingleTypeReference typeRef, BlockScope scope) {
-		return true; // do nothing by default, keep traversing
-	}
-	public boolean visit(JavadocArgumentExpression expression, BlockScope scope) {
-		return true; // do nothing by default, keep traversing
-	}
-	public boolean visit(JavadocFieldReference fieldRef, BlockScope scope) {
-		return true; // do nothing by default, keep traversing
-	}
-	public boolean visit(JavadocMessageSend messageSend, BlockScope scope) {
-		return true; // do nothing by default, keep traversing
-	}
-	public boolean visit(JavadocQualifiedTypeReference typeRef, BlockScope scope) {
-		return true; // do nothing by default, keep traversing
-	}
-	public boolean visit(JavadocReturnStatement statement, BlockScope scope) {
-		return true; // do nothing by default, keep traversing
-	}
-	public boolean visit(JavadocSingleNameReference argument, BlockScope scope) {
-		return true; // do nothing by default, keep traversing
-	}
-	public boolean visit(JavadocSingleTypeReference typeRef, BlockScope scope) {
-		return true; // do nothing by default, keep traversing
-	}
+	}	
 	public boolean visit(Argument argument, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
@@ -383,10 +454,10 @@
 	public boolean visit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
-	public boolean visit(Assignment assignment, BlockScope scope) {
+	public boolean visit(AssertStatement assertStatement, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
-	public boolean visit(AssertStatement assertStatement, BlockScope scope) {
+	public boolean visit(Assignment assignment, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
 	public boolean visit(BinaryExpression binaryExpression, BlockScope scope) {
@@ -440,10 +511,10 @@
 	public boolean visit(DoubleLiteral doubleLiteral, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
-	public boolean visit(EqualExpression equalExpression, BlockScope scope) {
+	public boolean visit(EmptyStatement emptyStatement, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
-	public boolean visit(EmptyStatement emptyStatement, BlockScope scope) {
+	public boolean visit(EqualExpression equalExpression, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
 	public boolean visit(
@@ -468,6 +539,9 @@
 	public boolean visit(FloatLiteral floatLiteral, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
+	public boolean visit(ForeachStatement forStatement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
 	public boolean visit(ForStatement forStatement, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
@@ -488,6 +562,33 @@
 	public boolean visit(IntLiteral intLiteral, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
+	public boolean visit(JavadocArgumentExpression expression, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocArrayQualifiedTypeReference typeRef, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocArraySingleTypeReference typeRef, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocFieldReference fieldRef, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocMessageSend messageSend, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocQualifiedTypeReference typeRef, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocReturnStatement statement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocSingleNameReference argument, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocSingleTypeReference typeRef, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
 	public boolean visit(LabeledStatement labeledStatement, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
@@ -497,6 +598,38 @@
 	public boolean visit(LongLiteral longLiteral, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
+	/**
+	 * @param annotation
+	 * @param scope
+	 * @since 3.1
+	 */
+	public boolean visit(MarkerAnnotation annotation, BlockScope scope) {
+		return true;
+	}
+	/**
+	 * @param annotation
+	 * @param scope
+	 * @since 3.1
+	 */
+	public boolean visit(MarkerAnnotation annotation, CompilationUnitScope scope) {
+		return true;
+	}
+	/**
+	 * @param pair
+	 * @param scope
+	 * @since 3.1
+	 */
+	public boolean visit(MemberValuePair pair, BlockScope scope) {
+		return true;
+	}
+	/**
+	 * @param pair
+	 * @param scope
+	 * @since 3.1
+	 */
+	public boolean visit(MemberValuePair pair, CompilationUnitScope scope) {
+		return true;
+	}
 	public boolean visit(MessageSend messageSend, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
@@ -508,12 +641,40 @@
 			BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
+	/**
+	 * @param annotation
+	 * @param scope
+	 * @since 3.1
+	 */
+	public boolean visit(NormalAnnotation annotation, BlockScope scope) {
+		return true;
+	}
+	/**
+	 * @param annotation
+	 * @param scope
+	 * @since 3.1
+	 */
+	public boolean visit(NormalAnnotation annotation, CompilationUnitScope scope) {
+		return true;
+	}
 	public boolean visit(NullLiteral nullLiteral, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
 	public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
+	public boolean visit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, ClassScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, ClassScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
 	public boolean visit(PostfixExpression postfixExpression, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
@@ -553,6 +714,22 @@
 	public boolean visit(ReturnStatement returnStatement, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
+	/**
+	 * @param annotation
+	 * @param scope
+	 * @since 3.1
+	 */
+	public boolean visit(SingleMemberAnnotation annotation, BlockScope scope) {
+		return true;
+	}
+	/**
+	 * @param annotation
+	 * @param scope
+	 * @since 3.1
+	 */
+	public boolean visit(SingleMemberAnnotation annotation, CompilationUnitScope scope) {
+		return true;
+	}
 	public boolean visit(
 		SingleNameReference singleNameReference,
 		BlockScope scope) {
@@ -609,10 +786,22 @@
 		CompilationUnitScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
+	public boolean visit(TypeParameter typeParameter, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(TypeParameter typeParameter, ClassScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
 	public boolean visit(UnaryExpression unaryExpression, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
 	public boolean visit(WhileStatement whileStatement, BlockScope scope) {
 		return true; // do nothing by default, keep traversing
 	}
+	public boolean visit(Wildcard wildcard, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(Wildcard wildcard, ClassScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index e575af5..661f07f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -20,6 +20,7 @@
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
 import org.eclipse.jdt.internal.compiler.impl.StringConstant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
@@ -45,29 +46,285 @@
  */
 public class ClassFile
 	implements AttributeNamesConstants, CompilerModifiers, TypeConstants, TypeIds {
-	public SourceTypeBinding referenceBinding;
-	public ConstantPool constantPool;
-	public ClassFile enclosingClassFile;
-	// used to generate private access methods
-	public int produceDebugAttributes;
-	public ReferenceBinding[] innerClassesBindings;
-	public int numberOfInnerClasses;
-	public byte[] header;
-	// the header contains all the bytes till the end of the constant pool
-	public byte[] contents;
-	// that collection contains all the remaining bytes of the .class file
-	public int headerOffset;
-	public int contentsOffset;
-	public int constantPoolOffset;
-	public int methodCountOffset;
-	public int methodCount;
-	protected boolean creatingProblemType;
 	public static final int INITIAL_CONTENTS_SIZE = 400;
 	public static final int INITIAL_HEADER_SIZE = 1500;
-	public boolean ownSharedArrays = false; // flag set when header/contents are set to shared arrays
 	public static final int INNER_CLASSES_SIZE = 5;
+
+	/**
+	 * INTERNAL USE-ONLY
+	 * Build all the directories and subdirectories corresponding to the packages names
+	 * into the directory specified in parameters.
+	 *
+	 * outputPath is formed like:
+	 *	   c:\temp\ the last character is a file separator
+	 * relativeFileName is formed like:
+	 *     java\lang\String.class *
+	 * 
+	 * @param outputPath java.lang.String
+	 * @param relativeFileName java.lang.String
+	 * @return java.lang.String
+	 */
+	public static String buildAllDirectoriesInto(
+		String outputPath,
+		String relativeFileName)
+		throws IOException {
+		char fileSeparatorChar = File.separatorChar;
+		String fileSeparator = File.separator;
+		File f;
+		// First we ensure that the outputPath exists
+		outputPath = outputPath.replace('/', fileSeparatorChar);
+		// To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
+		if (outputPath.endsWith(fileSeparator)) {
+			outputPath = outputPath.substring(0, outputPath.length() - 1);
+		}
+		f = new File(outputPath);
+		if (f.exists()) {
+			if (!f.isDirectory()) {
+				System.out.println(Util.bind("output.isFile" , f.getAbsolutePath())); //$NON-NLS-1$
+				throw new IOException(Util.bind("output.isFileNotDirectory" )); //$NON-NLS-1$
+			}
+		} else {
+			// we have to create that directory
+			if (!f.mkdirs()) {
+				System.out.println(Util.bind("output.dirName" , f.getAbsolutePath())); //$NON-NLS-1$
+				throw new IOException(Util.bind("output.notValidAll" )); //$NON-NLS-1$
+			}
+		}
+		StringBuffer outDir = new StringBuffer(outputPath);
+		outDir.append(fileSeparator);
+		StringTokenizer tokenizer =
+			new StringTokenizer(relativeFileName, fileSeparator);
+		String token = tokenizer.nextToken();
+		while (tokenizer.hasMoreTokens()) {
+			f = new File(outDir.append(token).append(fileSeparator).toString());
+			if (f.exists()) {
+				// The outDir already exists, so we proceed the next entry
+				// System.out.println("outDir: " + outDir + " already exists.");
+			} else {
+				// Need to add the outDir
+				if (!f.mkdir()) {
+					System.out.println(Util.bind("output.fileName" , f.getName())); //$NON-NLS-1$
+					throw new IOException(Util.bind("output.notValid" )); //$NON-NLS-1$
+				}
+			}
+			token = tokenizer.nextToken();
+		}
+		// token contains the last one
+		return outDir.append(token).toString();
+	}
+
+	/**
+	 * INTERNAL USE-ONLY
+	 * Request the creation of a ClassFile compatible representation of a problematic type
+	 *
+	 * @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
+	 * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
+	 */
+	public static void createProblemType(
+		TypeDeclaration typeDeclaration,
+		CompilationResult unitResult) {
+		SourceTypeBinding typeBinding = typeDeclaration.binding;
+		ClassFile classFile = new ClassFile(typeBinding, null, true);
+	
+		// TODO (olivier) handle cases where a field cannot be generated (name too long)
+		// TODO (olivier) handle too many methods
+		// inner attributes
+		if (typeBinding.isMemberType())
+			classFile.recordEnclosingTypeAttributes(typeBinding);
+	
+		// 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
+			classFile.contents[classFile.contentsOffset++] = 0;
+			classFile.contents[classFile.contentsOffset++] = 0;
+		}
+		// leave some space for the methodCount
+		classFile.setForMethodInfos();
+		// add its user defined methods
+		MethodBinding[] methods = typeBinding.methods;
+		AbstractMethodDeclaration[] methodDeclarations = typeDeclaration.methods;
+		int maxMethodDecl = methodDeclarations == null ? 0 : methodDeclarations.length;
+		int problemsLength;
+		IProblem[] problems = unitResult.getErrors();
+		if (problems == null) {
+			problems = new IProblem[0];
+		}
+		IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+		System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+		if (methods != null) {
+			if (typeBinding.isInterface()) {
+				// we cannot create problem methods for an interface. So we have to generate a clinit
+				// which should contain all the problem
+				classFile.addProblemClinit(problemsCopy);
+				for (int i = 0, max = methods.length; i < max; i++) {
+					MethodBinding methodBinding;
+					if ((methodBinding = methods[i]) != null) {
+						// find the corresponding method declaration
+						for (int j = 0; j < maxMethodDecl; j++) {
+							if ((methodDeclarations[j] != null)
+								&& (methodDeclarations[j].binding == methods[i])) {
+								if (!methodBinding.isConstructor()) {
+									classFile.addAbstractMethod(methodDeclarations[j], methodBinding);
+								}
+								break;
+							}
+						}
+					}
+				}
+			} else {
+				for (int i = 0, max = methods.length; i < max; i++) {
+					MethodBinding methodBinding;
+					if ((methodBinding = methods[i]) != null) {
+						// find the corresponding method declaration
+						for (int j = 0; j < maxMethodDecl; j++) {
+							if ((methodDeclarations[j] != null)
+								&& (methodDeclarations[j].binding == methods[i])) {
+								AbstractMethodDeclaration methodDecl;
+								if ((methodDecl = methodDeclarations[j]).isConstructor()) {
+									classFile.addProblemConstructor(methodDecl, methodBinding, problemsCopy);
+								} else {
+									classFile.addProblemMethod(methodDecl, methodBinding, problemsCopy);
+								}
+								break;
+							}
+						}
+					}
+				}
+			}
+			// add abstract methods
+			classFile.addDefaultAbstractMethods();
+		}
+		// propagate generation of (problem) member types
+		if (typeDeclaration.memberTypes != null) {
+			for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) {
+				TypeDeclaration memberType = typeDeclaration.memberTypes[i];
+				if (memberType.binding != null) {
+					classFile.recordNestedMemberAttribute(memberType.binding);
+					ClassFile.createProblemType(memberType, unitResult);
+				}
+			}
+		}
+		classFile.addAttributes();
+		unitResult.record(typeBinding.constantPoolName(), classFile);
+	}
+
+	/**
+	 * INTERNAL USE-ONLY
+	 * Search the line number corresponding to a specific position
+	 */
+	public static final int searchLineNumber(
+		int[] startLineIndexes,
+		int position) {
+		// this code is completely useless, but it is the same implementation than
+		// org.eclipse.jdt.internal.compiler.problem.ProblemHandler.searchLineNumber(int[], int)
+		// if (startLineIndexes == null)
+		//	return 1;
+		int length = startLineIndexes.length;
+		if (length == 0)
+			return 1;
+		int g = 0, d = length - 1;
+		int m = 0;
+		while (g <= d) {
+			m = (g + d) / 2;
+			if (position < startLineIndexes[m]) {
+				d = m - 1;
+			} else
+				if (position > startLineIndexes[m]) {
+					g = m + 1;
+				} else {
+					return m + 1;
+				}
+		}
+		if (position < startLineIndexes[m]) {
+			return m + 1;
+		}
+		return m + 2;
+	}
+
+	/**
+	 * INTERNAL USE-ONLY
+	 * outputPath is formed like:
+	 *	   c:\temp\ the last character is a file separator
+	 * relativeFileName is formed like:
+	 *     java\lang\String.class
+	 * @param generatePackagesStructure a flag to know if the packages structure has to be generated.
+	 * @param outputPath the output directory
+	 * @param relativeFileName java.lang.String
+	 * @param contents byte[]
+	 * 
+	 */
+	public static void writeToDisk(
+		boolean generatePackagesStructure,
+		String outputPath,
+		String relativeFileName,
+		byte[] contents)
+		throws IOException {
+			
+		BufferedOutputStream output = null;
+		if (generatePackagesStructure) {
+			output = new BufferedOutputStream(
+				new FileOutputStream(
+						new File(buildAllDirectoriesInto(outputPath, relativeFileName))));
+		} else {
+			String fileName = null;
+			char fileSeparatorChar = File.separatorChar;
+			String fileSeparator = File.separator;
+			// First we ensure that the outputPath exists
+			outputPath = outputPath.replace('/', fileSeparatorChar);
+			// To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
+			int indexOfPackageSeparator = relativeFileName.lastIndexOf(fileSeparatorChar);
+			if (indexOfPackageSeparator == -1) {
+				if (outputPath.endsWith(fileSeparator)) {
+					fileName = outputPath + relativeFileName;
+				} else {
+					fileName = outputPath + fileSeparator + relativeFileName;
+				}
+			} else {
+				int length = relativeFileName.length();
+				if (outputPath.endsWith(fileSeparator)) {
+					fileName = outputPath + relativeFileName.substring(indexOfPackageSeparator + 1, length);
+				} else {
+					fileName = outputPath + fileSeparator + relativeFileName.substring(indexOfPackageSeparator + 1, length);
+				}
+			}
+			output = new BufferedOutputStream(
+				new FileOutputStream(
+						new File(fileName)));
+		}
+		try {
+			output.write(contents);
+		} finally {
+			output.flush();
+			output.close();
+		}
+	}
 	public CodeStream codeStream;
-	protected int problemLine;	// used to create line number attributes for problem methods
+	public ConstantPool constantPool;
+	public int constantPoolOffset;
+	// the header contains all the bytes till the end of the constant pool
+	public byte[] contents;
+	public int contentsOffset;
+	protected boolean creatingProblemType;
+	public ClassFile enclosingClassFile;
+	public byte[] header;
+	// that collection contains all the remaining bytes of the .class file
+	public int headerOffset;
+	public ReferenceBinding[] innerClassesBindings;
+	public int methodCount;
+	public int methodCountOffset;
+	public int numberOfInnerClasses;
+	public boolean ownSharedArrays = false; // flag set when header/contents are set to shared arrays
+	// used to generate private access methods
+	public int produceDebugAttributes;
+	public SourceTypeBinding referenceBinding;
 	public long targetJDK;
 	
 	/**
@@ -91,7 +348,7 @@
 		ClassFile enclosingClassFile,
 		boolean creatingProblemType) {
 	    
-		referenceBinding = aType;
+		this.referenceBinding = aType;
 		initByteArrays();
 
 		// generate the magic numbers inside the header
@@ -100,7 +357,8 @@
 		header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
 		header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
 		
-		this.targetJDK = referenceBinding.scope.environment().options.targetJDK;
+		final CompilerOptions options = aType.scope.environment().options;
+		this.targetJDK = options.targetJDK;
 		header[headerOffset++] = (byte) (this.targetJDK >> 8); // minor high
 		header[headerOffset++] = (byte) (this.targetJDK >> 0); // minor low
 		header[headerOffset++] = (byte) (this.targetJDK >> 24); // major high
@@ -139,15 +397,15 @@
 		// now we continue to generate the bytes inside the contents array
 		contents[contentsOffset++] = (byte) (accessFlags >> 8);
 		contents[contentsOffset++] = (byte) accessFlags;
-		int classNameIndex = constantPool.literalIndex(aType);
+		int classNameIndex = constantPool.literalIndexForType(aType.constantPoolName());
 		contents[contentsOffset++] = (byte) (classNameIndex >> 8);
 		contents[contentsOffset++] = (byte) classNameIndex;
 		int superclassNameIndex;
 		if (aType.isInterface()) {
-			superclassNameIndex = constantPool.literalIndexForJavaLangObject();
+			superclassNameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName);
 		} else {
 			superclassNameIndex =
-				(aType.superclass == null ? 0 : constantPool.literalIndex(aType.superclass));
+				(aType.superclass == null ? 0 : constantPool.literalIndexForType(aType.superclass.constantPoolName()));
 		}
 		contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
 		contents[contentsOffset++] = (byte) superclassNameIndex;
@@ -156,14 +414,14 @@
 		contents[contentsOffset++] = (byte) (interfacesCount >> 8);
 		contents[contentsOffset++] = (byte) interfacesCount;
 		for (int i = 0; i < interfacesCount; i++) {
-			int interfaceIndex = constantPool.literalIndex(superInterfacesBinding[i]);
+			int interfaceIndex = constantPool.literalIndexForType(superInterfacesBinding[i].constantPoolName());
 			contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
 			contents[contentsOffset++] = (byte) interfaceIndex;
 		}
-		produceDebugAttributes = referenceBinding.scope.environment().options.produceDebugAttributes;
+		produceDebugAttributes = options.produceDebugAttributes;
 		innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE];
 		this.creatingProblemType = creatingProblemType;
-		codeStream = new CodeStream(this);
+		codeStream = new CodeStream(this, this.targetJDK);
 
 		// retrieve the enclosing one guaranteed to be the one matching the propagated flow info
 		// 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
@@ -284,14 +542,14 @@
 			for (int i = 0; i < numberOfInnerClasses; i++) {
 				ReferenceBinding innerClass = innerClassesBindings[i];
 				int accessFlags = innerClass.getAccessFlags();
-				int innerClassIndex = constantPool.literalIndex(innerClass);
+				int innerClassIndex = constantPool.literalIndexForType(innerClass.constantPoolName());
 				// inner class index
 				contents[contentsOffset++] = (byte) (innerClassIndex >> 8);
 				contents[contentsOffset++] = (byte) innerClassIndex;
 				// outer class index: anonymous and local have no outer class index
 				if (innerClass.isMemberType()) {
 					// member or member of local
-					int outerClassIndex = constantPool.literalIndex(innerClass.enclosingType());
+					int outerClassIndex = constantPool.literalIndexForType(innerClass.enclosingType().constantPoolName());
 					contents[contentsOffset++] = (byte) (outerClassIndex >> 8);
 					contents[contentsOffset++] = (byte) outerClassIndex;
 				} else {
@@ -312,15 +570,86 @@
 				// access flag
 				if (innerClass.isAnonymousType()) {
 					accessFlags |= AccPrivate;
-				} else
-					if (innerClass.isLocalType() && !innerClass.isMemberType()) {
-						accessFlags |= AccPrivate;
-					}
+				} else if (innerClass.isLocalType() && !innerClass.isMemberType()) {
+					accessFlags |= AccPrivate;
+				} else if (innerClass.isMemberType() && (innerClass.isInterface() || innerClass.isAnnotationType())) {
+					accessFlags |= AccStatic; // implicitely static
+				}
 				contents[contentsOffset++] = (byte) (accessFlags >> 8);
 				contents[contentsOffset++] = (byte) accessFlags;
 			}
 			attributeNumber++;
 		}
+		// add signature attribute
+		char[] genericSignature = referenceBinding.genericSignature();
+		if (genericSignature != null) {
+			// check that there is enough space to write all the bytes for the field info corresponding
+			// to the @fieldBinding
+			if (contentsOffset + 8 >= contents.length) {
+				resizeContents(8);
+			}
+			int signatureAttributeNameIndex =
+				constantPool.literalIndex(AttributeNamesConstants.SignatureName);
+			contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
+			contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
+			// the length of a signature attribute is equals to 2
+			contents[contentsOffset++] = 0;
+			contents[contentsOffset++] = 0;
+			contents[contentsOffset++] = 0;
+			contents[contentsOffset++] = 2;
+			int signatureIndex =
+				constantPool.literalIndex(genericSignature);
+			contents[contentsOffset++] = (byte) (signatureIndex >> 8);
+			contents[contentsOffset++] = (byte) signatureIndex;
+			attributeNumber++;
+		}
+		if (targetJDK >= ClassFileConstants.JDK1_5
+				&& (this.referenceBinding.isAnonymousType() || this.referenceBinding.isLocalType())) {
+			// add enclosing method attribute (1.5 mode only)
+			if (contentsOffset + 10 >= contents.length) {
+				resizeContents(10);
+			}
+			int enclosingMethodAttributeNameIndex =
+				constantPool.literalIndex(AttributeNamesConstants.EnclosingMethodName);
+			contents[contentsOffset++] = (byte) (enclosingMethodAttributeNameIndex >> 8);
+			contents[contentsOffset++] = (byte) enclosingMethodAttributeNameIndex;
+			// the length of a signature attribute is equals to 2
+			contents[contentsOffset++] = 0;
+			contents[contentsOffset++] = 0;
+			contents[contentsOffset++] = 0;
+			contents[contentsOffset++] = 4;
+			
+			int enclosingTypeIndex = constantPool.literalIndexForType(this.referenceBinding.enclosingType().constantPoolName());
+			contents[contentsOffset++] = (byte) (enclosingTypeIndex >> 8);
+			contents[contentsOffset++] = (byte) enclosingTypeIndex;
+			byte methodIndexByte1 = 0;
+			byte methodIndexByte2 = 0;
+			if (this.referenceBinding.scope != null) {
+				MethodScope methodScope = this.referenceBinding.scope.methodScope();
+				if (methodScope != null) {
+					ReferenceContext referenceContext = methodScope.referenceContext;
+					if (referenceContext instanceof AbstractMethodDeclaration) {
+						AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) referenceContext;
+						MethodBinding methodBinding = methodDeclaration.binding;
+						int enclosingMethodIndex = constantPool.literalIndexForMethod(methodBinding.selector, methodBinding.signature());
+						methodIndexByte1 = (byte) (enclosingMethodIndex >> 8);
+						methodIndexByte2 = (byte) enclosingMethodIndex;
+					}
+				}
+			}
+			contents[contentsOffset++] = methodIndexByte1;
+			contents[contentsOffset++] = methodIndexByte2;
+			attributeNumber++;			
+		}
+		if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType) {
+			TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
+			if (typeDeclaration != null) {
+				final Annotation[] annotations = typeDeclaration.annotations;
+				if (annotations != null) {
+					attributeNumber += generateRuntimeAnnotations(annotations);
+				}
+			}
+		}
 		// update the number of attributes
 		if (attributeOffset + 2 >= this.contents.length) {
 			resizeContents(2);
@@ -335,7 +664,7 @@
 		header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
 		header[constantPoolOffset] = (byte) constantPoolCount;
 	}
-
+	
 	/**
 	 * INTERNAL USE-ONLY
 	 * This methods generate all the default abstract method infos that correpond to
@@ -352,37 +681,14 @@
 		}
 	}
 
-	/**
-	 * INTERNAL USE-ONLY
-	 * This methods generates the bytes for the field binding passed like a parameter
-	 * @param fieldBinding org.eclipse.jdt.internal.compiler.lookup.FieldBinding
-	 */
-	public void addFieldInfo(FieldBinding fieldBinding) {
-		int attributeNumber = 0;
-		// check that there is enough space to write all the bytes for the field info corresponding
-		// to the @fieldBinding
-		if (contentsOffset + 30 >= contents.length) {
-			resizeContents(30);
-		}
-		// Generate two attribute: constantValueAttribute and SyntheticAttribute
-		// Now we can generate all entries into the byte array
-		// First the accessFlags
-		int accessFlags = fieldBinding.getAccessFlags();
-		contents[contentsOffset++] = (byte) (accessFlags >> 8);
-		contents[contentsOffset++] = (byte) accessFlags;
-		// Then the nameIndex
-		int nameIndex = constantPool.literalIndex(fieldBinding.name);
-		contents[contentsOffset++] = (byte) (nameIndex >> 8);
-		contents[contentsOffset++] = (byte) nameIndex;
-		// Then the descriptorIndex
-		int descriptorIndex = constantPool.literalIndex(fieldBinding.type.signature());
-		contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
-		contents[contentsOffset++] = (byte) descriptorIndex;
-		// leave some space for the number of attributes
-		int fieldAttributeOffset = contentsOffset;
-		contentsOffset += 2;
+	private int addFieldAttributes(FieldBinding fieldBinding, int fieldAttributeOffset) {
+		int attributesNumber = 0;
 		// 4.7.2 only static constant fields get a ConstantAttribute
-		if (fieldBinding.constant != Constant.NotAConstant){
+		// Generate the constantValueAttribute
+		if (fieldBinding.isConstantValue()){
+			if (contentsOffset + 8 >= contents.length) {
+				resizeContents(8);
+			}
 			// Now we generate the constant attribute corresponding to the fieldBinding
 			int constantValueNameIndex =
 				constantPool.literalIndex(AttributeNamesConstants.ConstantValueName);
@@ -393,12 +699,13 @@
 			contents[contentsOffset++] = 0;
 			contents[contentsOffset++] = 0;
 			contents[contentsOffset++] = 2;
-			attributeNumber++;
+			attributesNumber++;
 			// Need to add the constant_value_index
-			switch (fieldBinding.constant.typeID()) {
+			Constant fieldConstant = fieldBinding.constant();
+			switch (fieldConstant.typeID()) {
 				case T_boolean :
 					int booleanValueIndex =
-						constantPool.literalIndex(fieldBinding.constant.booleanValue() ? 1 : 0);
+						constantPool.literalIndex(fieldConstant.booleanValue() ? 1 : 0);
 					contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
 					contents[contentsOffset++] = (byte) booleanValueIndex;
 					break;
@@ -407,32 +714,32 @@
 				case T_int :
 				case T_short :
 					int integerValueIndex =
-						constantPool.literalIndex(fieldBinding.constant.intValue());
+						constantPool.literalIndex(fieldConstant.intValue());
 					contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
 					contents[contentsOffset++] = (byte) integerValueIndex;
 					break;
 				case T_float :
 					int floatValueIndex =
-						constantPool.literalIndex(fieldBinding.constant.floatValue());
+						constantPool.literalIndex(fieldConstant.floatValue());
 					contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
 					contents[contentsOffset++] = (byte) floatValueIndex;
 					break;
 				case T_double :
 					int doubleValueIndex =
-						constantPool.literalIndex(fieldBinding.constant.doubleValue());
+						constantPool.literalIndex(fieldConstant.doubleValue());
 					contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
 					contents[contentsOffset++] = (byte) doubleValueIndex;
 					break;
 				case T_long :
 					int longValueIndex =
-						constantPool.literalIndex(fieldBinding.constant.longValue());
+						constantPool.literalIndex(fieldConstant.longValue());
 					contents[contentsOffset++] = (byte) (longValueIndex >> 8);
 					contents[contentsOffset++] = (byte) longValueIndex;
 					break;
-				case T_String :
+				case T_JavaLangString :
 					int stringValueIndex =
 						constantPool.literalIndex(
-							((StringConstant) fieldBinding.constant).stringValue());
+							((StringConstant) fieldConstant).stringValue());
 					if (stringValueIndex == -1) {
 						if (!creatingProblemType) {
 							// report an error and abort: will lead to a problem type classfile creation
@@ -447,9 +754,7 @@
 							}
 						} else {
 							// already inside a problem type creation : no constant for this field
-							contentsOffset = fieldAttributeOffset + 2;
-							// +2 is necessary to keep the two byte space for the attribute number
-							attributeNumber--;
+							contentsOffset = fieldAttributeOffset;
 						}
 					} else {
 						contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
@@ -457,7 +762,10 @@
 					}
 			}
 		}
-		if (fieldBinding.isSynthetic()) {
+		if (this.targetJDK < ClassFileConstants.JDK1_5 && fieldBinding.isSynthetic()) {
+			if (contentsOffset + 6 >= contents.length) {
+				resizeContents(6);
+			}
 			int syntheticAttributeNameIndex =
 				constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
 			contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
@@ -467,9 +775,12 @@
 			contents[contentsOffset++] = 0;
 			contents[contentsOffset++] = 0;
 			contents[contentsOffset++] = 0;
-			attributeNumber++;
+			attributesNumber++;
 		}
 		if (fieldBinding.isDeprecated()) {
+			if (contentsOffset + 6 >= contents.length) {
+				resizeContents(6);
+			}
 			int deprecatedAttributeNameIndex =
 				constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
 			contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
@@ -479,8 +790,75 @@
 			contents[contentsOffset++] = 0;
 			contents[contentsOffset++] = 0;
 			contents[contentsOffset++] = 0;
-			attributeNumber++;
+			attributesNumber++;
 		}
+		// add signature attribute
+		char[] genericSignature = fieldBinding.genericSignature();
+		if (genericSignature != null) {
+			// check that there is enough space to write all the bytes for the field info corresponding
+			// to the @fieldBinding
+			if (contentsOffset + 8 >= contents.length) {
+				resizeContents(8);
+			}
+			int signatureAttributeNameIndex =
+				constantPool.literalIndex(AttributeNamesConstants.SignatureName);
+			contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
+			contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
+			// the length of a signature attribute is equals to 2
+			contents[contentsOffset++] = 0;
+			contents[contentsOffset++] = 0;
+			contents[contentsOffset++] = 0;
+			contents[contentsOffset++] = 2;
+			int signatureIndex =
+				constantPool.literalIndex(genericSignature);
+			contents[contentsOffset++] = (byte) (signatureIndex >> 8);
+			contents[contentsOffset++] = (byte) signatureIndex;
+			attributesNumber++;
+		}
+		if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType) {
+			FieldDeclaration fieldDeclaration = fieldBinding.sourceField();
+			if (fieldDeclaration != null) {
+				Annotation[] annotations = fieldDeclaration.annotations;
+				if (annotations != null) {
+					attributesNumber += generateRuntimeAnnotations(annotations);
+				}
+			}
+		}
+		return attributesNumber;
+	}
+	/**
+	 * INTERNAL USE-ONLY
+	 * This methods generates the bytes for the given field binding
+	 * @param fieldBinding the given field binding
+	 */
+	private void addFieldInfo(FieldBinding fieldBinding) {
+		// check that there is enough space to write all the bytes for the field info corresponding
+		// to the @fieldBinding
+		if (contentsOffset + 8 >= contents.length) {
+			resizeContents(8);
+		}
+		// Now we can generate all entries into the byte array
+		// First the accessFlags
+		int accessFlags = fieldBinding.getAccessFlags();
+		if (targetJDK < ClassFileConstants.JDK1_5) {
+		    // pre 1.5, synthetic was an attribute, not a modifier
+		    accessFlags &= ~AccSynthetic;
+		}		
+		contents[contentsOffset++] = (byte) (accessFlags >> 8);
+		contents[contentsOffset++] = (byte) accessFlags;
+		// Then the nameIndex
+		int nameIndex = constantPool.literalIndex(fieldBinding.name);
+		contents[contentsOffset++] = (byte) (nameIndex >> 8);
+		contents[contentsOffset++] = (byte) nameIndex;
+		// Then the descriptorIndex
+		int descriptorIndex = constantPool.literalIndex(fieldBinding.type.signature());
+		contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
+		contents[contentsOffset++] = (byte) descriptorIndex;
+		int fieldAttributeOffset = contentsOffset;
+		int attributeNumber = 0;
+		// leave some space for the number of attributes
+		contentsOffset += 2;
+		attributeNumber += addFieldAttributes(fieldBinding, fieldAttributeOffset);
 		contents[fieldAttributeOffset++] = (byte) (attributeNumber >> 8);
 		contents[fieldAttributeOffset] = (byte) attributeNumber;
 	}
@@ -492,6 +870,13 @@
 	 * - a field info for each defined field of that class
 	 * - a field info for each synthetic field (e.g. this$0)
 	 */
+	/**
+	 * INTERNAL USE-ONLY
+	 * This methods generate all the fields infos for the receiver.
+	 * This includes:
+	 * - a field info for each defined field of that class
+	 * - a field info for each synthetic field (e.g. this$0)
+	 */
 	public void addFieldInfos() {
 		SourceTypeBinding currentBinding = referenceBinding;
 		FieldBinding[] syntheticFields = currentBinding.syntheticFields();
@@ -523,7 +908,7 @@
 	 * have to be generated for the inner classes attributes.
 	 * @param refBinding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding 
 	 */
-	public void addInnerClasses(ReferenceBinding refBinding) {
+	private void addInnerClasses(ReferenceBinding refBinding) {
 		// check first if that reference binding is there
 		for (int i = 0; i < numberOfInnerClasses; i++) {
 			if (innerClassesBindings[i] == refBinding)
@@ -540,6 +925,38 @@
 		}
 		innerClassesBindings[numberOfInnerClasses++] = refBinding;
 	}
+	
+	private void addMissingAbstractProblemMethod(MethodDeclaration methodDeclaration, MethodBinding methodBinding, IProblem problem, CompilationResult compilationResult) {
+		// always clear the strictfp/native/abstract bit for a problem method
+		generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(AccStrictfp | AccNative | AccAbstract));
+		int methodAttributeOffset = contentsOffset;
+		int attributeNumber = generateMethodInfoAttribute(methodBinding);
+		
+		// Code attribute
+		attributeNumber++;
+		
+		int codeAttributeOffset = contentsOffset;
+		generateCodeAttributeHeader();
+		StringBuffer buffer = new StringBuffer(25);
+		buffer.append("\t"  + problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
+		buffer.insert(0, Util.bind("compilation.unresolvedProblem" )); //$NON-NLS-1$
+		String problemString = buffer.toString();
+		
+		codeStream.init(this);
+		codeStream.preserveUnusedLocals = true;
+		codeStream.initializeMaxLocals(methodBinding);
+
+		// return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+		codeStream.generateCodeAttributeForProblemMethod(problemString);
+				
+		completeCodeAttributeForMissingAbstractProblemMethod(
+			methodBinding,
+			codeAttributeOffset,
+			compilationResult.lineSeparatorPositions,
+			problem.getSourceLineNumber());
+			
+		completeMethodInfo(methodAttributeOffset, attributeNumber);
+	}
 
 	/**
 	 * INTERNAL USE-ONLY
@@ -559,6 +976,7 @@
 		generateCodeAttributeHeader();
 		codeStream.resetForProblemClinit(this);
 		String problemString = "" ; //$NON-NLS-1$
+		int problemLine = 0;
 		if (problems != null) {
 			int max = problems.length;
 			StringBuffer buffer = new StringBuffer(25);
@@ -591,7 +1009,8 @@
 				.scope
 				.referenceCompilationUnit()
 				.compilationResult
-				.lineSeparatorPositions);
+				.lineSeparatorPositions,
+			problemLine);
 		contents[attributeOffset++] = (byte) (attributeNumber >> 8);
 		contents[attributeOffset] = (byte) attributeNumber;
 	}
@@ -612,7 +1031,7 @@
 		// always clear the strictfp/native/abstract bit for a problem method
 		generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(AccStrictfp | AccNative | AccAbstract));
 		int methodAttributeOffset = contentsOffset;
-		int attributeNumber = generateMethodInfoAttribute(methodBinding);
+		int attributeNumber = generateMethodInfoAttribute(methodBinding, true);
 		
 		// Code attribute
 		attributeNumber++;
@@ -620,6 +1039,7 @@
 		generateCodeAttributeHeader();
 		codeStream.reset(method, this);
 		String problemString = "" ; //$NON-NLS-1$
+		int problemLine = 0;
 		if (problems != null) {
 			int max = problems.length;
 			StringBuffer buffer = new StringBuffer(25);
@@ -652,7 +1072,8 @@
 				.scope
 				.referenceCompilationUnit()
 				.compilationResult
-				.lineSeparatorPositions);
+				.lineSeparatorPositions,
+			problemLine);
 		completeMethodInfo(methodAttributeOffset, attributeNumber);
 	}
 
@@ -695,7 +1116,7 @@
 		// always clear the strictfp/native/abstract bit for a problem method
 		generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(AccStrictfp | AccNative | AccAbstract));
 		int methodAttributeOffset = contentsOffset;
-		int attributeNumber = generateMethodInfoAttribute(methodBinding);
+		int attributeNumber = generateMethodInfoAttribute(methodBinding, true);
 		
 		// Code attribute
 		attributeNumber++;
@@ -704,6 +1125,7 @@
 		generateCodeAttributeHeader();
 		codeStream.reset(method, this);
 		String problemString = "" ; //$NON-NLS-1$
+		int problemLine = 0;
 		if (problems != null) {
 			int max = problems.length;
 			StringBuffer buffer = new StringBuffer(25);
@@ -740,7 +1162,8 @@
 				.scope
 				.referenceCompilationUnit()
 				.compilationResult
-				.lineSeparatorPositions);
+				.lineSeparatorPositions,
+			problemLine);
 		completeMethodInfo(methodAttributeOffset, attributeNumber);
 	}
 
@@ -773,12 +1196,13 @@
 	 * - default abstract methods
 	 */
 	public void addSpecialMethods() {
+	    
 		// add all methods (default abstract methods and synthetic)
 
 		// default abstract methods
-		SourceTypeBinding currentBinding = referenceBinding;
-		MethodBinding[] defaultAbstractMethods =
-			currentBinding.getDefaultAbstractMethods();
+		generateMissingAbstractMethods(referenceBinding.scope.referenceType().missingAbstractMethods, referenceBinding.scope.referenceCompilationUnit().compilationResult);
+
+		MethodBinding[] defaultAbstractMethods = this.referenceBinding.getDefaultAbstractMethods();
 		for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
 			generateMethodInfoHeader(defaultAbstractMethods[i]);
 			int methodAttributeOffset = contentsOffset;
@@ -786,181 +1210,51 @@
 			completeMethodInfo(methodAttributeOffset, attributeNumber);
 		}
 		// add synthetic methods infos
-		SyntheticAccessMethodBinding[] syntheticAccessMethods =
-			currentBinding.syntheticAccessMethods();
-		if (syntheticAccessMethods != null) {
-			for (int i = 0, max = syntheticAccessMethods.length; i < max; i++) {
-				SyntheticAccessMethodBinding accessMethodBinding = syntheticAccessMethods[i];
-				switch (accessMethodBinding.accessType) {
-					case SyntheticAccessMethodBinding.FieldReadAccess :
+		SyntheticMethodBinding[] syntheticMethods = this.referenceBinding.syntheticMethods();
+		if (syntheticMethods != null) {
+			for (int i = 0, max = syntheticMethods.length; i < max; i++) {
+				SyntheticMethodBinding syntheticMethod = syntheticMethods[i];
+				switch (syntheticMethod.kind) {
+					case SyntheticMethodBinding.FieldReadAccess :
 						// generate a method info to emulate an reading access to
 						// a non-accessible field
-						addSyntheticFieldReadAccessMethod(syntheticAccessMethods[i]);
+						addSyntheticFieldReadAccessMethod(syntheticMethod);
 						break;
-					case SyntheticAccessMethodBinding.FieldWriteAccess :
+					case SyntheticMethodBinding.FieldWriteAccess :
 						// generate a method info to emulate an writing access to
 						// a non-accessible field
-						addSyntheticFieldWriteAccessMethod(syntheticAccessMethods[i]);
+						addSyntheticFieldWriteAccessMethod(syntheticMethod);
 						break;
-					case SyntheticAccessMethodBinding.MethodAccess :
-					case SyntheticAccessMethodBinding.SuperMethodAccess :
-						// generate a method info to emulate an access to a non-accessible method / super-method
-						addSyntheticMethodAccessMethod(syntheticAccessMethods[i]);
+					case SyntheticMethodBinding.MethodAccess :
+					case SyntheticMethodBinding.SuperMethodAccess :
+					case SyntheticMethodBinding.BridgeMethod :
+						// generate a method info to emulate an access to a non-accessible method / super-method or bridge method
+						addSyntheticMethodAccessMethod(syntheticMethod);
 						break;
-					case SyntheticAccessMethodBinding.ConstructorAccess :
+					case SyntheticMethodBinding.ConstructorAccess :
 						// generate a method info to emulate an access to a non-accessible constructor
-						addSyntheticConstructorAccessMethod(syntheticAccessMethods[i]);
+						addSyntheticConstructorAccessMethod(syntheticMethod);
+						break;
+					case SyntheticMethodBinding.EnumValues :
+						// generate a method info to define <enum>#values()
+						addSyntheticEnumValuesMethod(syntheticMethod);
+						break;
+					case SyntheticMethodBinding.EnumValueOf :
+						// generate a method info to define <enum>#valueOf(String)
+						addSyntheticEnumValueOfMethod(syntheticMethod);
+						break;
 				}
 			}
 		}
 	}
-
+		
 	/**
 	 * INTERNAL USE-ONLY
-	 * Generate the byte for problem method infos that correspond to missing abstract methods.
-	 * http://dev.eclipse.org/bugs/show_bug.cgi?id=3179
-	 *
-	 * @param methodDeclarations Array of all missing abstract methods
-	 */
-	public void generateMissingAbstractMethods(MethodDeclaration[] methodDeclarations, CompilationResult compilationResult) {
-		if (methodDeclarations != null) {
-			for (int i = 0, max = methodDeclarations.length; i < max; i++) {
-				MethodDeclaration methodDeclaration = methodDeclarations[i];
-				MethodBinding methodBinding = methodDeclaration.binding;
-		 		String readableName = new String(methodBinding.readableName());
-		 		IProblem[] problems = compilationResult.problems;
-		 		int problemsCount = compilationResult.problemCount;
-				for (int j = 0; j < problemsCount; j++) {
-					IProblem problem = problems[j];
-					if (problem != null
-						&& problem.getID() == IProblem.AbstractMethodMustBeImplemented
-						&& problem.getMessage().indexOf(readableName) != -1) {
-							// we found a match
-							addMissingAbstractProblemMethod(methodDeclaration, methodBinding, problem, compilationResult);
-						}
-				}
-			}
-		}
-	}
-	
-	private void addMissingAbstractProblemMethod(MethodDeclaration methodDeclaration, MethodBinding methodBinding, IProblem problem, CompilationResult compilationResult) {
-		// always clear the strictfp/native/abstract bit for a problem method
-		generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(AccStrictfp | AccNative | AccAbstract));
-		int methodAttributeOffset = contentsOffset;
-		int attributeNumber = generateMethodInfoAttribute(methodBinding);
-		
-		// Code attribute
-		attributeNumber++;
-		
-		int codeAttributeOffset = contentsOffset;
-		generateCodeAttributeHeader();
-		StringBuffer buffer = new StringBuffer(25);
-		buffer.append("\t"  + problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
-		buffer.insert(0, Util.bind("compilation.unresolvedProblem" )); //$NON-NLS-1$
-		String problemString = buffer.toString();
-		this.problemLine = problem.getSourceLineNumber();
-		
-		codeStream.init(this);
-		codeStream.preserveUnusedLocals = true;
-		codeStream.initializeMaxLocals(methodBinding);
-
-		// return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
-		codeStream.generateCodeAttributeForProblemMethod(problemString);
-				
-		completeCodeAttributeForMissingAbstractProblemMethod(
-			methodBinding,
-			codeAttributeOffset,
-			compilationResult.lineSeparatorPositions);
-			
-		completeMethodInfo(methodAttributeOffset, attributeNumber);
-	}
-
-	/**
-	 * 
-	 */
-	public void completeCodeAttributeForMissingAbstractProblemMethod(
-		MethodBinding binding,
-		int codeAttributeOffset,
-		int[] startLineIndexes) {
-		// reinitialize the localContents with the byte modified by the code stream
-		this.contents = codeStream.bCodeStream;
-		int localContentsOffset = codeStream.classFileOffset;
-		// codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc...
-		int max_stack = codeStream.stackMax;
-		this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
-		this.contents[codeAttributeOffset + 7] = (byte) max_stack;
-		int max_locals = codeStream.maxLocals;
-		this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
-		this.contents[codeAttributeOffset + 9] = (byte) max_locals;
-		int code_length = codeStream.position;
-		this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
-		this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
-		this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
-		this.contents[codeAttributeOffset + 13] = (byte) code_length;
-		// write the exception table
-		if (localContentsOffset + 50 >= this.contents.length) {
-			resizeContents(50);
-		}
-		this.contents[localContentsOffset++] = 0;
-		this.contents[localContentsOffset++] = 0;
-		// debug attributes
-		int codeAttributeAttributeOffset = localContentsOffset;
-		int attributeNumber = 0; // leave two bytes for the attribute_length
-		localContentsOffset += 2; // first we handle the linenumber attribute
-
-		if (codeStream.generateLineNumberAttributes) {
-			/* Create and add the line number attribute (used for debugging) 
-			    * Build the pairs of:
-			    * (bytecodePC lineNumber)
-			    * according to the table of start line indexes and the pcToSourceMap table
-			    * contained into the codestream
-			    */
-			int lineNumberNameIndex =
-				constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
-			this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
-			this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
-			this.contents[localContentsOffset++] = 0;
-			this.contents[localContentsOffset++] = 0;
-			this.contents[localContentsOffset++] = 0;
-			this.contents[localContentsOffset++] = 6;
-			this.contents[localContentsOffset++] = 0;
-			this.contents[localContentsOffset++] = 1;
-			if (problemLine == 0) {
-				problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
-			}
-			// first entry at pc = 0
-			this.contents[localContentsOffset++] = 0;
-			this.contents[localContentsOffset++] = 0;
-			this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
-			this.contents[localContentsOffset++] = (byte) problemLine;
-			// now we change the size of the line number attribute
-			attributeNumber++;
-		}
-		
-		// then we do the local variable attribute
-		// update the number of attributes// ensure first that there is enough space available inside the localContents array
-		if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
-			resizeContents(2);
-		}
-		this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
-		this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
-		// update the attribute length
-		int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
-		this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
-		this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
-		this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
-		this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
-		contentsOffset = localContentsOffset;
-	}
-
-	/**
-	 * INTERNAL USE-ONLY
-	 * Generate the byte for a problem method info that correspond to a synthetic method that
-	 * generate an access to a private constructor.
+	 * Generate the bytes for a synthetic method that provides an access to a private constructor.
 	 *
 	 * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
 	 */
-	public void addSyntheticConstructorAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+	public void addSyntheticConstructorAccessMethod(SyntheticMethodBinding methodBinding) {
 		generateMethodInfoHeader(methodBinding);
 		// We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
 		contents[contentsOffset++] = 0;
@@ -970,7 +1264,7 @@
 		generateCodeAttributeHeader();
 		codeStream.init(this);
 		codeStream.generateSyntheticBodyForConstructorAccess(methodBinding);
-		completeCodeAttributeForSyntheticAccessMethod(
+		completeCodeAttributeForSyntheticMethod(
 			methodBinding,
 			codeAttributeOffset,
 			((SourceTypeBinding) methodBinding.declaringClass)
@@ -992,12 +1286,88 @@
 
 	/**
 	 * INTERNAL USE-ONLY
+	 *  Generate the bytes for a synthetic method that implements Enum#valueOf(String) for a given enum type
+	 *
+	 * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+	 */	
+	public void addSyntheticEnumValueOfMethod(SyntheticMethodBinding methodBinding) {
+
+		generateMethodInfoHeader(methodBinding);
+		// We know that we won't get more than 1 attribute: the code attribute 
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 1;
+		// Code attribute
+		int codeAttributeOffset = contentsOffset;
+		generateCodeAttributeHeader();
+		codeStream.init(this);
+		codeStream.generateSyntheticBodyForEnumValueOf(methodBinding);
+		completeCodeAttributeForSyntheticMethod(
+			methodBinding,
+			codeAttributeOffset,
+			((SourceTypeBinding) methodBinding.declaringClass)
+				.scope
+				.referenceCompilationUnit()
+				.compilationResult
+				.lineSeparatorPositions);
+//		// add the synthetic attribute
+//		int syntheticAttributeNameIndex =
+//			constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+//		contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+//		contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+//		// the length of a synthetic attribute is equals to 0
+//		contents[contentsOffset++] = 0;
+//		contents[contentsOffset++] = 0;
+//		contents[contentsOffset++] = 0;
+//		contents[contentsOffset++] = 0;
+			
+	}
+
+	/**
+	 * INTERNAL USE-ONLY
+	 *  Generate the bytes for a synthetic method that implements Enum#values() for a given enum type
+	 *
+	 * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+	 */	
+	public void addSyntheticEnumValuesMethod(SyntheticMethodBinding methodBinding) {
+
+		generateMethodInfoHeader(methodBinding);
+		// We know that we won't get more than 1 attribute: the code attribute 
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 1;
+		// Code attribute
+		int codeAttributeOffset = contentsOffset;
+		generateCodeAttributeHeader();
+		codeStream.init(this);
+		codeStream.generateSyntheticBodyForEnumValues(methodBinding);
+		completeCodeAttributeForSyntheticMethod(
+			methodBinding,
+			codeAttributeOffset,
+			((SourceTypeBinding) methodBinding.declaringClass)
+				.scope
+				.referenceCompilationUnit()
+				.compilationResult
+				.lineSeparatorPositions);
+//		// add the synthetic attribute
+//		int syntheticAttributeNameIndex =
+//			constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+//		contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+//		contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+//		// the length of a synthetic attribute is equals to 0
+//		contents[contentsOffset++] = 0;
+//		contents[contentsOffset++] = 0;
+//		contents[contentsOffset++] = 0;
+//		contents[contentsOffset++] = 0;
+			
+	}
+
+	/**
+	 * INTERNAL USE-ONLY
 	 * Generate the byte for a problem method info that correspond to a synthetic method that
 	 * generate an read access to a private field.
 	 *
 	 * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
 	 */
-	public void addSyntheticFieldReadAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+	public void addSyntheticFieldReadAccessMethod(SyntheticMethodBinding methodBinding) {
 		generateMethodInfoHeader(methodBinding);
 		// We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
 		contents[contentsOffset++] = 0;
@@ -1007,7 +1377,7 @@
 		generateCodeAttributeHeader();
 		codeStream.init(this);
 		codeStream.generateSyntheticBodyForFieldReadAccess(methodBinding);
-		completeCodeAttributeForSyntheticAccessMethod(
+		completeCodeAttributeForSyntheticMethod(
 			methodBinding,
 			codeAttributeOffset,
 			((SourceTypeBinding) methodBinding.declaringClass)
@@ -1034,7 +1404,7 @@
 	 *
 	 * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
 	 */
-	public void addSyntheticFieldWriteAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+	public void addSyntheticFieldWriteAccessMethod(SyntheticMethodBinding methodBinding) {
 		generateMethodInfoHeader(methodBinding);
 		// We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
 		contents[contentsOffset++] = 0;
@@ -1044,7 +1414,7 @@
 		generateCodeAttributeHeader();
 		codeStream.init(this);
 		codeStream.generateSyntheticBodyForFieldWriteAccess(methodBinding);
-		completeCodeAttributeForSyntheticAccessMethod(
+		completeCodeAttributeForSyntheticMethod(
 			methodBinding,
 			codeAttributeOffset,
 			((SourceTypeBinding) methodBinding.declaringClass)
@@ -1066,12 +1436,11 @@
 
 	/**
 	 * INTERNAL USE-ONLY
-	 * Generate the byte for a problem method info that correspond to a synthetic method that
-	 * generate an access to a private method.
+	 * Generate the bytes for a synthetic method that provides access to a private method.
 	 *
 	 * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
 	 */
-	public void addSyntheticMethodAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+	public void addSyntheticMethodAccessMethod(SyntheticMethodBinding methodBinding) {
 		generateMethodInfoHeader(methodBinding);
 		// We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
 		contents[contentsOffset++] = 0;
@@ -1081,7 +1450,7 @@
 		generateCodeAttributeHeader();
 		codeStream.init(this);
 		codeStream.generateSyntheticBodyForMethodAccess(methodBinding);
-		completeCodeAttributeForSyntheticAccessMethod(
+		completeCodeAttributeForSyntheticMethod(
 			methodBinding,
 			codeAttributeOffset,
 			((SourceTypeBinding) methodBinding.declaringClass)
@@ -1103,69 +1472,6 @@
 
 	/**
 	 * INTERNAL USE-ONLY
-	 * Build all the directories and subdirectories corresponding to the packages names
-	 * into the directory specified in parameters.
-	 *
-	 * outputPath is formed like:
-	 *	   c:\temp\ the last character is a file separator
-	 * relativeFileName is formed like:
-	 *     java\lang\String.class *
-	 * 
-	 * @param outputPath java.lang.String
-	 * @param relativeFileName java.lang.String
-	 * @return java.lang.String
-	 */
-	public static String buildAllDirectoriesInto(
-		String outputPath,
-		String relativeFileName)
-		throws IOException {
-		char fileSeparatorChar = File.separatorChar;
-		String fileSeparator = File.separator;
-		File f;
-		// First we ensure that the outputPath exists
-		outputPath = outputPath.replace('/', fileSeparatorChar);
-		// To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
-		if (outputPath.endsWith(fileSeparator)) {
-			outputPath = outputPath.substring(0, outputPath.length() - 1);
-		}
-		f = new File(outputPath);
-		if (f.exists()) {
-			if (!f.isDirectory()) {
-				System.out.println(Util.bind("output.isFile" , f.getAbsolutePath())); //$NON-NLS-1$
-				throw new IOException(Util.bind("output.isFileNotDirectory" )); //$NON-NLS-1$
-			}
-		} else {
-			// we have to create that directory
-			if (!f.mkdirs()) {
-				System.out.println(Util.bind("output.dirName" , f.getAbsolutePath())); //$NON-NLS-1$
-				throw new IOException(Util.bind("output.notValidAll" )); //$NON-NLS-1$
-			}
-		}
-		StringBuffer outDir = new StringBuffer(outputPath);
-		outDir.append(fileSeparator);
-		StringTokenizer tokenizer =
-			new StringTokenizer(relativeFileName, fileSeparator);
-		String token = tokenizer.nextToken();
-		while (tokenizer.hasMoreTokens()) {
-			f = new File(outDir.append(token).append(fileSeparator).toString());
-			if (f.exists()) {
-				// The outDir already exists, so we proceed the next entry
-				// System.out.println("outDir: " + outDir + " already exists.");
-			} else {
-				// Need to add the outDir
-				if (!f.mkdir()) {
-					System.out.println(Util.bind("output.fileName" , f.getName())); //$NON-NLS-1$
-					throw new IOException(Util.bind("output.notValid" )); //$NON-NLS-1$
-				}
-			}
-			token = tokenizer.nextToken();
-		}
-		// token contains the last one
-		return outDir.append(token).toString();
-	}
-
-	/**
-	 * INTERNAL USE-ONLY
 	 * That method completes the creation of the code attribute by setting
 	 * - the attribute_length
 	 * - max_stack
@@ -1204,7 +1510,7 @@
 		this.contents[codeAttributeOffset + 13] = (byte) code_length;
 
 		// write the exception table
-		int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
+		int exceptionHandlersNumber = codeStream.exceptionHandlersCounter;
 		ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
 		int exSize = exceptionHandlersNumber * 8 + 2;
 		if (exSize + localContentsOffset >= this.contents.length) {
@@ -1214,31 +1520,33 @@
 		// on the attribute generation
 		this.contents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
 		this.contents[localContentsOffset++] = (byte) exceptionHandlersNumber;
-		for (int i = 0; i < exceptionHandlersNumber; i++) {
+		for (int i = 0, max = codeStream.exceptionHandlersIndex; i < max; i++) {
 			ExceptionLabel exceptionHandler = exceptionHandlers[i];
-			int start = exceptionHandler.start;
-			this.contents[localContentsOffset++] = (byte) (start >> 8);
-			this.contents[localContentsOffset++] = (byte) start;
-			int end = exceptionHandler.end;
-			this.contents[localContentsOffset++] = (byte) (end >> 8);
-			this.contents[localContentsOffset++] = (byte) end;
-			int handlerPC = exceptionHandler.position;
-			this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
-			this.contents[localContentsOffset++] = (byte) handlerPC;
-			if (exceptionHandler.exceptionType == null) {
-				// any exception handler
-				this.contents[localContentsOffset++] = 0;
-				this.contents[localContentsOffset++] = 0;
-			} else {
-				int nameIndex;
-				if (exceptionHandler.exceptionType == BaseTypes.NullBinding) {
-					/* represents ClassNotFoundException, see class literal access*/
-					nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
+			if (exceptionHandler != null) {
+				int start = exceptionHandler.start;
+				this.contents[localContentsOffset++] = (byte) (start >> 8);
+				this.contents[localContentsOffset++] = (byte) start;
+				int end = exceptionHandler.end;
+				this.contents[localContentsOffset++] = (byte) (end >> 8);
+				this.contents[localContentsOffset++] = (byte) end;
+				int handlerPC = exceptionHandler.position;
+				this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
+				this.contents[localContentsOffset++] = (byte) handlerPC;
+				if (exceptionHandler.exceptionType == null) {
+					// any exception handler
+					this.contents[localContentsOffset++] = 0;
+					this.contents[localContentsOffset++] = 0;
 				} else {
-					nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
+					int nameIndex;
+					if (exceptionHandler.exceptionType == BaseTypes.NullBinding) {
+						/* represents ClassNotFoundException, see class literal access*/
+						nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
+					} else {
+						nameIndex = constantPool.literalIndexForType(exceptionHandler.exceptionType.constantPoolName());
+					}
+					this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+					this.contents[localContentsOffset++] = (byte) nameIndex;
 				}
-				this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
-				this.contents[localContentsOffset++] = (byte) nameIndex;
 			}
 		}
 		// debug attributes
@@ -1300,8 +1608,14 @@
 			int numberOfEntries = 0;
 			int localVariableNameIndex =
 				constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
-			if (localContentsOffset + 8 >= this.contents.length) {
-				resizeContents(8);
+			final boolean methodDeclarationIsStatic = codeStream.methodDeclaration.isStatic();
+			int maxOfEntries = 8 + 10 * (methodDeclarationIsStatic ? 0 : 1);
+			for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+				maxOfEntries += 10 * codeStream.locals[i].initializationCount;
+			}
+			// reserve enough space
+			if (localContentsOffset + maxOfEntries >= this.contents.length) {
+				resizeContents(maxOfEntries);
 			}
 			this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
 			this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
@@ -1309,28 +1623,41 @@
 			// leave space for attribute_length and local_variable_table_length
 			int nameIndex;
 			int descriptorIndex;
-			if (!codeStream.methodDeclaration.isStatic()) {
+			SourceTypeBinding declaringClassBinding = null;
+			if (!methodDeclarationIsStatic) {
 				numberOfEntries++;
-				if (localContentsOffset + 10 >= this.contents.length) {
-					resizeContents(10);
-				}
 				this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
 				this.contents[localContentsOffset++] = 0;
 				this.contents[localContentsOffset++] = (byte) (code_length >> 8);
 				this.contents[localContentsOffset++] = (byte) code_length;
-				nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
+				nameIndex = constantPool.literalIndex(ConstantPool.This);
 				this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
 				this.contents[localContentsOffset++] = (byte) nameIndex;
+				declaringClassBinding = (SourceTypeBinding) codeStream.methodDeclaration.binding.declaringClass;
 				descriptorIndex =
 					constantPool.literalIndex(
-						codeStream.methodDeclaration.binding.declaringClass.signature());
+						declaringClassBinding.signature());
 				this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
 				this.contents[localContentsOffset++] = (byte) descriptorIndex;
 				this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
 				this.contents[localContentsOffset++] = 0;
 			}
-			for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+			// used to remember the local variable with a generic type
+			int genericLocalVariablesCounter = 0;
+			LocalVariableBinding[] genericLocalVariables = null;
+			int numberOfGenericEntries = 0;
+			
+			for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
 				LocalVariableBinding localVariable = codeStream.locals[i];
+				final TypeBinding localVariableTypeBinding = localVariable.type;
+				boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
+				if (localVariable.initializationCount != 0 && isParameterizedType) {
+					if (genericLocalVariables == null) {
+						// we cannot have more than max locals
+						genericLocalVariables = new LocalVariableBinding[max];
+					}
+					genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
+				}
 				for (int j = 0; j < localVariable.initializationCount; j++) {
 					int startPC = localVariable.initializationPCs[j << 1];
 					int endPC = localVariable.initializationPCs[(j << 1) + 1];
@@ -1340,8 +1667,8 @@
 								Util.bind("abort.invalidAttribute" , new String(localVariable.name)), //$NON-NLS-1$
 								(ASTNode) localVariable.declaringScope.methodScope().referenceContext);
 						}
-						if (localContentsOffset + 10 >= this.contents.length) {
-							resizeContents(10);
+						if (isParameterizedType) {
+							numberOfGenericEntries++;
 						}
 						// now we can safely add the local entry
 						numberOfEntries++;
@@ -1353,7 +1680,7 @@
 						nameIndex = constantPool.literalIndex(localVariable.name);
 						this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
 						this.contents[localContentsOffset++] = (byte) nameIndex;
-						descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+						descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
 						this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
 						this.contents[localContentsOffset++] = (byte) descriptorIndex;
 						int resolvedPosition = localVariable.resolvedPosition;
@@ -1371,6 +1698,72 @@
 			this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
 			this.contents[localVariableTableOffset] = (byte) numberOfEntries;
 			attributeNumber++;
+			
+			final boolean currentInstanceIsGeneric = 
+				!methodDeclarationIsStatic
+				&& declaringClassBinding != null 
+				&& declaringClassBinding.typeVariables != NoTypeVariables;
+			if (genericLocalVariablesCounter != 0 || currentInstanceIsGeneric) {
+				// add the local variable type table attribute
+				numberOfGenericEntries += (currentInstanceIsGeneric ? 1 : 0);
+				maxOfEntries = 8 + numberOfGenericEntries * 10;
+				// reserve enough space
+				if (localContentsOffset + maxOfEntries >= this.contents.length) {
+					resizeContents(maxOfEntries);
+				}
+				int localVariableTypeNameIndex =
+					constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
+				this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
+				this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
+				value = numberOfGenericEntries * 10 + 2;
+				this.contents[localContentsOffset++] = (byte) (value >> 24);
+				this.contents[localContentsOffset++] = (byte) (value >> 16);
+				this.contents[localContentsOffset++] = (byte) (value >> 8);
+				this.contents[localContentsOffset++] = (byte) value;
+				this.contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
+				this.contents[localContentsOffset++] = (byte) numberOfGenericEntries;
+				if (currentInstanceIsGeneric) {
+					this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
+					this.contents[localContentsOffset++] = 0;
+					this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+					this.contents[localContentsOffset++] = (byte) code_length;
+					nameIndex = constantPool.literalIndex(ConstantPool.This);
+					this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+					this.contents[localContentsOffset++] = (byte) nameIndex;
+					descriptorIndex = constantPool.literalIndex(declaringClassBinding.genericTypeSignature());
+					this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+					this.contents[localContentsOffset++] = (byte) descriptorIndex;
+					this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
+					this.contents[localContentsOffset++] = 0;
+				}
+				
+				for (int i = 0; i < genericLocalVariablesCounter; i++) {
+					LocalVariableBinding localVariable = genericLocalVariables[i];
+					for (int j = 0; j < localVariable.initializationCount; j++) {
+						int startPC = localVariable.initializationPCs[j << 1];
+						int endPC = localVariable.initializationPCs[(j << 1) + 1];
+						if (startPC != endPC) {
+							// only entries for non zero length
+							// now we can safely add the local entry
+							this.contents[localContentsOffset++] = (byte) (startPC >> 8);
+							this.contents[localContentsOffset++] = (byte) startPC;
+							int length = endPC - startPC;
+							this.contents[localContentsOffset++] = (byte) (length >> 8);
+							this.contents[localContentsOffset++] = (byte) length;
+							nameIndex = constantPool.literalIndex(localVariable.name);
+							this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+							this.contents[localContentsOffset++] = (byte) nameIndex;
+							descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
+							this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+							this.contents[localContentsOffset++] = (byte) descriptorIndex;
+							int resolvedPosition = localVariable.resolvedPosition;
+							this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+							this.contents[localContentsOffset++] = (byte) resolvedPosition;
+						}
+					}
+				}
+				attributeNumber++;
+			}
 		}
 		// update the number of attributes
 		// ensure first that there is enough space available inside the localContents array
@@ -1429,7 +1822,7 @@
 		this.contents[codeAttributeOffset + 13] = (byte) code_length;
 
 		// write the exception table
-		int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
+		int exceptionHandlersNumber = codeStream.exceptionHandlersCounter;
 		ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
 		int exSize = exceptionHandlersNumber * 8 + 2;
 		if (exSize + localContentsOffset >= this.contents.length) {
@@ -1439,31 +1832,33 @@
 		// on the attribute generation
 		this.contents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
 		this.contents[localContentsOffset++] = (byte) exceptionHandlersNumber;
-		for (int i = 0; i < exceptionHandlersNumber; i++) {
+		for (int i = 0, max = codeStream.exceptionHandlersIndex; i < max; i++) {
 			ExceptionLabel exceptionHandler = exceptionHandlers[i];
-			int start = exceptionHandler.start;
-			this.contents[localContentsOffset++] = (byte) (start >> 8);
-			this.contents[localContentsOffset++] = (byte) start;
-			int end = exceptionHandler.end;
-			this.contents[localContentsOffset++] = (byte) (end >> 8);
-			this.contents[localContentsOffset++] = (byte) end;
-			int handlerPC = exceptionHandler.position;
-			this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
-			this.contents[localContentsOffset++] = (byte) handlerPC;
-			if (exceptionHandler.exceptionType == null) {
-				// any exception handler
-				this.contents[localContentsOffset++] = 0;
-				this.contents[localContentsOffset++] = 0;
-			} else {
-				int nameIndex;
-				if (exceptionHandler.exceptionType == BaseTypes.NullBinding) {
-					/* represents denote ClassNotFoundException, see class literal access*/
-					nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
+			if (exceptionHandler != null) {
+				int start = exceptionHandler.start;
+				this.contents[localContentsOffset++] = (byte) (start >> 8);
+				this.contents[localContentsOffset++] = (byte) start;
+				int end = exceptionHandler.end;
+				this.contents[localContentsOffset++] = (byte) (end >> 8);
+				this.contents[localContentsOffset++] = (byte) end;
+				int handlerPC = exceptionHandler.position;
+				this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
+				this.contents[localContentsOffset++] = (byte) handlerPC;
+				if (exceptionHandler.exceptionType == null) {
+					// any exception handler
+					this.contents[localContentsOffset++] = 0;
+					this.contents[localContentsOffset++] = 0;
 				} else {
-					nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
+					int nameIndex;
+					if (exceptionHandler.exceptionType == BaseTypes.NullBinding) {
+						/* represents denote ClassNotFoundException, see class literal access*/
+						nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
+					} else {
+						nameIndex = constantPool.literalIndexForType(exceptionHandler.exceptionType.constantPoolName());
+					}
+					this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+					this.contents[localContentsOffset++] = (byte) nameIndex;
 				}
-				this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
-				this.contents[localContentsOffset++] = (byte) nameIndex;
 			}
 		}
 		// debug attributes
@@ -1534,11 +1929,27 @@
 				this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
 				this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
 				localContentsOffset += 6;
+
 				// leave space for attribute_length and local_variable_table_length
 				int nameIndex;
 				int descriptorIndex;
-				for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+
+				// used to remember the local variable with a generic type
+				int genericLocalVariablesCounter = 0;
+				LocalVariableBinding[] genericLocalVariables = null;
+				int numberOfGenericEntries = 0;
+
+				for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
 					LocalVariableBinding localVariable = codeStream.locals[i];
+					final TypeBinding localVariableTypeBinding = localVariable.type;
+					boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
+					if (localVariable.initializationCount != 0 && isParameterizedType) {
+						if (genericLocalVariables == null) {
+							// we cannot have more than max locals
+							genericLocalVariables = new LocalVariableBinding[max];
+						}
+						genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
+					}
 					for (int j = 0; j < localVariable.initializationCount; j++) {
 						int startPC = localVariable.initializationPCs[j << 1];
 						int endPC = localVariable.initializationPCs[(j << 1) + 1];
@@ -1553,6 +1964,9 @@
 							}
 							// now we can safely add the local entry
 							numberOfEntries++;
+							if (isParameterizedType) {
+								numberOfGenericEntries++;
+							}
 							this.contents[localContentsOffset++] = (byte) (startPC >> 8);
 							this.contents[localContentsOffset++] = (byte) startPC;
 							int length = endPC - startPC;
@@ -1561,7 +1975,7 @@
 							nameIndex = constantPool.literalIndex(localVariable.name);
 							this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
 							this.contents[localContentsOffset++] = (byte) nameIndex;
-							descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+							descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
 							this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
 							this.contents[localContentsOffset++] = (byte) descriptorIndex;
 							int resolvedPosition = localVariable.resolvedPosition;
@@ -1579,6 +1993,52 @@
 				this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
 				this.contents[localVariableTableOffset] = (byte) numberOfEntries;
 				attributeNumber++;
+
+				if (genericLocalVariablesCounter != 0) {
+					// add the local variable type table attribute
+					// reserve enough space
+					int maxOfEntries = 8 + numberOfGenericEntries * 10;
+
+					if (localContentsOffset + maxOfEntries >= this.contents.length) {
+						resizeContents(maxOfEntries);
+					}
+					int localVariableTypeNameIndex =
+						constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
+					this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
+					this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
+					value = numberOfGenericEntries * 10 + 2;
+					this.contents[localContentsOffset++] = (byte) (value >> 24);
+					this.contents[localContentsOffset++] = (byte) (value >> 16);
+					this.contents[localContentsOffset++] = (byte) (value >> 8);
+					this.contents[localContentsOffset++] = (byte) value;
+					this.contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
+					this.contents[localContentsOffset++] = (byte) numberOfGenericEntries;
+					for (int i = 0; i < genericLocalVariablesCounter; i++) {
+						LocalVariableBinding localVariable = genericLocalVariables[i];
+						for (int j = 0; j < localVariable.initializationCount; j++) {
+							int startPC = localVariable.initializationPCs[j << 1];
+							int endPC = localVariable.initializationPCs[(j << 1) + 1];
+							if (startPC != endPC) { // only entries for non zero length
+								// now we can safely add the local entry
+								this.contents[localContentsOffset++] = (byte) (startPC >> 8);
+								this.contents[localContentsOffset++] = (byte) startPC;
+								int length = endPC - startPC;
+								this.contents[localContentsOffset++] = (byte) (length >> 8);
+								this.contents[localContentsOffset++] = (byte) length;
+								nameIndex = constantPool.literalIndex(localVariable.name);
+								this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+								this.contents[localContentsOffset++] = (byte) nameIndex;
+								descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
+								this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+								this.contents[localContentsOffset++] = (byte) descriptorIndex;
+								int resolvedPosition = localVariable.resolvedPosition;
+								this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+								this.contents[localContentsOffset++] = (byte) resolvedPosition;
+							}
+						}
+					}
+					attributeNumber++;
+				}
 			}
 		}
 		// update the number of attributes
@@ -1612,7 +2072,8 @@
 	 */
 	public void completeCodeAttributeForClinit(
 		int codeAttributeOffset,
-		int[] startLineIndexes) {
+		int[] startLineIndexes,
+		int problemLine) {
 		// reinitialize the contents with the byte modified by the code stream
 		this.contents = codeStream.bCodeStream;
 		int localContentsOffset = codeStream.classFileOffset;
@@ -1711,6 +2172,85 @@
 	}
 
 	/**
+	 * 
+	 */
+	public void completeCodeAttributeForMissingAbstractProblemMethod(
+		MethodBinding binding,
+		int codeAttributeOffset,
+		int[] startLineIndexes,
+		int problemLine) {
+		// reinitialize the localContents with the byte modified by the code stream
+		this.contents = codeStream.bCodeStream;
+		int localContentsOffset = codeStream.classFileOffset;
+		// codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc...
+		int max_stack = codeStream.stackMax;
+		this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+		this.contents[codeAttributeOffset + 7] = (byte) max_stack;
+		int max_locals = codeStream.maxLocals;
+		this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+		this.contents[codeAttributeOffset + 9] = (byte) max_locals;
+		int code_length = codeStream.position;
+		this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+		this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+		this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+		this.contents[codeAttributeOffset + 13] = (byte) code_length;
+		// write the exception table
+		if (localContentsOffset + 50 >= this.contents.length) {
+			resizeContents(50);
+		}
+		this.contents[localContentsOffset++] = 0;
+		this.contents[localContentsOffset++] = 0;
+		// debug attributes
+		int codeAttributeAttributeOffset = localContentsOffset;
+		int attributeNumber = 0; // leave two bytes for the attribute_length
+		localContentsOffset += 2; // first we handle the linenumber attribute
+
+		if (codeStream.generateLineNumberAttributes) {
+			/* Create and add the line number attribute (used for debugging) 
+			    * Build the pairs of:
+			    * (bytecodePC lineNumber)
+			    * according to the table of start line indexes and the pcToSourceMap table
+			    * contained into the codestream
+			    */
+			int lineNumberNameIndex =
+				constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+			this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+			this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
+			this.contents[localContentsOffset++] = 0;
+			this.contents[localContentsOffset++] = 0;
+			this.contents[localContentsOffset++] = 0;
+			this.contents[localContentsOffset++] = 6;
+			this.contents[localContentsOffset++] = 0;
+			this.contents[localContentsOffset++] = 1;
+			if (problemLine == 0) {
+				problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
+			}
+			// first entry at pc = 0
+			this.contents[localContentsOffset++] = 0;
+			this.contents[localContentsOffset++] = 0;
+			this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
+			this.contents[localContentsOffset++] = (byte) problemLine;
+			// now we change the size of the line number attribute
+			attributeNumber++;
+		}
+		
+		// then we do the local variable attribute
+		// update the number of attributes// ensure first that there is enough space available inside the localContents array
+		if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
+			resizeContents(2);
+		}
+		this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+		this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+		// update the attribute length
+		int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+		this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+		this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+		this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+		this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+		contentsOffset = localContentsOffset;
+	}
+
+	/**
 	 * INTERNAL USE-ONLY
 	 * That method completes the creation of the code attribute by setting
 	 * - the attribute_length
@@ -1726,7 +2266,8 @@
 		AbstractMethodDeclaration method,
 		MethodBinding binding,
 		int codeAttributeOffset,
-		int[] startLineIndexes) {
+		int[] startLineIndexes,
+		int problemLine) {
 		// reinitialize the localContents with the byte modified by the code stream
 		this.contents = codeStream.bCodeStream;
 		int localContentsOffset = codeStream.classFileOffset;
@@ -1803,7 +2344,10 @@
 			localContentsOffset += 6;
 			// leave space for attribute_length and local_variable_table_length
 			int descriptorIndex;
-			if (!codeStream.methodDeclaration.isStatic()) {
+			int nameIndex;
+			SourceTypeBinding declaringClassBinding = null;
+			final boolean methodDeclarationIsStatic = codeStream.methodDeclaration.isStatic();
+			if (!methodDeclarationIsStatic) {
 				numberOfEntries++;
 				if (localContentsOffset + 10 >= this.contents.length) {
 					resizeContents(10);
@@ -1812,28 +2356,41 @@
 				this.contents[localContentsOffset++] = 0;
 				this.contents[localContentsOffset++] = (byte) (code_length >> 8);
 				this.contents[localContentsOffset++] = (byte) code_length;
-				int nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
+				nameIndex = constantPool.literalIndex(ConstantPool.This);
 				this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
 				this.contents[localContentsOffset++] = (byte) nameIndex;
+				declaringClassBinding = (SourceTypeBinding) codeStream.methodDeclaration.binding.declaringClass;
 				descriptorIndex =
-					constantPool.literalIndex(
-						codeStream.methodDeclaration.binding.declaringClass.signature());
+					constantPool.literalIndex(declaringClassBinding.signature());
 				this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
 				this.contents[localContentsOffset++] = (byte) descriptorIndex;
 				// the resolved position for this is always 0
 				this.contents[localContentsOffset++] = 0;
 				this.contents[localContentsOffset++] = 0;
 			}
+			// used to remember the local variable with a generic type
+			int genericLocalVariablesCounter = 0;
+			LocalVariableBinding[] genericLocalVariables = null;
+			int numberOfGenericEntries = 0;
+			
 			if (binding.isConstructor()) {
 				ReferenceBinding declaringClass = binding.declaringClass;
 				if (declaringClass.isNestedType()) {
 					NestedTypeBinding methodDeclaringClass = (NestedTypeBinding) declaringClass;
 					argSize = methodDeclaringClass.enclosingInstancesSlotSize;
 					SyntheticArgumentBinding[] syntheticArguments;
-					if ((syntheticArguments = methodDeclaringClass.syntheticEnclosingInstances())
-						!= null) {
+					if ((syntheticArguments = methodDeclaringClass.syntheticEnclosingInstances()) != null) {
 						for (int i = 0, max = syntheticArguments.length; i < max; i++) {
 							LocalVariableBinding localVariable = syntheticArguments[i];
+							final TypeBinding localVariableTypeBinding = localVariable.type;
+							if (localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable()) {
+								if (genericLocalVariables == null) {
+									// we cannot have more than max locals
+									genericLocalVariables = new LocalVariableBinding[max];
+								}
+								genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
+								numberOfGenericEntries++;								
+							}
 							if (localContentsOffset + 10 >= this.contents.length) {
 								resizeContents(10);
 							}
@@ -1843,10 +2400,10 @@
 							this.contents[localContentsOffset++] = 0;
 							this.contents[localContentsOffset++] = (byte) (code_length >> 8);
 							this.contents[localContentsOffset++] = (byte) code_length;
-							int nameIndex = constantPool.literalIndex(localVariable.name);
+							nameIndex = constantPool.literalIndex(localVariable.name);
 							this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
 							this.contents[localContentsOffset++] = (byte) nameIndex;
-							descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+							descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
 							this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
 							this.contents[localContentsOffset++] = (byte) descriptorIndex;
 							int resolvedPosition = localVariable.resolvedPosition;
@@ -1860,6 +2417,12 @@
 			} else {
 				argSize = binding.isStatic() ? 0 : 1;
 			}
+			
+			int genericArgumentsCounter = 0;
+			int[] genericArgumentsNameIndexes = null;
+			int[] genericArgumentsResolvedPositions = null;
+			TypeBinding[] genericArgumentsTypeBindings = null;
+
 			if (method.binding != null) {
 				TypeBinding[] parameters = method.binding.parameters;
 				Argument[] arguments = method.arguments;
@@ -1875,13 +2438,24 @@
 						this.contents[localContentsOffset++] = 0;
 						this.contents[localContentsOffset++] = (byte) (code_length >> 8);
 						this.contents[localContentsOffset++] = (byte) code_length;
-						int nameIndex = constantPool.literalIndex(arguments[i].name);
+						nameIndex = constantPool.literalIndex(arguments[i].name);
 						this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
 						this.contents[localContentsOffset++] = (byte) nameIndex;
+						int resolvedPosition = argSize;
+						if (argumentBinding.isParameterizedType() || argumentBinding.isTypeVariable()) {
+							if (genericArgumentsCounter == 0) {
+								// we cannot have more than max locals
+								genericArgumentsNameIndexes = new int[max];
+								genericArgumentsResolvedPositions = new int[max];
+								genericArgumentsTypeBindings = new TypeBinding[max];
+							}
+							genericArgumentsNameIndexes[genericArgumentsCounter] = nameIndex;
+							genericArgumentsResolvedPositions[genericArgumentsCounter] = resolvedPosition;
+							genericArgumentsTypeBindings[genericArgumentsCounter++] = argumentBinding;
+						}
 						descriptorIndex = constantPool.literalIndex(argumentBinding.signature());
 						this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
 						this.contents[localContentsOffset++] = (byte) descriptorIndex;
-						int resolvedPosition = argSize;
 						if ((argumentBinding == BaseTypes.LongBinding)
 							|| (argumentBinding == BaseTypes.DoubleBinding))
 							argSize += 2;
@@ -1901,6 +2475,79 @@
 			this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
 			this.contents[localVariableTableOffset] = (byte) numberOfEntries;
 			attributeNumber++;
+			
+			final boolean currentInstanceIsGeneric = 
+				!methodDeclarationIsStatic
+				&& declaringClassBinding != null
+				&& declaringClassBinding.typeVariables != NoTypeVariables;
+			if (genericLocalVariablesCounter != 0 || genericArgumentsCounter != 0 || currentInstanceIsGeneric) {
+				// add the local variable type table attribute
+				numberOfEntries = numberOfGenericEntries + genericArgumentsCounter + (currentInstanceIsGeneric ? 1 : 0);
+				// reserve enough space
+				int maxOfEntries = 8 + numberOfEntries * 10;
+				if (localContentsOffset + maxOfEntries >= this.contents.length) {
+					resizeContents(maxOfEntries);
+				}
+				int localVariableTypeNameIndex =
+					constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
+				this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
+				this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
+				value = numberOfEntries * 10 + 2;
+				this.contents[localContentsOffset++] = (byte) (value >> 24);
+				this.contents[localContentsOffset++] = (byte) (value >> 16);
+				this.contents[localContentsOffset++] = (byte) (value >> 8);
+				this.contents[localContentsOffset++] = (byte) value;
+				this.contents[localContentsOffset++] = (byte) (numberOfEntries >> 8);
+				this.contents[localContentsOffset++] = (byte) numberOfEntries;
+				if (currentInstanceIsGeneric) {
+					numberOfEntries++;
+					this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
+					this.contents[localContentsOffset++] = 0;
+					this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+					this.contents[localContentsOffset++] = (byte) code_length;
+					nameIndex = constantPool.literalIndex(ConstantPool.This);
+					this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+					this.contents[localContentsOffset++] = (byte) nameIndex;
+					descriptorIndex = constantPool.literalIndex(declaringClassBinding.genericTypeSignature());
+					this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+					this.contents[localContentsOffset++] = (byte) descriptorIndex;
+					this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
+					this.contents[localContentsOffset++] = 0;
+				}
+				
+				for (int i = 0; i < genericLocalVariablesCounter; i++) {
+					LocalVariableBinding localVariable = genericLocalVariables[i];
+					this.contents[localContentsOffset++] = 0;
+					this.contents[localContentsOffset++] = 0;
+					this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+					this.contents[localContentsOffset++] = (byte) code_length;
+					nameIndex = constantPool.literalIndex(localVariable.name);
+					this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+					this.contents[localContentsOffset++] = (byte) nameIndex;
+					descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
+					this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+					this.contents[localContentsOffset++] = (byte) descriptorIndex;
+					int resolvedPosition = localVariable.resolvedPosition;
+					this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+					this.contents[localContentsOffset++] = (byte) resolvedPosition;
+				}
+				for (int i = 0; i < genericArgumentsCounter; i++) {
+					this.contents[localContentsOffset++] = 0;
+					this.contents[localContentsOffset++] = 0;
+					this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+					this.contents[localContentsOffset++] = (byte) code_length;
+					nameIndex = genericArgumentsNameIndexes[i];
+					this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+					this.contents[localContentsOffset++] = (byte) nameIndex;
+					descriptorIndex = constantPool.literalIndex(genericArgumentsTypeBindings[i].genericTypeSignature());
+					this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+					this.contents[localContentsOffset++] = (byte) descriptorIndex;
+					int resolvedPosition = genericArgumentsResolvedPositions[i];
+					this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+					this.contents[localContentsOffset++] = (byte) resolvedPosition;
+				}				
+				attributeNumber++;
+			}			
 		}
 		// update the number of attributes// ensure first that there is enough space available inside the localContents array
 		if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
@@ -1930,8 +2577,8 @@
 	 * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
 	 * @param codeAttributeOffset <CODE>int</CODE>
 	 */
-	public void completeCodeAttributeForSyntheticAccessMethod(
-		SyntheticAccessMethodBinding binding,
+	public void completeCodeAttributeForSyntheticMethod(
+		SyntheticMethodBinding binding,
 		int codeAttributeOffset,
 		int[] startLineIndexes) {
 		// reinitialize the contents with the byte modified by the code stream
@@ -2005,8 +2652,23 @@
 			// leave space for attribute_length and local_variable_table_length
 			int nameIndex;
 			int descriptorIndex;
-			for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+
+			// used to remember the local variable with a generic type
+			int genericLocalVariablesCounter = 0;
+			LocalVariableBinding[] genericLocalVariables = null;
+			int numberOfGenericEntries = 0;
+			
+			for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
 				LocalVariableBinding localVariable = codeStream.locals[i];
+				final TypeBinding localVariableTypeBinding = localVariable.type;
+				boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
+				if (localVariable.initializationCount != 0 && isParameterizedType) {
+					if (genericLocalVariables == null) {
+						// we cannot have more than max locals
+						genericLocalVariables = new LocalVariableBinding[max];
+					}
+					genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
+				}
 				for (int j = 0; j < localVariable.initializationCount; j++) {
 					int startPC = localVariable.initializationPCs[j << 1];
 					int endPC = localVariable.initializationPCs[(j << 1) + 1];
@@ -2021,6 +2683,9 @@
 						}
 						// now we can safely add the local entry
 						numberOfEntries++;
+						if (isParameterizedType) {
+							numberOfGenericEntries++;
+						}
 						contents[localContentsOffset++] = (byte) (startPC >> 8);
 						contents[localContentsOffset++] = (byte) startPC;
 						int length = endPC - startPC;
@@ -2029,7 +2694,7 @@
 						nameIndex = constantPool.literalIndex(localVariable.name);
 						contents[localContentsOffset++] = (byte) (nameIndex >> 8);
 						contents[localContentsOffset++] = (byte) nameIndex;
-						descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+						descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
 						contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
 						contents[localContentsOffset++] = (byte) descriptorIndex;
 						int resolvedPosition = localVariable.resolvedPosition;
@@ -2047,6 +2712,52 @@
 			contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
 			contents[localVariableTableOffset] = (byte) numberOfEntries;
 			attributeNumber++;
+
+			if (genericLocalVariablesCounter != 0) {
+				// add the local variable type table attribute
+				int maxOfEntries = 8 + numberOfGenericEntries * 10;
+				// reserve enough space
+				if (localContentsOffset + maxOfEntries >= this.contents.length) {
+					resizeContents(maxOfEntries);
+				}
+				int localVariableTypeNameIndex =
+					constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
+				contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
+				contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
+				value = numberOfGenericEntries * 10 + 2;
+				contents[localContentsOffset++] = (byte) (value >> 24);
+				contents[localContentsOffset++] = (byte) (value >> 16);
+				contents[localContentsOffset++] = (byte) (value >> 8);
+				contents[localContentsOffset++] = (byte) value;
+				contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
+				contents[localContentsOffset++] = (byte) numberOfGenericEntries;
+
+				for (int i = 0; i < genericLocalVariablesCounter; i++) {
+					LocalVariableBinding localVariable = genericLocalVariables[i];
+					for (int j = 0; j < localVariable.initializationCount; j++) {
+						int startPC = localVariable.initializationPCs[j << 1];
+						int endPC = localVariable.initializationPCs[(j << 1) + 1];
+						if (startPC != endPC) { // only entries for non zero length
+							// now we can safely add the local entry
+							contents[localContentsOffset++] = (byte) (startPC >> 8);
+							contents[localContentsOffset++] = (byte) startPC;
+							int length = endPC - startPC;
+							contents[localContentsOffset++] = (byte) (length >> 8);
+							contents[localContentsOffset++] = (byte) length;
+							nameIndex = constantPool.literalIndex(localVariable.name);
+							contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+							contents[localContentsOffset++] = (byte) nameIndex;
+							descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
+							contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+							contents[localContentsOffset++] = (byte) descriptorIndex;
+							int resolvedPosition = localVariable.resolvedPosition;
+							contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+							contents[localContentsOffset++] = (byte) resolvedPosition;
+						}
+					}
+				}
+				attributeNumber++;
+			}
 		}
 		// update the number of attributes
 		// ensure first that there is enough space available inside the contents array
@@ -2082,109 +2793,6 @@
 
 	/**
 	 * INTERNAL USE-ONLY
-	 * Request the creation of a ClassFile compatible representation of a problematic type
-	 *
-	 * @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
-	 * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
-	 */
-	public static void createProblemType(
-		TypeDeclaration typeDeclaration,
-		CompilationResult unitResult) {
-		SourceTypeBinding typeBinding = typeDeclaration.binding;
-		ClassFile classFile = new ClassFile(typeBinding, null, true);
-
-		// TODO (olivier) handle cases where a field cannot be generated (name too long)
-		// TODO (olivier) handle too many methods
-		// inner attributes
-		if (typeBinding.isMemberType())
-			classFile.recordEnclosingTypeAttributes(typeBinding);
-
-		// 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
-			classFile.contents[classFile.contentsOffset++] = 0;
-			classFile.contents[classFile.contentsOffset++] = 0;
-		}
-		// leave some space for the methodCount
-		classFile.setForMethodInfos();
-		// add its user defined methods
-		MethodBinding[] methods = typeBinding.methods;
-		AbstractMethodDeclaration[] methodDeclarations = typeDeclaration.methods;
-		int maxMethodDecl = methodDeclarations == null ? 0 : methodDeclarations.length;
-		int problemsLength;
-		IProblem[] problems = unitResult.getErrors();
-		if (problems == null) {
-			problems = new IProblem[0];
-		}
-		IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
-		System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
-		if (methods != null) {
-			if (typeBinding.isInterface()) {
-				// we cannot create problem methods for an interface. So we have to generate a clinit
-				// which should contain all the problem
-				classFile.addProblemClinit(problemsCopy);
-				for (int i = 0, max = methods.length; i < max; i++) {
-					MethodBinding methodBinding;
-					if ((methodBinding = methods[i]) != null) {
-						// find the corresponding method declaration
-						for (int j = 0; j < maxMethodDecl; j++) {
-							if ((methodDeclarations[j] != null)
-								&& (methodDeclarations[j].binding == methods[i])) {
-								if (!methodBinding.isConstructor()) {
-									classFile.addAbstractMethod(methodDeclarations[j], methodBinding);
-								}
-								break;
-							}
-						}
-					}
-				}
-			} else {
-				for (int i = 0, max = methods.length; i < max; i++) {
-					MethodBinding methodBinding;
-					if ((methodBinding = methods[i]) != null) {
-						// find the corresponding method declaration
-						for (int j = 0; j < maxMethodDecl; j++) {
-							if ((methodDeclarations[j] != null)
-								&& (methodDeclarations[j].binding == methods[i])) {
-								AbstractMethodDeclaration methodDecl;
-								if ((methodDecl = methodDeclarations[j]).isConstructor()) {
-									classFile.addProblemConstructor(methodDecl, methodBinding, problemsCopy);
-								} else {
-									classFile.addProblemMethod(methodDecl, methodBinding, problemsCopy);
-								}
-								break;
-							}
-						}
-					}
-				}
-			}
-			// add abstract methods
-			classFile.addDefaultAbstractMethods();
-		}
-		// propagate generation of (problem) member types
-		if (typeDeclaration.memberTypes != null) {
-			for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) {
-				TypeDeclaration memberType = typeDeclaration.memberTypes[i];
-				if (memberType.binding != null) {
-					classFile.recordNestedMemberAttribute(memberType.binding);
-					ClassFile.createProblemType(memberType, unitResult);
-				}
-			}
-		}
-		classFile.addAttributes();
-		unitResult.record(typeBinding.constantPoolName(), classFile);
-	}
-
-	/**
-	 * INTERNAL USE-ONLY
 	 * This methods returns a char[] representing the file name of the receiver
 	 *
 	 * @return char[]
@@ -2193,6 +2801,68 @@
 		return constantPool.UTF8Cache.returnKeyFor(1);
 	}
 
+	private void generateAnnotation(Annotation annotation, int attributeOffset) {
+		if (contentsOffset + 4 >= this.contents.length) {
+			resizeContents(4);
+		}
+		TypeBinding annotationTypeBinding = annotation.resolvedType;
+		if (annotationTypeBinding == null) {
+			this.contentsOffset = attributeOffset;
+			return;
+		}
+		final int typeIndex = constantPool.literalIndex(annotationTypeBinding.signature());
+		contents[contentsOffset++] = (byte) (typeIndex >> 8);
+		contents[contentsOffset++] = (byte) typeIndex;
+		if (annotation instanceof NormalAnnotation) {
+			NormalAnnotation normalAnnotation = (NormalAnnotation) annotation;
+			MemberValuePair[] memberValuePairs = normalAnnotation.memberValuePairs;
+			if (memberValuePairs != null) {
+				final int memberValuePairsLength = memberValuePairs.length;
+				contents[contentsOffset++] = (byte) (memberValuePairsLength >> 8);
+				contents[contentsOffset++] = (byte) memberValuePairsLength;
+				for (int i = 0; i < memberValuePairsLength; i++) {
+					MemberValuePair memberValuePair = memberValuePairs[i];
+					if (contentsOffset + 2 >= this.contents.length) {
+						resizeContents(2);
+					}
+					final int elementNameIndex = constantPool.literalIndex(memberValuePair.name);
+					contents[contentsOffset++] = (byte) (elementNameIndex >> 8);
+					contents[contentsOffset++] = (byte) elementNameIndex;
+					MethodBinding methodBinding = memberValuePair.binding;
+					if (methodBinding == null) {
+						contentsOffset = attributeOffset;
+					} else {
+						generateElementValue(memberValuePair.value, methodBinding.returnType, attributeOffset);
+					}
+				}
+			} else {
+				contents[contentsOffset++] = 0;
+				contents[contentsOffset++] = 0;
+			}
+		} else if (annotation instanceof SingleMemberAnnotation) {
+			SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) annotation;
+			// this is a single member annotation (one member value)
+			contents[contentsOffset++] = 0;
+			contents[contentsOffset++] = 1;
+			if (contentsOffset + 2 >= this.contents.length) {
+				resizeContents(2);
+			}
+			final int elementNameIndex = constantPool.literalIndex(VALUE);
+			contents[contentsOffset++] = (byte) (elementNameIndex >> 8);
+			contents[contentsOffset++] = (byte) elementNameIndex;
+			MethodBinding methodBinding = singleMemberAnnotation.singlePair.binding;
+			if (methodBinding == null) {
+				contentsOffset = attributeOffset;
+			} else {
+				generateElementValue(singleMemberAnnotation.memberValue, methodBinding.returnType, attributeOffset);
+			}
+		} else {
+			// this is a marker annotation (no member value pairs)
+			contents[contentsOffset++] = 0;
+			contents[contentsOffset++] = 0;
+		}
+	}
+
 	/**
 	 * INTERNAL USE-ONLY
 	 * That method generates the header of a code attribute.
@@ -2211,6 +2881,187 @@
 		contentsOffset += 12;
 	}
 
+	private void generateElementValue(
+			Expression defaultValue,
+			TypeBinding memberValuePairReturnType,
+			int attributeOffset) {
+		Constant constant = defaultValue.constant;
+		TypeBinding defaultValueBinding = defaultValue.resolvedType;
+		if (defaultValueBinding == null) {
+			contentsOffset = attributeOffset;
+		} else {
+			if (memberValuePairReturnType.isArrayType() && !defaultValueBinding.isArrayType()) {
+				// automatic wrapping
+				if (contentsOffset + 3 >= this.contents.length) {
+					resizeContents(3);
+				}
+				contents[contentsOffset++] = (byte) '[';
+				contents[contentsOffset++] = (byte) 0;
+				contents[contentsOffset++] = (byte) 1;
+			}
+			if (constant != null && constant != Constant.NotAConstant) {
+				generateElementValue(attributeOffset, defaultValue, constant, memberValuePairReturnType.leafComponentType());
+			} else {
+				generateElementValueForNonConstantExpression(defaultValue, attributeOffset, defaultValueBinding);
+			}
+		}
+	}
+
+	/**
+	 * @param attributeOffset
+	 */
+	private void generateElementValue(int attributeOffset, Expression defaultValue, Constant constant, TypeBinding binding) {
+		if (contentsOffset + 3 >= this.contents.length) {
+			resizeContents(3);
+		}
+		switch (binding.id) {
+			case T_boolean :
+				contents[contentsOffset++] = (byte) 'Z';
+				int booleanValueIndex =
+					constantPool.literalIndex(constant.booleanValue() ? 1 : 0);
+				contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
+				contents[contentsOffset++] = (byte) booleanValueIndex;
+				break;
+			case T_byte :
+				contents[contentsOffset++] = (byte) 'B';
+				int integerValueIndex =
+					constantPool.literalIndex(constant.intValue());
+				contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
+				contents[contentsOffset++] = (byte) integerValueIndex;
+				break;
+			case T_char :
+				contents[contentsOffset++] = (byte) 'C';
+				integerValueIndex =
+					constantPool.literalIndex(constant.intValue());
+				contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
+				contents[contentsOffset++] = (byte) integerValueIndex;
+				break;
+			case T_int :
+				contents[contentsOffset++] = (byte) 'I';
+				integerValueIndex =
+					constantPool.literalIndex(constant.intValue());
+				contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
+				contents[contentsOffset++] = (byte) integerValueIndex;
+				break;
+			case T_short :
+				contents[contentsOffset++] = (byte) 'S';
+				integerValueIndex =
+					constantPool.literalIndex(constant.intValue());
+				contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
+				contents[contentsOffset++] = (byte) integerValueIndex;
+				break;
+			case T_float :
+				contents[contentsOffset++] = (byte) 'F';
+				int floatValueIndex =
+					constantPool.literalIndex(constant.floatValue());
+				contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
+				contents[contentsOffset++] = (byte) floatValueIndex;
+				break;
+			case T_double :
+				contents[contentsOffset++] = (byte) 'D';
+				int doubleValueIndex =
+					constantPool.literalIndex(constant.doubleValue());
+				contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
+				contents[contentsOffset++] = (byte) doubleValueIndex;
+				break;
+			case T_long :
+				contents[contentsOffset++] = (byte) 'J';
+				int longValueIndex =
+					constantPool.literalIndex(constant.longValue());
+				contents[contentsOffset++] = (byte) (longValueIndex >> 8);
+				contents[contentsOffset++] = (byte) longValueIndex;
+				break;
+			case T_JavaLangString :
+				contents[contentsOffset++] = (byte) 's';
+				int stringValueIndex =
+					constantPool.literalIndex(((StringConstant) constant).stringValue().toCharArray());
+				if (stringValueIndex == -1) {
+					if (!creatingProblemType) {
+						// report an error and abort: will lead to a problem type classfile creation
+						TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
+						typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(defaultValue);
+					} else {
+						// already inside a problem type creation : no attribute
+						contentsOffset = attributeOffset;
+					}
+				} else {
+					contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
+					contents[contentsOffset++] = (byte) stringValueIndex;
+				}
+		}
+	}
+	
+	private void generateElementValueForNonConstantExpression(Expression defaultValue, int attributeOffset, TypeBinding defaultValueBinding) {
+		if (defaultValueBinding != null) {
+			if (defaultValueBinding.isEnum()) {
+				if (contentsOffset + 5 >= this.contents.length) {
+					resizeContents(5);
+				}
+				contents[contentsOffset++] = (byte) 'e';
+				FieldBinding fieldBinding = null;
+				if (defaultValue instanceof QualifiedNameReference) {
+					QualifiedNameReference nameReference = (QualifiedNameReference) defaultValue;
+					fieldBinding = (FieldBinding) nameReference.binding;
+				} else if (defaultValue instanceof SingleNameReference) {
+					SingleNameReference nameReference = (SingleNameReference) defaultValue;
+					fieldBinding = (FieldBinding) nameReference.binding;
+				} else {
+					contentsOffset = attributeOffset;
+				}
+				if (fieldBinding != null) {
+					final int enumConstantTypeNameIndex = constantPool.literalIndex(fieldBinding.type.signature());
+					final int enumConstantNameIndex = constantPool.literalIndex(fieldBinding.name);
+					contents[contentsOffset++] = (byte) (enumConstantTypeNameIndex >> 8);
+					contents[contentsOffset++] = (byte) enumConstantTypeNameIndex;
+					contents[contentsOffset++] = (byte) (enumConstantNameIndex >> 8);
+					contents[contentsOffset++] = (byte) enumConstantNameIndex;
+				}
+			} else if (defaultValueBinding.isAnnotationType()) {
+				if (contentsOffset + 1 >= this.contents.length) {
+					resizeContents(1);
+				}
+				contents[contentsOffset++] = (byte) '@';
+				generateAnnotation((Annotation) defaultValue, attributeOffset);
+			} else if (defaultValueBinding.isArrayType()) {
+				// array type
+				if (contentsOffset + 3 >= this.contents.length) {
+					resizeContents(3);
+				}
+				contents[contentsOffset++] = (byte) '[';
+				if (defaultValue instanceof ArrayInitializer) {
+					ArrayInitializer arrayInitializer = (ArrayInitializer) defaultValue;
+					int arrayLength = arrayInitializer.expressions != null ? arrayInitializer.expressions.length : 0;
+					contents[contentsOffset++] = (byte) (arrayLength >> 8);
+					contents[contentsOffset++] = (byte) arrayLength;
+					for (int i = 0; i < arrayLength; i++) {
+						generateElementValue(arrayInitializer.expressions[i], defaultValueBinding.leafComponentType(), attributeOffset);
+					}
+				} else {
+					contentsOffset = attributeOffset;
+				}
+			} else {
+				// class type
+				if (contentsOffset + 3 >= this.contents.length) {
+					resizeContents(3);
+				}
+				contents[contentsOffset++] = (byte) 'c';
+				if (defaultValue instanceof ClassLiteralAccess) {
+					ClassLiteralAccess classLiteralAccess = (ClassLiteralAccess) defaultValue;
+					final int classInfoIndex = constantPool.literalIndex(classLiteralAccess.targetType.signature());
+					contents[contentsOffset++] = (byte) (classInfoIndex >> 8);
+					contents[contentsOffset++] = (byte) classInfoIndex;
+				} else {
+					contentsOffset = attributeOffset;
+				}
+			}
+		} else {
+			contentsOffset = attributeOffset;
+		}
+	}
+
+	public int generateMethodInfoAttribute(MethodBinding methodBinding) {
+		return generateMethodInfoAttribute(methodBinding, false);
+	}
 	/**
 	 * INTERNAL USE-ONLY
 	 * That method generates the attributes of a code attribute.
@@ -2224,7 +3075,7 @@
 	 * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
 	 * @return <CODE>int</CODE>
 	 */
-	public int generateMethodInfoAttribute(MethodBinding methodBinding) {
+	public int generateMethodInfoAttribute(MethodBinding methodBinding, boolean createProblemMethod) {
 		// leave two bytes for the attribute_number
 		contentsOffset += 2;
 		// now we can handle all the attribute for that method info:
@@ -2258,7 +3109,7 @@
 			contents[contentsOffset++] = (byte) (length >> 8);
 			contents[contentsOffset++] = (byte) length;
 			for (int i = 0; i < length; i++) {
-				int exceptionIndex = constantPool.literalIndex(thrownsExceptions[i]);
+				int exceptionIndex = constantPool.literalIndexForType(thrownsExceptions[i].constantPoolName());
 				contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
 				contents[contentsOffset++] = (byte) exceptionIndex;
 			}
@@ -2300,9 +3151,72 @@
 
 			attributeNumber++;
 		}
+		// add signature attribute
+		char[] genericSignature = methodBinding.genericSignature();
+		if (genericSignature != null) {
+			// check that there is enough space to write all the bytes for the field info corresponding
+			// to the @fieldBinding
+			if (contentsOffset + 8 >= this.contents.length) {
+				resizeContents(8);
+			}
+			int signatureAttributeNameIndex =
+				constantPool.literalIndex(AttributeNamesConstants.SignatureName);
+			contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
+			contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
+			// the length of a signature attribute is equals to 2
+			contents[contentsOffset++] = 0;
+			contents[contentsOffset++] = 0;
+			contents[contentsOffset++] = 0;
+			contents[contentsOffset++] = 2;
+			int signatureIndex =
+				constantPool.literalIndex(genericSignature);
+			contents[contentsOffset++] = (byte) (signatureIndex >> 8);
+			contents[contentsOffset++] = (byte) signatureIndex;
+			attributeNumber++;
+		}
+		if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType && !createProblemMethod) {
+			AbstractMethodDeclaration methodDeclaration = methodBinding.sourceMethod();
+			if (methodDeclaration != null) {
+				Annotation[] annotations = methodDeclaration.annotations;
+				if (annotations != null) {
+					attributeNumber += generateRuntimeAnnotations(annotations);
+				}
+				if ((methodBinding.tagBits & TagBits.HasParameterAnnotations) != 0) {
+					Argument[] arguments = methodDeclaration.arguments;
+					if (arguments != null) {
+						attributeNumber += generateRuntimeAnnotationsForParameters(arguments);
+					}
+				}
+			}
+		}
 		return attributeNumber;
 	}
 
+	public int generateMethodInfoAttribute(MethodBinding methodBinding, AnnotationMethodDeclaration declaration) {
+		int attributesNumber = generateMethodInfoAttribute(methodBinding);
+		int attributeOffset = contentsOffset;
+		if ((declaration.modifiers & AccAnnotationDefault) != 0) {
+			// add an annotation default attribute
+			int annotationDefaultNameIndex =
+				constantPool.literalIndex(AttributeNamesConstants.AnnotationDefaultName);
+			contents[contentsOffset++] = (byte) (annotationDefaultNameIndex >> 8);
+			contents[contentsOffset++] = (byte) annotationDefaultNameIndex;
+			int attributeLengthOffset = contentsOffset;
+			contentsOffset += 4;
+
+			generateElementValue(declaration.defaultValue, declaration.binding.returnType, attributeOffset);
+			if (contentsOffset != attributeOffset) {
+				int attributeLength = contentsOffset - attributeLengthOffset - 4;
+				contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+				contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+				contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+				contents[attributeLengthOffset++] = (byte) attributeLength;			
+				attributesNumber++;
+			}
+		}
+		return attributesNumber;
+	}
+
 	/**
 	 * INTERNAL USE-ONLY
 	 * That method generates the header of a method info:
@@ -2368,11 +3282,11 @@
 		}
 		contents[contentsOffset++] = (byte) ((AccDefault | AccStatic) >> 8);
 		contents[contentsOffset++] = (byte) (AccDefault | AccStatic);
-		int nameIndex = constantPool.literalIndex(QualifiedNamesConstants.Clinit);
+		int nameIndex = constantPool.literalIndex(ConstantPool.Clinit);
 		contents[contentsOffset++] = (byte) (nameIndex >> 8);
 		contents[contentsOffset++] = (byte) nameIndex;
 		int descriptorIndex =
-			constantPool.literalIndex(QualifiedNamesConstants.ClinitSignature);
+			constantPool.literalIndex(ConstantPool.ClinitSignature);
 		contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
 		contents[contentsOffset++] = (byte) descriptorIndex;
 		// We know that we won't get more than 1 attribute: the code attribute
@@ -2381,6 +3295,264 @@
 	}
 
 	/**
+	 * INTERNAL USE-ONLY
+	 * Generate the byte for problem method infos that correspond to missing abstract methods.
+	 * http://dev.eclipse.org/bugs/show_bug.cgi?id=3179
+	 *
+	 * @param methodDeclarations Array of all missing abstract methods
+	 */
+	public void generateMissingAbstractMethods(MethodDeclaration[] methodDeclarations, CompilationResult compilationResult) {
+		if (methodDeclarations != null) {
+			for (int i = 0, max = methodDeclarations.length; i < max; i++) {
+				MethodDeclaration methodDeclaration = methodDeclarations[i];
+				MethodBinding methodBinding = methodDeclaration.binding;
+		 		String readableName = new String(methodBinding.readableName());
+		 		IProblem[] problems = compilationResult.problems;
+		 		int problemsCount = compilationResult.problemCount;
+				for (int j = 0; j < problemsCount; j++) {
+					IProblem problem = problems[j];
+					if (problem != null
+						&& problem.getID() == IProblem.AbstractMethodMustBeImplemented
+						&& problem.getMessage().indexOf(readableName) != -1) {
+							// we found a match
+							addMissingAbstractProblemMethod(methodDeclaration, methodBinding, problem, compilationResult);
+						}
+				}
+			}
+		}
+	}
+
+	/**
+	 * @param annotations
+	 * @return the number of attributes created while dumping the annotations in the .class file
+	 */
+	private int generateRuntimeAnnotations(final Annotation[] annotations) {
+		int attributesNumber = 0;
+		final int length = annotations.length;
+		int visibleAnnotationsCounter = 0;
+		int invisibleAnnotationsCounter = 0;
+		
+		for (int i = 0; i < length; i++) {
+			Annotation annotation = annotations[i];
+			if (isRuntimeInvisible(annotation)) {
+				invisibleAnnotationsCounter++;
+			} else if (isRuntimeVisible(annotation)) {
+				visibleAnnotationsCounter++;
+			}
+		}
+
+		if (invisibleAnnotationsCounter != 0) {
+			int annotationAttributeOffset = contentsOffset;
+			if (contentsOffset + 10 >= contents.length) {
+				resizeContents(10);
+			}
+			int runtimeInvisibleAnnotationsAttributeNameIndex =
+				constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleAnnotationsName);
+			contents[contentsOffset++] = (byte) (runtimeInvisibleAnnotationsAttributeNameIndex >> 8);
+			contents[contentsOffset++] = (byte) runtimeInvisibleAnnotationsAttributeNameIndex;
+			int attributeLengthOffset = contentsOffset;
+			contentsOffset += 4; // leave space for the attribute length
+	
+			int annotationsLengthOffset = contentsOffset;
+			contentsOffset += 2; // leave space for the annotations length
+		
+			contents[annotationsLengthOffset++] = (byte) (invisibleAnnotationsCounter >> 8);
+			contents[annotationsLengthOffset++] = (byte) invisibleAnnotationsCounter;
+
+			loop: for (int i = 0; i < length; i++) {
+				if (invisibleAnnotationsCounter == 0) break loop;
+				Annotation annotation = annotations[i];
+				if (isRuntimeInvisible(annotation)) {
+					generateAnnotation(annotation, annotationAttributeOffset);
+					invisibleAnnotationsCounter--;
+					if (this.contentsOffset == annotationAttributeOffset) {
+						break loop;
+					}
+				}
+			}
+			if (contentsOffset != annotationAttributeOffset) {
+				int attributeLength = contentsOffset - attributeLengthOffset - 4;
+				contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+				contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+				contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+				contents[attributeLengthOffset++] = (byte) attributeLength;			
+				attributesNumber++;
+			} else {		
+				contentsOffset = annotationAttributeOffset;
+			}
+		}
+	
+		if (visibleAnnotationsCounter != 0) {
+			int annotationAttributeOffset = contentsOffset;
+			if (contentsOffset + 10 >= contents.length) {
+				resizeContents(10);
+			}
+			int runtimeVisibleAnnotationsAttributeNameIndex =
+				constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleAnnotationsName);
+			contents[contentsOffset++] = (byte) (runtimeVisibleAnnotationsAttributeNameIndex >> 8);
+			contents[contentsOffset++] = (byte) runtimeVisibleAnnotationsAttributeNameIndex;
+			int attributeLengthOffset = contentsOffset;
+			contentsOffset += 4; // leave space for the attribute length
+	
+			int annotationsLengthOffset = contentsOffset;
+			contentsOffset += 2; // leave space for the annotations length
+		
+			contents[annotationsLengthOffset++] = (byte) (visibleAnnotationsCounter >> 8);
+			contents[annotationsLengthOffset++] = (byte) visibleAnnotationsCounter;
+
+			loop: for (int i = 0; i < length; i++) {
+				if (visibleAnnotationsCounter == 0) break loop;
+				Annotation annotation = annotations[i];
+				if (isRuntimeVisible(annotation)) {
+					visibleAnnotationsCounter--;
+					generateAnnotation(annotation, annotationAttributeOffset);
+					if (this.contentsOffset == annotationAttributeOffset) {
+						break loop;
+					}
+				}
+			}
+			if (contentsOffset != annotationAttributeOffset) {
+				int attributeLength = contentsOffset - attributeLengthOffset - 4;
+				contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+				contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+				contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+				contents[attributeLengthOffset++] = (byte) attributeLength;			
+				attributesNumber++;
+			} else {
+				contentsOffset = annotationAttributeOffset;
+			}
+		}
+		return attributesNumber;
+	}
+	
+	private int generateRuntimeAnnotationsForParameters(Argument[] arguments) {
+		final int argumentsLength = arguments.length;
+		final int VISIBLE_INDEX = 0;
+		final int INVISIBLE_INDEX = 1;
+		int invisibleParametersAnnotationsCounter = 0;
+		int visibleParametersAnnotationsCounter = 0;
+		int[][] annotationsCounters = new int[argumentsLength][2];
+		for (int i = 0; i < argumentsLength; i++) {
+			Argument argument = arguments[i];
+			Annotation[] annotations = argument.annotations;
+			if (annotations != null) {
+				for (int j = 0, max2 = annotations.length; j < max2; j++) {
+					Annotation annotation = annotations[j];
+					if (isRuntimeInvisible(annotation)) {
+						annotationsCounters[i][INVISIBLE_INDEX]++;
+						invisibleParametersAnnotationsCounter++;
+					} else if (isRuntimeVisible(annotation)) {
+						annotationsCounters[i][VISIBLE_INDEX]++;
+						visibleParametersAnnotationsCounter++;
+					}
+				}
+			}
+		}
+		int attributesNumber = 0;
+		int annotationAttributeOffset = contentsOffset;
+		if (invisibleParametersAnnotationsCounter != 0) {
+			if (contentsOffset + 7 >= contents.length) {
+				resizeContents(7);
+			}
+			int attributeNameIndex =
+				constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleParameterAnnotationsName);
+			contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
+			contents[contentsOffset++] = (byte) attributeNameIndex;
+			int attributeLengthOffset = contentsOffset;
+			contentsOffset += 4; // leave space for the attribute length
+
+			contents[contentsOffset++] = (byte) argumentsLength;
+			invisibleLoop: for (int i = 0; i < argumentsLength; i++) {
+				if (contentsOffset + 2 >= contents.length) {
+					resizeContents(2);
+				}
+				if (invisibleParametersAnnotationsCounter == 0) {
+					contents[contentsOffset++] = (byte) 0;
+					contents[contentsOffset++] = (byte) 0;					
+				} else {
+					final int numberOfInvisibleAnnotations = annotationsCounters[i][INVISIBLE_INDEX];
+					contents[contentsOffset++] = (byte) (numberOfInvisibleAnnotations >> 8);
+					contents[contentsOffset++] = (byte) numberOfInvisibleAnnotations;
+					if (numberOfInvisibleAnnotations != 0) {
+						Argument argument = arguments[i];
+						Annotation[] annotations = argument.annotations;
+						for (int j = 0, max = annotations.length; j < max; j++) {
+							Annotation annotation = annotations[j];
+							if (isRuntimeInvisible(annotation)) {
+								generateAnnotation(annotation, annotationAttributeOffset);
+								if (contentsOffset == annotationAttributeOffset) {
+									break invisibleLoop;
+								}
+								invisibleParametersAnnotationsCounter--;
+							}
+						}
+					}
+				}
+			}
+			if (contentsOffset != annotationAttributeOffset) {
+				int attributeLength = contentsOffset - attributeLengthOffset - 4;
+				contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+				contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+				contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+				contents[attributeLengthOffset++] = (byte) attributeLength;			
+				attributesNumber++;
+			} else {
+				contentsOffset = annotationAttributeOffset;
+			}
+		}
+		if (visibleParametersAnnotationsCounter != 0) {
+			if (contentsOffset + 7 >= contents.length) {
+				resizeContents(7);
+			}
+			int attributeNameIndex =
+				constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleParameterAnnotationsName);
+			contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
+			contents[contentsOffset++] = (byte) attributeNameIndex;
+			int attributeLengthOffset = contentsOffset;
+			contentsOffset += 4; // leave space for the attribute length
+
+			contents[contentsOffset++] = (byte) argumentsLength;
+			visibleLoop: for (int i = 0; i < argumentsLength; i++) {
+				if (contentsOffset + 2 >= contents.length) {
+					resizeContents(2);
+				}
+				if (visibleParametersAnnotationsCounter == 0) {
+					contents[contentsOffset++] = (byte) 0;
+					contents[contentsOffset++] = (byte) 0;					
+				} else {
+					final int numberOfVisibleAnnotations = annotationsCounters[i][VISIBLE_INDEX];
+					contents[contentsOffset++] = (byte) (numberOfVisibleAnnotations >> 8);
+					contents[contentsOffset++] = (byte) numberOfVisibleAnnotations;
+					if (numberOfVisibleAnnotations != 0) {
+						Argument argument = arguments[i];
+						Annotation[] annotations = argument.annotations;
+						for (int j = 0, max = annotations.length; j < max; j++) {
+							Annotation annotation = annotations[j];
+							if (isRuntimeVisible(annotation)) {
+								generateAnnotation(annotation, annotationAttributeOffset);
+								if (contentsOffset == annotationAttributeOffset) {
+									break visibleLoop;
+								}
+								visibleParametersAnnotationsCounter--;
+							}
+						}
+					}
+				}
+			}
+			if (contentsOffset != annotationAttributeOffset) {
+				int attributeLength = contentsOffset - attributeLengthOffset - 4;
+				contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+				contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+				contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+				contents[attributeLengthOffset++] = (byte) attributeLength;			
+				attributesNumber++;
+			} else {
+				contentsOffset = annotationAttributeOffset;
+			}
+		}
+		return attributesNumber;
+	}
+	/**
 	 * EXTERNAL API
 	 * Answer the actual bytes of the class file
 	 *
@@ -2422,6 +3594,31 @@
 		}
 	}
 
+	
+	private boolean isRuntimeInvisible(Annotation annotation) {
+		final TypeBinding annotationBinding = annotation.resolvedType;
+		if (annotationBinding == null) {
+			return false;
+		}
+		long metaTagBits = annotationBinding.getAnnotationTagBits(); // could be forward reference
+		if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0)
+			return true; // by default the retention is CLASS
+			
+		return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationClassRetention;
+	}
+
+	private boolean isRuntimeVisible(Annotation annotation) {
+		final TypeBinding annotationBinding = annotation.resolvedType;
+		if (annotationBinding == null) {
+			return false;
+		}
+		long metaTagBits = annotationBinding.tagBits;
+		if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0)
+			return false; // by default the retention is CLASS
+			
+		return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
+	}
+
 	/**
 	 * INTERNAL USE-ONLY
 	 * Returns the most enclosing classfile of the receiver. This is used know to store the constant pool name
@@ -2520,39 +3717,6 @@
 
 	/**
 	 * INTERNAL USE-ONLY
-	 * Search the line number corresponding to a specific position
-	 */
-	public static final int searchLineNumber(
-		int[] startLineIndexes,
-		int position) {
-		// this code is completely useless, but it is the same implementation than
-		// org.eclipse.jdt.internal.compiler.problem.ProblemHandler.searchLineNumber(int[], int)
-		// if (startLineIndexes == null)
-		//	return 1;
-		int length = startLineIndexes.length;
-		if (length == 0)
-			return 1;
-		int g = 0, d = length - 1;
-		int m = 0;
-		while (g <= d) {
-			m = (g + d) / 2;
-			if (position < startLineIndexes[m]) {
-				d = m - 1;
-			} else
-				if (position > startLineIndexes[m]) {
-					g = m + 1;
-				} else {
-					return m + 1;
-				}
-		}
-		if (position < startLineIndexes[m]) {
-			return m + 1;
-		}
-		return m + 2;
-	}
-
-	/**
-	 * INTERNAL USE-ONLY
 	 * This methods leaves the space for method counts recording.
 	 */
 	public void setForMethodInfos() {
@@ -2560,62 +3724,4 @@
 		methodCountOffset = contentsOffset;
 		contentsOffset += 2;
 	}
-
-	/**
-	 * INTERNAL USE-ONLY
-	 * outputPath is formed like:
-	 *	   c:\temp\ the last character is a file separator
-	 * relativeFileName is formed like:
-	 *     java\lang\String.class
-	 * @param generatePackagesStructure a flag to know if the packages structure has to be generated.
-	 * @param outputPath the output directory
-	 * @param relativeFileName java.lang.String
-	 * @param contents byte[]
-	 * 
-	 */
-	public static void writeToDisk(
-		boolean generatePackagesStructure,
-		String outputPath,
-		String relativeFileName,
-		byte[] contents)
-		throws IOException {
-			
-		BufferedOutputStream output = null;
-		if (generatePackagesStructure) {
-			output = new BufferedOutputStream(
-				new FileOutputStream(
-						new File(buildAllDirectoriesInto(outputPath, relativeFileName))));
-		} else {
-			String fileName = null;
-			char fileSeparatorChar = File.separatorChar;
-			String fileSeparator = File.separator;
-			// First we ensure that the outputPath exists
-			outputPath = outputPath.replace('/', fileSeparatorChar);
-			// To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
-			int indexOfPackageSeparator = relativeFileName.lastIndexOf(fileSeparatorChar);
-			if (indexOfPackageSeparator == -1) {
-				if (outputPath.endsWith(fileSeparator)) {
-					fileName = outputPath + relativeFileName;
-				} else {
-					fileName = outputPath + fileSeparator + relativeFileName;
-				}
-			} else {
-				int length = relativeFileName.length();
-				if (outputPath.endsWith(fileSeparator)) {
-					fileName = outputPath + relativeFileName.substring(indexOfPackageSeparator + 1, length);
-				} else {
-					fileName = outputPath + fileSeparator + relativeFileName.substring(indexOfPackageSeparator + 1, length);
-				}
-			}
-			output = new BufferedOutputStream(
-				new FileOutputStream(
-						new File(fileName)));
-		}
-		try {
-			output.write(contents);
-		} finally {
-			output.flush();
-			output.close();
-		}
-	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java
index 684df0b..d6b7475 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java
@@ -35,6 +35,7 @@
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.env.*;
 import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
 
 import java.util.*;
 
@@ -56,6 +57,7 @@
 	public int unitIndex, totalUnitsKnown;
 	public boolean hasBeenAccepted = false;
 	public char[] fileName;
+	public boolean hasInconsistentToplevelHierarchies = false; // record the fact some toplevel types have inconsistent hierarchies
 	
 	public CompilationResult(
 		char[] fileName,
@@ -358,6 +360,10 @@
 	 */
 	public void record(char[] typeName, ClassFile classFile) {
 
+	    SourceTypeBinding sourceType = classFile.referenceBinding;
+	    if (!sourceType.isLocalType() && sourceType.isHierarchyInconsistent()) {
+	        this.hasInconsistentToplevelHierarchies = true;
+	    }
 		compiledTypes.put(typeName, classFile);
 	}
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
index 92c85dc..ba20e99 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
@@ -180,7 +180,7 @@
 	/**
 	 * Add an additional binary type
 	 */
-	public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
+	public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
 		if (options.verbose) {
 			System.out.println(
 				Util.bind(
@@ -190,14 +190,14 @@
 //			new Exception("TRACE BINARY").printStackTrace(System.out);
 //		    System.out.println();
 		}
-		lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
+		lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
 	}
 
 	/**
 	 * Add an additional compilation unit into the loop
 	 *  ->  build compilation unit declarations, their bindings and record their results.
 	 */
-	public void accept(ICompilationUnit sourceUnit) {
+	public void accept(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
 		// Switch the current policy and compilation result for this unit to the requested one.
 		CompilationResult unitResult =
 			new CompilationResult(sourceUnit, totalUnits, totalUnits, this.options.maxProblemsPerUnit);
@@ -220,7 +220,7 @@
 				parsedUnit = parser.dietParse(sourceUnit, unitResult);
 			}
 			// initial type binding creation
-			lookupEnvironment.buildTypeBindings(parsedUnit);
+			lookupEnvironment.buildTypeBindings(parsedUnit, accessRestriction);
 			this.addCompilationUnit(sourceUnit, parsedUnit);
 
 			// binding resolution
@@ -239,7 +239,7 @@
 	/**
 	 * Add additional source types
 	 */
-	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
+	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
 		problemReporter.abortDueToInternalError(
 			Util.bind(
 				"abort.againstSourceModel" , //$NON-NLS-1$
@@ -295,7 +295,7 @@
 					parsedUnit = parser.dietParse(sourceUnits[i], unitResult);
 				}
 				// initial type binding creation
-				lookupEnvironment.buildTypeBindings(parsedUnit);
+				lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
 				this.addCompilationUnit(sourceUnits[i], parsedUnit);
 				//} catch (AbortCompilationUnit e) {
 				//	requestor.acceptResult(unitResult.tagAsAccepted());
@@ -340,11 +340,13 @@
 				unitsToProcess[i] = null; // release reference to processed unit declaration
 				requestor.acceptResult(unit.compilationResult.tagAsAccepted());
 				if (options.verbose)
-					System.out.println(Util.bind("compilation.done", //$NON-NLS-1$
-				new String[] {
-					String.valueOf(i + 1),
-					String.valueOf(totalUnits),
-					new String(unit.getFileName())}));
+					System.out.println(
+						Util.bind(
+							"compilation.done", //$NON-NLS-1$
+							new String[] {
+								String.valueOf(i + 1),
+								String.valueOf(totalUnits),
+								new String(unit.getFileName())}));
 			}
 		} catch (AbortCompilation e) {
 			this.handleInternalException(e, unit);
@@ -546,7 +548,7 @@
 				unit = unitsToProcess[0];
 			} else {
 				// initial type binding creation
-				lookupEnvironment.buildTypeBindings(unit);
+				lookupEnvironment.buildTypeBindings(unit, null /*no access restriction*/);
 
 				// binding resolution
 				lookupEnvironment.completeTypeBindings();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
index 74ba90b..073b101 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
+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;
@@ -26,14 +27,14 @@
 	public final static int Bit2 = 0x2; 						// return type (operator) | name reference kind (name ref) | has local type (type, method, field decl)
 	public final static int Bit3 = 0x4; 						// return type (operator) | name reference kind (name ref) | implicit this (this ref)
 	public final static int Bit4 = 0x8; 						// return type (operator) | first assignment to local (local decl) | undocumented empty block (block, type and method decl)
-	public final static int Bit5 = 0x10; 						// value for return (expression) | has all method bodies (unit)
+	public final static int 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 Bit7 = 0x40; 						// depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression)
 	public final static int Bit8 = 0x80; 						// depth (name ref, msg) | operator (operator) 
 	public final static int Bit9 = 0x100; 					// depth (name ref, msg) | operator (operator) | is local type (type decl)
 	public final static int Bit10= 0x200; 					// depth (name ref, msg) | operator (operator) | is anonymous type (type decl)
 	public final static int Bit11 = 0x400; 					// depth (name ref, msg) | operator (operator) | is member type (type decl)
-	public final static int Bit12 = 0x800; 					// depth (name ref, msg) | operator (operator)
+	public final static int 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 Bit14 = 0x2000; 				// strictly assigned (reference lhs)
 	public final static int Bit15 = 0x4000; 				// is unnecessary cast (expression)
@@ -64,6 +65,22 @@
 	public final static long Bit38L = 0x2000000000L;
 	public final static long Bit39L = 0x4000000000L;
 	public final static long Bit40L = 0x8000000000L;
+	public final static long Bit41L = 0x10000000000L;
+	public final static long Bit42L = 0x20000000000L;
+	public final static long Bit43L = 0x40000000000L;
+	public final static long Bit44L = 0x80000000000L;
+	public final static long Bit45L = 0x100000000000L;
+	public final static long Bit46L = 0x200000000000L;
+	public final static long Bit47L = 0x400000000000L;
+	public final static long Bit48L = 0x800000000000L;
+	public final static long Bit49L = 0x1000000000000L;
+	public final static long Bit50L = 0x2000000000000L;
+	public final static long Bit51L = 0x4000000000000L;
+	public final static long Bit52L = 0x8000000000000L;
+	public final static long Bit53L = 0x10000000000000L;
+	public final static long Bit54L = 0x20000000000000L;
+	public final static long Bit55L = 0x40000000000000L;
+	public final static long Bit56L = 0x80000000000000L;
 
 	public int bits = IsReachableMASK; 				// reachable by default
 
@@ -102,6 +119,7 @@
 	public static final int IsAnonymousTypeMASK = Bit10; // used to test for anonymous 
 	public static final int AnonymousAndLocalMask = IsAnonymousTypeMASK | IsLocalTypeMASK; // used to set anonymous marker
 	public static final int IsMemberTypeMASK = Bit11; // local member do not know it is local at parse time (need to look at binding)
+	public static final int HasAbstractMethods = Bit12; // used to promote abstract enums
 	
 	// for type, method and field declarations 
 	public static final int HasLocalTypeMASK = Bit2; // cannot conflict with AddAssertionMASK
@@ -132,15 +150,80 @@
 	// for if statement
 	public static final int IsElseIfStatement = Bit30;
 	
+	// for type reference
+	public static final int IsSuperType = Bit5;
+	
+	// for variable argument
+	public static final int IsVarArgs = Bit15;
+	
 	public ASTNode() {
 
 		super();
 	}
+	private static boolean checkInvocationArgument(BlockScope scope, Expression argument, TypeBinding parameterType, TypeBinding argumentType) {
+		argument.computeConversion(scope, parameterType, argumentType);
 
+		if (argumentType != NullBinding && parameterType.isWildcard() && ((WildcardBinding) parameterType).kind != Wildcard.SUPER)
+		    return true; // unsafeWildcardInvocation
+		if (argumentType != parameterType && argumentType.isRawType())
+	        if (parameterType.isBoundParameterizedType() || parameterType.isGenericType())
+				scope.problemReporter().unsafeRawConversion(argument, argumentType, parameterType);
+		return false;
+	}
+	public static void checkInvocationArguments(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding method, Expression[] arguments, TypeBinding[] argumentTypes, boolean argsContainCast, InvocationSite invocationSite) {
+		boolean unsafeWildcardInvocation = false;
+		TypeBinding[] params = method.parameters;
+		if (method.isVarargs()) {
+			// 4 possibilities exist for a call to the vararg method foo(int i, long ... value) : foo(1), foo(1, 2), foo(1, 2, 3, 4) & foo(1, new long[] {1, 2})
+			int lastIndex = params.length - 1;
+			for (int i = 0; i < lastIndex; i++)
+			    if (checkInvocationArgument(scope, arguments[i], params[i], argumentTypes[i]))
+				    unsafeWildcardInvocation = true;
+		   int argLength = arguments.length;
+		   if (lastIndex < argLength) { // vararg argument was provided
+			   	TypeBinding parameterType = params[lastIndex];
+			    if (params.length != argLength || parameterType.dimensions() != argumentTypes[lastIndex].dimensions())
+			    	parameterType = ((ArrayBinding) parameterType).elementsType(); // single element was provided for vararg parameter
+				for (int i = lastIndex; i < argLength; i++)
+				    if (checkInvocationArgument(scope, arguments[i], parameterType, argumentTypes[i]))
+					    unsafeWildcardInvocation = true;
+			}
+
+		   if (method.parameters.length == argumentTypes.length) { // 70056
+				int varargIndex = method.parameters.length - 1;
+				ArrayBinding varargType = (ArrayBinding) method.parameters[varargIndex];
+				TypeBinding lastArgType = argumentTypes[varargIndex];
+				if (lastArgType == NullBinding) {
+					if (!(varargType.leafComponentType().isBaseType() && varargType.dimensions() == 1))
+						scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite);
+				} else if (varargType.dimensions <= lastArgType.dimensions()) {
+					int dimensions = lastArgType.dimensions();
+					if (lastArgType.leafComponentType().isBaseType())
+						dimensions--;
+					if (varargType.dimensions < dimensions)
+						scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite);
+					else if (varargType.dimensions == dimensions && varargType.leafComponentType != lastArgType.leafComponentType())
+						scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite);
+				}
+			}
+		} else {
+			for (int i = 0, argLength = arguments.length; i < argLength; i++)
+			    if (checkInvocationArgument(scope, arguments[i], params[i], argumentTypes[i]))
+				    unsafeWildcardInvocation = true;
+		}
+		if (argsContainCast) {
+			CastExpression.checkNeedForArgumentCasts(scope, receiver, receiverType, method, arguments, argumentTypes, invocationSite);
+		}
+		if (unsafeWildcardInvocation) {
+		    scope.problemReporter().wildcardInvocation((ASTNode)invocationSite, receiverType, method, argumentTypes);
+		} else if (!receiverType.isUnboundWildcard() && method.declaringClass.isRawType() && method.hasSubstitutedParameters()) {
+		    scope.problemReporter().unsafeRawInvocation((ASTNode)invocationSite, method);
+		}
+	}
 	public ASTNode concreteStatement() {
 		return this;
 	}
-
+	
 	/* Answer true if the field use is considered deprecated.
 	* An access in the same compilation unit is allowed.
 	*/
@@ -173,7 +256,7 @@
 
 		if (method.isPrivate() && !scope.isDefinedInMethod(method)) {
 			// ignore cases where method is used from within inside itself (e.g. direct recursions)
-			method.modifiers |= AccPrivateUsed;
+			method.original().modifiers |= AccPrivateUsed;
 		}
 		
 		if (!method.isViewedAsDeprecated()) return false;
@@ -210,9 +293,15 @@
 
 		if (refType.isPrivate() && !scope.isDefinedInType(refType)) {
 			// ignore cases where type is used from within inside itself 
-			refType.modifiers |= AccPrivateUsed;
+			((ReferenceBinding)refType.erasure()).modifiers |= AccPrivateUsed;
 		}
-
+		
+		if (refType.hasRestrictedAccess()) {
+			AccessRestriction restriction = scope.environment().getAccessRestriction(type);
+			if (restriction != null) {
+				scope.problemReporter().forbiddenReference(type, this, restriction.getMessageTemplate());
+			}
+		}
 		if (!refType.isViewedAsDeprecated()) return false;
 		
 		// inside same unit - no report
@@ -225,6 +314,15 @@
 
 	public abstract StringBuffer print(int indent, StringBuffer output);
 
+	public static StringBuffer printAnnotations(Annotation[] annotations, StringBuffer output) {
+		int length = annotations.length;
+		for (int i = 0; i < length; i++) {
+			annotations[i].print(0, output);
+			output.append(" "); //$NON-NLS-1$
+		}
+		return output;
+	}
+	
 	public static StringBuffer printIndent(int indent, StringBuffer output) {
 
 		for (int i = indent; i > 0; i--) output.append("  "); //$NON-NLS-1$
@@ -255,6 +353,68 @@
 			output.append("abstract "); //$NON-NLS-1$
 		return output;
 	}
+	
+	/**
+	 * Resolve annotations, and check duplicates, answers combined tagBits 
+	 * for recognized standard annotations
+	 */
+	public static void resolveAnnotations(BlockScope scope, Annotation[] annotations, Binding recipient) {
+		if (recipient != null) {
+			switch (recipient.kind()) {
+				case Binding.PACKAGE :
+					// TODO (philippe) need support for package annotations
+					break;
+				case Binding.TYPE :
+				case Binding.GENERIC_TYPE :
+				case Binding.TYPE_PARAMETER :
+					ReferenceBinding type = (ReferenceBinding) recipient;
+					if ((type.tagBits & TagBits.AnnotationResolved) != 0) return;
+					type.tagBits |= TagBits.AnnotationResolved;
+					break;
+				case Binding.METHOD :
+					MethodBinding method = (MethodBinding) recipient;
+					if ((method.tagBits & TagBits.AnnotationResolved) != 0) return;
+					method.tagBits |= TagBits.AnnotationResolved;
+					break;
+				case Binding.FIELD :
+					FieldBinding field = (FieldBinding) recipient;
+					if ((field.tagBits & TagBits.AnnotationResolved) != 0) return;
+					field.tagBits |= TagBits.AnnotationResolved;
+					break;
+				case Binding.LOCAL :
+					LocalVariableBinding local = (LocalVariableBinding) recipient;
+					if ((local.tagBits & TagBits.AnnotationResolved) != 0) return;
+					local.tagBits |= TagBits.AnnotationResolved;
+					break;
+			}			
+		}
+		if (annotations == null) 
+			return;
+		int length = annotations.length;
+		TypeBinding[] annotationTypes = new TypeBinding[length];
+		for (int i = 0; i < length; i++) {
+			Annotation annotation = annotations[i];
+			annotation.recipient = recipient;
+			annotationTypes[i] = annotation.resolveType(scope);
+		}
+		// check duplicate annotations
+		for (int i = 0; i < length; i++) {
+			TypeBinding annotationType = annotationTypes[i];
+			if (annotationType == null) continue;
+			boolean foundDuplicate = false;
+			for (int j = i+1; j < length; j++) {
+				if (annotationTypes[j] == annotationType) {
+					foundDuplicate = true;
+					annotationTypes[j] = null; // report it only once
+					scope.problemReporter().duplicateAnnotation(annotations[j]);
+				}
+			}
+			if (foundDuplicate) {
+				scope.problemReporter().duplicateAnnotation(annotations[i]);
+			}
+		}
+	}
+	
 	public int sourceStart() {
 		return this.sourceStart;
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
index c25253e..985a97d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
@@ -32,6 +32,7 @@
 	public int declarationSourceEnd;
 	public int modifiers;
 	public int modifiersSourceStart;
+	public Annotation[] annotations;
 	public Argument[] arguments;
 	public TypeReference[] thrownExceptions;
 	public Statement[] statements;
@@ -83,7 +84,11 @@
 			int length = this.arguments.length;
 			for (int i = 0; i < length; i++) {
 				TypeBinding argType = this.binding == null ? null : this.binding.parameters[i];
-				this.arguments[i].bind(this.scope, argType, used);
+				Argument argument = this.arguments[i];
+				argument.bind(this.scope, argType, used);
+				if (argument.annotations != null) {
+					this.binding.tagBits |= TagBits.HasParameterAnnotations;
+				}
 			}
 		}
 	}
@@ -187,7 +192,7 @@
 		}
 	}
 
-	private void generateCode(ClassFile classFile) {
+	public void generateCode(ClassFile classFile) {
 
 		classFile.generateMethodInfoHeader(this.binding);
 		int methodAttributeOffset = classFile.contentsOffset;
@@ -258,6 +263,11 @@
 		return (this.modifiers & AccAbstract) != 0;
 	}
 
+	public boolean isAnnotationMethod() {
+
+		return false;
+	}
+	
 	public boolean isClinit() {
 
 		return false;
@@ -278,6 +288,11 @@
 		return false;
 	}
 
+	public boolean isMethod() {
+
+		return false;
+	}
+
 	public boolean isNative() {
 
 		if (this.binding != null)
@@ -305,6 +320,20 @@
 
 		printIndent(tab, output);
 		printModifiers(this.modifiers, output);
+		if (this.annotations != null) printAnnotations(this.annotations, output);
+		
+		TypeParameter[] typeParams = typeParameters();
+		if (typeParams != null) {
+			output.append('<');//$NON-NLS-1$
+			int max = typeParams.length - 1;
+			for (int j = 0; j < max; j++) {
+				typeParams[j].print(0, output);
+				output.append(", ");//$NON-NLS-1$
+			}
+			typeParams[max].print(0, output);
+			output.append('>');
+		}
+		
 		printReturnType(0, output).append(this.selector).append('(');
 		if (this.arguments != null) {
 			for (int i = 0; i < this.arguments.length; i++) {
@@ -356,6 +385,7 @@
 			bindArguments(); 
 			bindThrownExceptions();
 			resolveJavadoc();
+			resolveAnnotations(scope, this.annotations, this.binding);
 			resolveStatements();
 		} catch (AbortMethod e) {	// ========= abort on fatal error =============
 			this.ignoreFurtherInvestigation = true;
@@ -395,4 +425,8 @@
 		ClassScope classScope) {
 		// default implementation: subclass will define it
 	}
+	
+	public TypeParameter[] typeParameters() {
+	    return null;
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
index cce62fc..ec08039 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
@@ -15,6 +15,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 
 public abstract class AbstractVariableDeclaration extends Statement implements InvocationSite {
 	public int declarationEnd;
@@ -24,6 +25,7 @@
 	public Expression initialization;
 	public int modifiers;
 	public int modifiersSourceStart;
+	public Annotation[] annotations;
 
 	public char[] name;
 
@@ -32,6 +34,27 @@
 	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
 		return flowInfo;
 	}
+	
+	public static final int FIELD = 1;
+	public static final int INITIALIZER = 2;
+	public static final int ENUM_CONSTANT = 3;
+	public static final int LOCAL_VARIABLE = 4;
+	public static final int PARAMETER = 5;
+	public static final int TYPE_PARAMETER = 6;
+	
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+	 */
+	public TypeBinding[] genericTypeArguments() {
+		return null;
+	}
+	
+	/**
+	 * Returns the constant kind of this variable declaration
+	 */
+	public abstract int getKind();
+	
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#isSuperAccess()
 	 */
@@ -46,17 +69,29 @@
 		return false;
 	}
 
-	
 	public StringBuffer printStatement(int indent, StringBuffer output) {
 
 		printIndent(indent, output);
 		printModifiers(this.modifiers, output);
-		type.print(0, output).append(' ').append(this.name); 
-		if (initialization != null) {
-			output.append(" = "); //$NON-NLS-1$
-			initialization.printExpression(indent, output);
+		if (this.annotations != null) printAnnotations(this.annotations, output);
+		
+		if (type != null) {
+			type.print(0, output).append(' ');
 		}
-		return output.append(';');
+		output.append(this.name); 
+		switch(getKind()) {
+			case ENUM_CONSTANT:
+				if (initialization != null) {
+					initialization.printExpression(indent, output);
+				}
+				return output.append(',');
+			default:
+				if (initialization != null) {
+					output.append(" = "); //$NON-NLS-1$
+					initialization.printExpression(indent, output);
+				}
+				return output.append(';');
+		}
 	}
 
 	public void resolve(BlockScope scope) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
index 2a47d4d..e631f12 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
@@ -15,15 +15,16 @@
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
-public class AllocationExpression
-	extends Expression
-	implements InvocationSite {
+public class AllocationExpression extends Expression implements InvocationSite {
 		
 	public TypeReference type;
 	public Expression[] arguments;
-	public MethodBinding binding;
-
-	MethodBinding syntheticAccessor;
+	public MethodBinding binding;							// exact binding resulting from lookup
+	protected MethodBinding codegenBinding;	// actual binding used for code generation (if no synthetic accessor)
+	MethodBinding syntheticAccessor;						// synthetic accessor for inner-emulation
+	public TypeReference[] typeArguments;	
+	public TypeBinding[] genericTypeArguments;
+	public FieldDeclaration enumConstant; // for enum constant initializations
 
 	public FlowInfo analyseCode(
 		BlockScope currentScope,
@@ -31,7 +32,7 @@
 		FlowInfo flowInfo) {
 
 		// check captured variables are initialized in current context (26134)
-		checkCapturedLocalInitializationIfNecessary(this.binding.declaringClass, currentScope, flowInfo);
+		checkCapturedLocalInitializationIfNecessary((ReferenceBinding)this.binding.declaringClass.erasure(), currentScope, flowInfo);
 
 		// process arguments
 		if (arguments != null) {
@@ -74,7 +75,6 @@
 						currentScope.problemReporter().uninitializedLocalVariable(targetLocal, this);
 					}
 				}
-						
 		}
 	}
 	
@@ -88,14 +88,20 @@
 		boolean valueRequired) {
 
 		int pc = codeStream.position;
-		ReferenceBinding allocatedType = binding.declaringClass;
+		ReferenceBinding allocatedType = this.codegenBinding.declaringClass;
 
 		codeStream.new_(allocatedType);
 		if (valueRequired) {
 			codeStream.dup();
 		}
 		// better highlight for allocation: display the type individually
-		codeStream.recordPositionsFrom(pc, type.sourceStart);
+		if (this.type != null) { // null for enum constant body
+			codeStream.recordPositionsFrom(pc, this.type.sourceStart);
+		} else {
+			// push enum constant name and ordinal
+			codeStream.ldc(String.valueOf(enumConstant.name));
+			codeStream.generateInlinedValue(enumConstant.binding.id);
+		}
 
 		// handling innerclass instance allocation - enclosing instance arguments
 		if (allocatedType.isNestedType()) {
@@ -106,11 +112,7 @@
 				this);
 		}
 		// generate the arguments for constructor
-		if (arguments != null) {
-			for (int i = 0, count = arguments.length; i < count; i++) {
-				arguments[i].generateCode(currentScope, codeStream, true);
-			}
-		}
+		generateArguments(binding, arguments, currentScope, codeStream);
 		// handling innerclass instance allocation - outer local arguments
 		if (allocatedType.isNestedType()) {
 			codeStream.generateSyntheticOuterArgumentValues(
@@ -120,20 +122,27 @@
 		}
 		// invoke constructor
 		if (syntheticAccessor == null) {
-			codeStream.invokespecial(binding);
+			codeStream.invokespecial(this.codegenBinding);
 		} else {
 			// synthetic accessor got some extra arguments appended to its signature, which need values
 			for (int i = 0,
-				max = syntheticAccessor.parameters.length - binding.parameters.length;
+				max = syntheticAccessor.parameters.length - this.codegenBinding.parameters.length;
 				i < max;
 				i++) {
 				codeStream.aconst_null();
 			}
 			codeStream.invokespecial(syntheticAccessor);
 		}
+		codeStream.generateImplicitConversion(this.implicitConversion);
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
-
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+	 */
+	public TypeBinding[] genericTypeArguments() {
+		return this.genericTypeArguments;
+	}
+	
 	public boolean isSuperAccess() {
 
 		return false;
@@ -154,18 +163,18 @@
 	public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 
 		if (!flowInfo.isReachable()) return;
-		ReferenceBinding allocatedType;
+		ReferenceBinding allocatedTypeErasure = (ReferenceBinding) binding.declaringClass.erasure();
 
 		// perform some emulation work in case there is some and we are inside a local type only
-		if ((allocatedType = binding.declaringClass).isNestedType()
+		if (allocatedTypeErasure.isNestedType()
 			&& currentScope.enclosingSourceType().isLocalType()) {
 
-			if (allocatedType.isLocalType()) {
-				((LocalTypeBinding) allocatedType).addInnerEmulationDependent(currentScope, false);
+			if (allocatedTypeErasure.isLocalType()) {
+				((LocalTypeBinding) allocatedTypeErasure).addInnerEmulationDependent(currentScope, false);
 				// request cascade of accesses
 			} else {
 				// locally propagate, since we already now the desired shape for sure
-				currentScope.propagateInnerEmulation(allocatedType, false);
+				currentScope.propagateInnerEmulation(allocatedTypeErasure, false);
 				// request cascade of accesses
 			}
 		}
@@ -174,27 +183,42 @@
 	public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 
 		if (!flowInfo.isReachable()) return;
-		if (binding.isPrivate()
-			&& (currentScope.enclosingSourceType() != binding.declaringClass)) {
 
-			if (currentScope
-				.environment()
-				.options
-				.isPrivateConstructorAccessChangingVisibility) {
-				binding.tagForClearingPrivateModifier();
+		// if constructor from parameterized type got found, use the original constructor at codegen time
+		this.codegenBinding = this.binding.original();
+
+		if (this.codegenBinding.isPrivate()
+			&& (currentScope.enclosingSourceType() != this.codegenBinding.declaringClass)) {
+
+			if (currentScope.environment().options.isPrivateConstructorAccessChangingVisibility) {
+				this.codegenBinding.tagForClearingPrivateModifier();
 				// constructor will not be dumped as private, no emulation required thus
 			} else {
 				syntheticAccessor =
-					((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding, isSuperAccess());
-				currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
+					((SourceTypeBinding) this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isSuperAccess());
+				currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this);
 			}
 		}
 	}
 
 	public StringBuffer printExpression(int indent, StringBuffer output) {
 
-		output.append("new "); //$NON-NLS-1$
-		type.printExpression(0, output); 
+		if (this.type != null) { // type null for enum constant initializations
+			output.append("new "); //$NON-NLS-1$
+		}
+		if (typeArguments != null) {
+			output.append('<');//$NON-NLS-1$
+			int max = typeArguments.length - 1;
+			for (int j = 0; j < max; j++) {
+				typeArguments[j].print(0, output);
+				output.append(", ");//$NON-NLS-1$
+			}
+			typeArguments[max].print(0, output);
+			output.append('>');
+		}
+		if (type != null) { // type null for enum constant initializations
+			type.printExpression(0, output); 
+		}
 		output.append('(');
 		if (arguments != null) {
 			for (int i = 0; i < arguments.length; i++) {
@@ -209,9 +233,29 @@
 
 		// Propagate the type checking to the arguments, and check if the constructor is defined.
 		constant = NotAConstant;
-		this.resolvedType = type.resolveType(scope);
+		if (this.type == null) {
+			// initialization of an enum constant
+			this.resolvedType = scope.enclosingSourceType();
+		} else {
+			this.resolvedType = this.type.resolveType(scope, true /* check bounds*/);
+		}
 		// will check for null after args are resolved
 
+		// resolve type arguments (for generic constructor call)
+		if (this.typeArguments != null) {
+			int length = this.typeArguments.length;
+			boolean argHasError = false; // typeChecks all arguments
+			this.genericTypeArguments = new TypeBinding[length];
+			for (int i = 0; i < length; i++) {
+				if ((this.genericTypeArguments[i] = this.typeArguments[i].resolveType(scope, true /* check bounds*/)) == null) {
+					argHasError = true;
+				}
+			}
+			if (argHasError) {
+				return null;
+			}
+		}
+		
 		// buffering the arguments' types
 		boolean argsContainCast = false;
 		TypeBinding[] argumentTypes = NoParameters;
@@ -236,13 +280,13 @@
 		if (this.resolvedType == null)
 			return null;
 
-		if (!this.resolvedType.canBeInstantiated()) {
+		// null type denotes fake allocation for enum constant inits
+		if (this.type != null && !this.resolvedType.canBeInstantiated()) {
 			scope.problemReporter().cannotInstantiate(type, this.resolvedType);
 			return this.resolvedType;
 		}
 		ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType;
-		if (!(binding = scope.getConstructor(allocationType, argumentTypes, this))
-			.isValidBinding()) {
+		if (!(binding = scope.getConstructor(allocationType, argumentTypes, this)).isValidBinding()) {
 			if (binding.declaringClass == null)
 				binding.declaringClass = allocationType;
 			scope.problemReporter().invalidConstructor(this, binding);
@@ -250,15 +294,9 @@
 		}
 		if (isMethodUseDeprecated(binding, scope))
 			scope.problemReporter().deprecatedMethod(binding, this);
+		if (this.arguments != null)
+			checkInvocationArguments(scope, null, allocationType, this.binding, this.arguments, argumentTypes, argsContainCast, this);
 
-		if (arguments != null) {
-			for (int i = 0; i < arguments.length; i++) {
-				arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
-			}
-			if (argsContainCast) {
-				CastExpression.checkNeedForArgumentCasts(scope, null, allocationType, binding, this.arguments, argumentTypes, this);
-			}
-		}
 		return allocationType;
 	}
 
@@ -277,12 +315,17 @@
 	public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 		if (visitor.visit(this, scope)) {
-			int argumentsLength;
-			type.traverse(visitor, scope);
-			if (arguments != null) {
-				argumentsLength = arguments.length;
-				for (int i = 0; i < argumentsLength; i++)
-					arguments[i].traverse(visitor, scope);
+			if (this.typeArguments != null) {
+				for (int i = 0, typeArgumentsLength = this.typeArguments.length; i < typeArgumentsLength; i++) {
+					this.typeArguments[i].traverse(visitor, scope);
+				}
+			}
+			if (this.type != null) { // enum constant scenario
+				this.type.traverse(visitor, scope);
+			}
+			if (this.arguments != null) {
+				for (int i = 0, argumentsLength = this.arguments.length; i < argumentsLength; i++)
+					this.arguments[i].traverse(visitor, scope);
 			}
 		}
 		visitor.endVisit(this, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
new file mode 100644
index 0000000..df2b1d3
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
@@ -0,0 +1,304 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/**
+ * Annotation
+ */
+public abstract class Annotation extends Expression {
+	
+	public TypeReference type;
+	public int declarationSourceEnd;
+	public Binding recipient;
+	
+	final static MemberValuePair[] NoValuePairs = new MemberValuePair[0];
+	
+	public static long getRetentionPolicy(char[] policyName) {
+		if (policyName == null || policyName.length == 0)
+			return 0;
+		switch(policyName[0]) {
+			case 'C' :
+				if (CharOperation.equals(policyName, TypeConstants.UPPER_CLASS)) 
+					return TagBits.AnnotationClassRetention;
+				break;
+			case 'S' :
+				if (CharOperation.equals(policyName, TypeConstants.UPPER_SOURCE)) 
+					return TagBits.AnnotationSourceRetention;
+				break;
+			case 'R' :
+				if (CharOperation.equals(policyName, TypeConstants.UPPER_RUNTIME)) 
+					return TagBits.AnnotationRuntimeRetention;
+				break;
+		}
+		return 0; // unknown
+	}
+	
+	public static long getTargetElementType(char[] elementName) {
+		if (elementName == null || elementName.length == 0)
+			return 0;
+		switch(elementName[0]) {
+			case 'A' :
+				if (CharOperation.equals(elementName, TypeConstants.UPPER_ANNOTATION_TYPE)) 
+					return TagBits.AnnotationForAnnotationType;
+				break;
+			case 'C' :
+				if (CharOperation.equals(elementName, TypeConstants.UPPER_CONSTRUCTOR)) 
+					return TagBits.AnnotationForConstructor;
+				break;
+			case 'F' :
+				if (CharOperation.equals(elementName, TypeConstants.UPPER_FIELD)) 
+					return TagBits.AnnotationForField;
+				break;
+			case 'L' :
+				if (CharOperation.equals(elementName, TypeConstants.UPPER_LOCAL_VARIABLE)) 
+					return TagBits.AnnotationForLocalVariable;
+				break;
+			case 'M' :
+				if (CharOperation.equals(elementName, TypeConstants.UPPER_METHOD)) 
+					return TagBits.AnnotationForMethod;
+				break;
+			case 'P' :
+				if (CharOperation.equals(elementName, TypeConstants.UPPER_PARAMETER)) 
+					return TagBits.AnnotationForParameter;
+				else if (CharOperation.equals(elementName, TypeConstants.UPPER_PACKAGE)) 
+					return TagBits.AnnotationForPackage;
+				break;
+			case 'T' :
+				if (CharOperation.equals(elementName, TypeConstants.TYPE)) 
+					return TagBits.AnnotationForType;
+				break;
+		}
+		return 0; // unknown
+	}		
+	
+	/**
+	 * Compute the bit pattern for recognized standard annotations the compiler may need to act upon
+	 */
+	private long detectStandardAnnotation(Scope scope, ReferenceBinding annotationType, MemberValuePair valueAttribute) {
+		long tagBits = 0;
+		switch (annotationType.id) {
+			// retention annotation
+			case TypeIds.T_JavaLangAnnotationRetention :
+				if (valueAttribute != null) {
+					Expression expr = valueAttribute.value;
+					if ((expr.bits & Binding.VARIABLE) == Binding.FIELD) {
+						FieldBinding field = ((Reference)expr).fieldBinding();
+						if (field != null && field.declaringClass.id == T_JavaLangAnnotationRetentionPolicy) {
+							tagBits |= getRetentionPolicy(field.name);
+						}
+					}
+				}
+				break;
+			// target annotation
+			case TypeIds.T_JavaLangAnnotationTarget :		
+				tagBits |= TagBits.AnnotationTarget; // target specified (could be empty)
+				if (valueAttribute != null) {
+					Expression expr = valueAttribute.value;
+					if (expr instanceof ArrayInitializer) {
+						ArrayInitializer initializer = (ArrayInitializer) expr;
+						final Expression[] expressions = initializer.expressions;
+						if (expressions != null) {
+							for (int i = 0, length = expressions.length; i < length; i++) {
+								Expression initExpr = expressions[i];
+								if ((initExpr.bits & Binding.VARIABLE) == Binding.FIELD) {
+									FieldBinding field = ((Reference) initExpr).fieldBinding();
+									if (field != null && field.declaringClass.id == T_JavaLangAnnotationElementType) {
+										long element = getTargetElementType(field.name);
+										if ((tagBits & element) != 0) {
+											scope.problemReporter().duplicateTargetInTargetAnnotation(annotationType, (NameReference)initExpr);
+										} else {
+											tagBits |= element;
+										}
+									}							
+								}
+							}
+						}
+					} else if ((expr.bits & Binding.VARIABLE) == Binding.FIELD) {
+						FieldBinding field = ((Reference) expr).fieldBinding();
+						if (field != null && field.declaringClass.id == T_JavaLangAnnotationElementType) {
+							tagBits |= getTargetElementType(field.name);
+						}
+					}
+				}
+				break;
+			// marker annotations
+			case TypeIds.T_JavaLangDeprecated :
+				tagBits |= TagBits.AnnotationDeprecated;
+				break;
+			case TypeIds.T_JavaLangAnnotationDocumented :
+				tagBits |= TagBits.AnnotationDocumented;
+				break;
+			case TypeIds.T_JavaLangAnnotationInherited :
+				tagBits |= TagBits.AnnotationInherited;
+				break;
+			case TypeIds.T_JavaLangOverride :
+				tagBits |= TagBits.AnnotationOverride;
+				break;
+			case TypeIds.T_JavaLangSuppressWarnings :
+				tagBits |= TagBits.AnnotationSuppressWarnings;
+				break;
+		}
+		return tagBits;
+	}
+	
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+		output.append('@');
+		this.type.printExpression(0, output);
+		return output;
+	}
+	
+	public abstract MemberValuePair[] memberValuePairs();
+	
+	public TypeBinding resolveType(BlockScope scope) {
+		
+		this.constant = NotAConstant;
+		
+		TypeBinding typeBinding = this.type.resolveType(scope);
+		if (typeBinding == null)
+			return null;
+		this.resolvedType = typeBinding;
+		// ensure type refers to an annotation type
+		if (!typeBinding.isAnnotationType()) {
+			scope.problemReporter().typeMismatchError(typeBinding, scope.getJavaLangAnnotationAnnotation(), this.type);
+			return null;
+		}
+
+		ReferenceBinding annotationType = (ReferenceBinding) this.resolvedType;
+		MethodBinding[] methods = annotationType.methods();
+		// clone valuePairs to keep track of unused ones
+		MemberValuePair[] originalValuePairs = memberValuePairs();
+		MemberValuePair valueAttribute = null; // remember the first 'value' pair
+		MemberValuePair[] pairs;
+		int pairsLength = originalValuePairs.length;
+		System.arraycopy(originalValuePairs, 0, pairs = new MemberValuePair[pairsLength], 0, pairsLength);
+		
+		nextMember: for (int i = 0, requiredLength = methods.length; i < requiredLength; i++) {
+			MethodBinding method = methods[i];
+			char[] selector = method.selector;
+			boolean foundValue = false;
+			nextPair: for (int j = 0; j < pairsLength; j++) {
+				MemberValuePair pair = pairs[j];
+				if (pair == null) continue nextPair;
+				char[] name = pair.name;
+				if (CharOperation.equals(name, selector)) {
+					if (valueAttribute == null && CharOperation.equals(name, TypeConstants.VALUE)) {
+						valueAttribute = pair;
+					}
+					pair.binding = method;
+					pair.resolveTypeExpecting(scope, method.returnType);
+					pairs[j] = null; // consumed
+					foundValue = true;
+					
+					// check duplicates
+					boolean foundDuplicate = false;
+					for (int k = j+1; k < pairsLength; k++) {
+						MemberValuePair otherPair = pairs[k];
+						if (otherPair == null) continue;
+						if (CharOperation.equals(otherPair.name, selector)) {
+							foundDuplicate = true;
+							scope.problemReporter().duplicateAnnotationValue(annotationType, otherPair);
+							otherPair.binding = method;
+							otherPair.resolveTypeExpecting(scope, method.returnType);
+							pairs[k] = null;
+						}
+					}
+					if (foundDuplicate) {
+						scope.problemReporter().duplicateAnnotationValue(annotationType, pair);
+						continue nextMember;
+					}
+				}
+			}
+			if (!foundValue && (method.modifiers & AccAnnotationDefault) == 0) {
+				scope.problemReporter().missingValueForAnnotationMember(this, selector);
+			}
+		}
+		// check unused pairs
+		for (int i = 0; i < pairsLength; i++) {
+			if (pairs[i] != null) {
+				scope.problemReporter().undefinedAnnotationValue(annotationType, pairs[i]);
+			}
+		}
+		// recognize standard annotations ?
+		long tagBits = detectStandardAnnotation(scope, annotationType, valueAttribute);
+		if (this.recipient != null) {
+			if (tagBits != 0) {
+				// tag bits onto recipient
+				switch (this.recipient.kind()) {
+					case Binding.PACKAGE :
+						// TODO (philippe) need support for package annotations
+						break;
+					case Binding.TYPE :
+					case Binding.GENERIC_TYPE :
+					case Binding.TYPE_PARAMETER :
+						((ReferenceBinding)this.recipient).tagBits |= tagBits;
+						break;
+					case Binding.METHOD :
+						((MethodBinding)this.recipient).tagBits |= tagBits;
+						break;
+					case Binding.FIELD :
+						((FieldBinding)this.recipient).tagBits |= tagBits;
+						break;
+					case Binding.LOCAL :
+						((LocalVariableBinding)this.recipient).tagBits |= tagBits;
+						break;
+				}			
+			}
+			// check (meta)target compatibility
+			checkTargetCompatibility: {
+				long metaTagBits = annotationType.getAnnotationTagBits(); // could be forward reference
+				if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0) // does not specify any target restriction
+					break checkTargetCompatibility;
+					
+				switch (recipient.kind()) {
+					case Binding.PACKAGE :
+						if ((metaTagBits & TagBits.AnnotationForPackage) != 0)
+							break checkTargetCompatibility;
+						break;
+					case Binding.TYPE :
+					case Binding.GENERIC_TYPE :
+						if (((ReferenceBinding)this.recipient).isAnnotationType()) {
+							if ((metaTagBits & (TagBits.AnnotationForAnnotationType|TagBits.AnnotationForType)) != 0)
+							break checkTargetCompatibility;
+						} else if ((metaTagBits & TagBits.AnnotationForType) != 0) 
+							break checkTargetCompatibility;
+						break;
+					case Binding.METHOD :
+						if (((MethodBinding)this.recipient).isConstructor()) {
+							if ((metaTagBits & TagBits.AnnotationForConstructor) != 0)
+								break checkTargetCompatibility;
+						} else 	if ((metaTagBits & TagBits.AnnotationForMethod) != 0)
+							break checkTargetCompatibility;
+						break;
+					case Binding.FIELD :
+						if ((metaTagBits & TagBits.AnnotationForField) != 0)
+							break checkTargetCompatibility;
+						break;
+					case Binding.LOCAL :
+						if (((LocalVariableBinding)this.recipient).isArgument) {
+							if ((metaTagBits & TagBits.AnnotationForParameter) != 0)
+								break checkTargetCompatibility;
+						} else 	if ((annotationType.tagBits & TagBits.AnnotationForLocalVariable) != 0)
+							break checkTargetCompatibility;
+						break;
+				}			
+				scope.problemReporter().disallowedTargetForAnnotation(this);
+			}
+		}
+		return this.resolvedType;
+	}
+	
+	public abstract void traverse(ASTVisitor visitor, BlockScope scope);
+	public abstract void traverse(ASTVisitor visitor, CompilationUnitScope scope);
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AnnotationMethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AnnotationMethodDeclaration.java
new file mode 100644
index 0000000..c7ef29f
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AnnotationMethodDeclaration.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ClassFile;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
+
+public class AnnotationMethodDeclaration extends MethodDeclaration {
+	
+	public Expression defaultValue;
+	public int extendedDimensions;
+
+	/**
+	 * MethodDeclaration constructor comment.
+	 */
+	public AnnotationMethodDeclaration(CompilationResult compilationResult) {
+		super(compilationResult);
+	}
+
+	public void generateCode(ClassFile classFile) {
+		classFile.generateMethodInfoHeader(this.binding);
+		int methodAttributeOffset = classFile.contentsOffset;
+		int attributeNumber = classFile.generateMethodInfoAttribute(this.binding, this);
+		classFile.completeMethodInfo(methodAttributeOffset, attributeNumber);
+	}
+	
+	public boolean isAnnotationMethod() {
+
+		return true;
+	}
+	
+	public boolean isMethod() {
+
+		return false;
+	}
+	
+	public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
+		// nothing to do
+		// annotation type member declaration don't have any body
+	}
+	
+	public StringBuffer print(int tab, StringBuffer output) {
+
+		printIndent(tab, output);
+		printModifiers(this.modifiers, output);
+		if (this.annotations != null) printAnnotations(this.annotations, output);
+		
+		TypeParameter[] typeParams = typeParameters();
+		if (typeParams != null) {
+			output.append('<');//$NON-NLS-1$
+			int max = typeParams.length - 1;
+			for (int j = 0; j < max; j++) {
+				typeParams[j].print(0, output);
+				output.append(", ");//$NON-NLS-1$
+			}
+			typeParams[max].print(0, output);
+			output.append('>');
+		}
+		
+		printReturnType(0, output).append(this.selector).append('(');
+		if (this.arguments != null) {
+			for (int i = 0; i < this.arguments.length; i++) {
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				this.arguments[i].print(0, output);
+			}
+		}
+		output.append(')');
+		if (this.thrownExceptions != null) {
+			output.append(" throws "); //$NON-NLS-1$
+			for (int i = 0; i < this.thrownExceptions.length; i++) {
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				this.thrownExceptions[i].print(0, output);
+			}
+		}
+		
+		if (this.defaultValue != null) {
+			output.append(" default "); //$NON-NLS-1$
+			this.defaultValue.print(0, output);
+		}
+		
+		printBody(tab + 1, output);
+		return output;
+	}
+	
+	public void resolveStatements() {
+
+		super.resolveStatements();
+		if (this.arguments != null) {
+			scope.problemReporter().annotationMembersCannotHaveParameters(this);
+		}
+		if (this.typeParameters != null) {
+			scope.problemReporter().annotationMembersCannotHaveTypeParameters(this);
+		}
+		if (this.extendedDimensions != 0) {
+			scope.problemReporter().illegalExtendedDimensions(this);		
+		}		
+		if (this.binding == null) return;
+		TypeBinding returnTypeBinding = this.binding.returnType;
+		if (returnTypeBinding != null) {
+				
+			// annotation methods can only return base types, String, Class, enum type, annotation types and arrays of these
+			checkAnnotationMethodType: {
+				TypeBinding leafReturnType = returnTypeBinding.leafComponentType();
+					
+				switch (leafReturnType.erasure().id) {
+					case T_byte :
+					case T_short :
+					case T_char :
+					case T_int :
+					case T_long :
+					case T_float :
+					case T_double :
+					case T_boolean :
+					case T_JavaLangString :
+					case T_JavaLangClass :
+						if (returnTypeBinding.dimensions() <= 1) // only 1-dimensional array permitted
+							break checkAnnotationMethodType;
+				}
+				if (leafReturnType.isEnum()) {
+					if (returnTypeBinding.dimensions() <= 1) // only 1-dimensional array permitted
+						break checkAnnotationMethodType;
+				}
+				if (leafReturnType.isAnnotationType()) {
+					scope.classScope().detectAnnotationCycle(scope.enclosingSourceType(), leafReturnType, this.returnType);
+					if (returnTypeBinding.dimensions() <= 1) // only 1-dimensional array permitted
+						break checkAnnotationMethodType;
+				}
+				scope.problemReporter().invalidAnnotationMemberType(this);
+			}
+			if (this.defaultValue != null) {
+				MemberValuePair pair = new MemberValuePair(this.selector, this.sourceStart, this.sourceEnd, this.defaultValue);
+				pair.binding = this.binding;
+				pair.resolveTypeExpecting(scope, returnTypeBinding);
+			}
+		}
+	}
+
+	public void traverse(
+		ASTVisitor visitor,
+		ClassScope classScope) {
+
+		if (visitor.visit(this, classScope)) {
+			if (this.annotations != null) {
+				int annotationsLength = this.annotations.length;
+				for (int i = 0; i < annotationsLength; i++)
+					this.annotations[i].traverse(visitor, scope);
+			}
+			if (this.returnType != null) {
+				this.returnType.traverse(visitor, scope);
+			}
+			if (this.defaultValue != null) {
+				this.defaultValue.traverse(visitor, scope);
+			}
+		}
+		visitor.endVisit(this, classScope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
index b6669ac..4a75e07 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
@@ -18,7 +18,7 @@
 	
 	// prefix for setter method (to recognize special hiding argument)
 	private final static char[] SET = "set".toCharArray(); //$NON-NLS-1$
-
+	
 	public Argument(char[] name, long posNom, TypeReference tr, int modifiers) {
 
 		super(name, (int) (posNom >>> 32), (int) posNom);
@@ -31,11 +31,11 @@
 	public void bind(MethodScope scope, TypeBinding typeBinding, boolean used) {
 
 		if (this.type != null)
-			this.type.resolvedType = typeBinding;
+			this.type.resolvedType = typeBinding; // TODO (philippe) no longer necessary as when binding got resolved, it was recorded already (SourceTypeBinding#resolveTypesFor(MethodBinding))
 		// record the resolved type into the type reference
 		int modifierFlag = this.modifiers;
 
-		Binding existingVariable = scope.getBinding(name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
+		Binding existingVariable = scope.getBinding(name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
 		if (existingVariable != null && existingVariable.isValidBinding()){
 			if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) {
 				scope.problemReporter().redefineArgument(this);
@@ -58,17 +58,29 @@
 		scope.addLocalVariable(
 			this.binding =
 				new LocalVariableBinding(this, typeBinding, modifierFlag, true));
+		resolveAnnotations(scope, this.annotations, this.binding);		
 		//true stand for argument instead of just local
-		if (typeBinding != null && isTypeUseDeprecated(typeBinding, scope))
-			scope.problemReporter().deprecatedType(typeBinding, this.type);
 		this.binding.declaration = this;
 		this.binding.useFlag = used ? LocalVariableBinding.USED : LocalVariableBinding.UNUSED;
 	}
 
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
+	 */
+	public int getKind() {
+		return PARAMETER;
+	}
+
+	public boolean isVarArgs() {
+		return (this.type.bits & IsVarArgs) != 0;
+	}
+		
 	public StringBuffer print(int indent, StringBuffer output) {
 
 		printIndent(indent, output);
 		printModifiers(this.modifiers, output);
+		if (this.annotations != null) printAnnotations(this.annotations, output);
+		
 		if (type == null) {
 			output.append("<no type> "); //$NON-NLS-1$
 		} else {
@@ -88,11 +100,23 @@
 		// provide the scope with a side effect : insertion of a LOCAL
 		// that represents the argument. The type must be from JavaThrowable
 
-		TypeBinding tb = type.resolveTypeExpecting(scope, scope.getJavaLangThrowable());
-		if (tb == null)
+		TypeBinding exceptionType = this.type.resolveType(scope, true /* check bounds*/);
+		if (exceptionType == null) return null;
+		if (exceptionType.isGenericType() || exceptionType.isParameterizedType()) {
+			scope.problemReporter().invalidParameterizedExceptionType(exceptionType, this);
 			return null;
-
-		Binding existingVariable = scope.getBinding(name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
+		}
+		if (exceptionType.isTypeVariable()) {
+			scope.problemReporter().invalidTypeVariableAsException(exceptionType, this);
+			return null;
+		}		
+		TypeBinding throwable = scope.getJavaLangThrowable();
+		if (!exceptionType.isCompatibleWith(throwable)) {
+			scope.problemReporter().typeMismatchError(exceptionType, throwable, this);
+			return null;
+		}
+		
+		Binding existingVariable = scope.getBinding(name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
 		if (existingVariable != null && existingVariable.isValidBinding()){
 			if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) {
 				scope.problemReporter().redefineArgument(this);
@@ -101,10 +125,12 @@
 			scope.problemReporter().localVariableHiding(this, existingVariable, false);
 		}
 
-		binding = new LocalVariableBinding(this, tb, modifiers, false); // argument decl, but local var  (where isArgument = false)
+		this.binding = new LocalVariableBinding(this, exceptionType, modifiers, false); // argument decl, but local var  (where isArgument = false)
+		resolveAnnotations(scope, this.annotations, this.binding);
+		
 		scope.addLocalVariable(binding);
-		binding.constant = NotAConstant;
-		return tb;
+		binding.setConstant(NotAConstant);
+		return exceptionType;
 	}
 
 	public void traverse(ASTVisitor visitor, BlockScope scope) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
index d9ab28d..d1862ff 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
@@ -73,7 +73,7 @@
 		// Generate a sequence of bytecodes corresponding to an array allocation
 		if (this.resolvedType.dimensions() == 1) {
 			// Mono-dimensional array
-			codeStream.newArray(currentScope, (ArrayBinding)this.resolvedType);
+			codeStream.newArray((ArrayBinding)this.resolvedType);
 		} else {
 			// Multi-dimensional array
 			codeStream.multianewarray(this.resolvedType, nonNullDimensionsLength);
@@ -113,7 +113,7 @@
 		// only at the -end- like new int [4][][]. The parser allows new int[][4][]
 		// so this must be checked here......(this comes from a reduction to LL1 grammar)
 
-		TypeBinding referenceType = type.resolveType(scope);
+		TypeBinding referenceType = type.resolveType(scope, true /* check bounds*/);
 		
 		// will check for null after dimensions are checked
 		constant = Constant.NotAConstant;
@@ -124,12 +124,13 @@
 
 		// check the validity of the dimension syntax (and test for all null dimensions)
 		int explicitDimIndex = -1;
-		for (int i = dimensions.length; --i >= 0;) {
+		loop: for (int i = dimensions.length; --i >= 0;) {
 			if (dimensions[i] != null) {
 				if (explicitDimIndex < 0) explicitDimIndex = i;
-			} else if (explicitDimIndex> 0) {
+			} else if (explicitDimIndex > 0) {
 				// should not have an empty dimension before an non-empty one
-				scope.problemReporter().incorrectLocationForEmptyDimension(this, i);
+				scope.problemReporter().incorrectLocationForNonEmptyDimension(this, explicitDimIndex);
+				break loop;
 			}
 		}
 
@@ -139,6 +140,10 @@
 			if (explicitDimIndex < 0) {
 				scope.problemReporter().mustDefineDimensionsOrInitializer(this);
 			}
+			// allow new List<?>[5] - only check for generic array when no initializer, since also checked inside initializer resolution
+			if (referenceType != null && !referenceType.isReifiable()) {
+			    scope.problemReporter().illegalGenericArray(referenceType, this);
+			}
 		} else if (explicitDimIndex >= 0) {
 			scope.problemReporter().cannotDefineDimensionsAndInitializer(this);
 		}
@@ -148,7 +153,7 @@
 			if (dimensions[i] != null) {
 				TypeBinding dimensionType = dimensions[i].resolveTypeExpecting(scope, IntBinding);
 				if (dimensionType != null) {
-					dimensions[i].implicitWidening(IntBinding, dimensionType);
+					dimensions[i].computeConversion(scope, IntBinding, dimensionType);
 				}
 			}
 		}
@@ -158,7 +163,7 @@
 			if (dimensions.length > 255) {
 				scope.problemReporter().tooManyDimensions(this);
 			}
-			this.resolvedType = scope.createArray(referenceType, dimensions.length);
+			this.resolvedType = scope.createArrayType(referenceType, dimensions.length);
 
 			// check the initializer
 			if (initializer != null) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
index b717047..9310cf7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
@@ -47,7 +47,7 @@
 		int pc = codeStream.position;
 		int expressionLength = (expressions == null) ? 0: expressions.length;
 		codeStream.generateInlinedValue(expressionLength);
-		codeStream.newArray(currentScope, binding);
+		codeStream.newArray(binding);
 		if (expressions != null) {
 			// binding is an ArrayType, so I can just deal with the dimension
 			int elementsTypeID = binding.dimensions > 1 ? -1 : binding.leafComponentType.id;
@@ -101,7 +101,9 @@
 				}
 			}
 		}
-		if (!valueRequired) {
+		if (valueRequired) {
+			codeStream.generateImplicitConversion(this.implicitConversion);
+		} else {
 			codeStream.pop();
 		}
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
@@ -133,12 +135,19 @@
 	
 		// this method is recursive... (the test on isArrayType is the stop case)
 	
-		constant = NotAConstant;
+		this.constant = NotAConstant;
+		
+		// allow new List<?>[5]
+		TypeBinding leafComponentType = expectedTb.leafComponentType();
+		if (leafComponentType.isBoundParameterizedType() || leafComponentType.isGenericType() || leafComponentType.isTypeVariable()) {
+		    scope.problemReporter().illegalGenericArray(leafComponentType, this);
+		}
+			
 		if (expectedTb.isArrayType()) {
 			binding = (ArrayBinding) expectedTb;
 			if (expressions == null)
 				return binding;
-			TypeBinding expectedElementsTb = binding.elementsType(scope);
+			TypeBinding expectedElementsTb = binding.elementsType();
 			if (expectedElementsTb.isBaseType()) {
 				for (int i = 0, length = expressions.length; i < length; i++) {
 					Expression expression = expressions[i];
@@ -150,12 +159,14 @@
 						return null;
 	
 					// Compile-time conversion required?
-					if (expression.isConstantValueOfTypeAssignableToType(expressionTb, expectedElementsTb)) {
-						expression.implicitWidening(expectedElementsTb, expressionTb);
-					} else if (BaseTypeBinding.isWidening(expectedElementsTb.id, expressionTb.id)) {
-						expression.implicitWidening(expectedElementsTb, expressionTb);
+					if (expectedElementsTb != expressionTb) // must call before computeConversion() and typeMismatchError()
+						scope.compilationUnitScope().recordTypeConversion(expectedElementsTb, expressionTb);
+					if (expression.isConstantValueOfTypeAssignableToType(expressionTb, expectedElementsTb)
+						|| BaseTypeBinding.isWidening(expectedElementsTb.id, expressionTb.id)
+						|| scope.isBoxingCompatibleWith(expressionTb, expectedElementsTb)) {
+							expression.computeConversion(scope, expectedElementsTb, expressionTb);
 					} else {
-						scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionTb, expectedElementsTb);
+						scope.problemReporter().typeMismatchError(expressionTb, expectedElementsTb, expression);
 						return null;
 					}
 				}
@@ -189,8 +200,8 @@
 			}
 		}
 		if (leafElementType != null) {
-			TypeBinding probableTb = scope.createArray(leafElementType, dim);
-			scope.problemReporter().typeMismatchErrorActualTypeExpectedType(this, probableTb, expectedTb);
+			TypeBinding probableTb = scope.createArrayType(leafElementType, dim);
+			scope.problemReporter().typeMismatchError(probableTb, expectedTb, this);
 		}
 		return null;
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
index 701f3a6..6c6d1ad 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
@@ -10,8 +10,10 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 
 public class ArrayQualifiedTypeReference extends QualifiedTypeReference {
 	int dimensions;
@@ -22,32 +24,57 @@
 		dimensions = dim ;
 	}
 	
-	public ArrayQualifiedTypeReference(char[][] sources , TypeBinding tb, int dim, long[] poss) {
-		
-		super( sources , tb, poss);
-		dimensions = dim ;
-	}
-	
 	public int dimensions() {
 		
 		return dimensions;
 	}
+
+	/**
+	 * @return char[][]
+	 */
+	public char [][] getParameterizedTypeName(){
+		int dim = this.dimensions;
+		char[] dimChars = new char[dim*2];
+		for (int i = 0; i < dim; i++) {
+			int index = i*2;
+			dimChars[index] = '[';
+			dimChars[index+1] = ']';
+		}
+		int length = this.tokens.length;
+		char[][] qParamName = new char[length][];
+		System.arraycopy(this.tokens, 0, qParamName, 0, length-1);
+		qParamName[length-1] = CharOperation.concat(this.tokens[length-1], dimChars);
+		return qParamName;
+	}	
 	
-	public TypeBinding getTypeBinding(Scope scope) {
+	protected TypeBinding getTypeBinding(Scope scope) {
 		
 		if (this.resolvedType != null)
 			return this.resolvedType;
 		if (dimensions > 255) {
 			scope.problemReporter().tooManyDimensions(this);
 		}
-		return scope.createArray(scope.getType(tokens), dimensions);
+		try {
+			TypeBinding leafComponentType = scope.getType(this.tokens, this.tokens.length);
+			return scope.createArrayType(leafComponentType, dimensions);
+		} catch (AbortCompilation e) {
+			e.updateContext(this, scope.referenceCompilationUnit().compilationResult);
+			throw e;
+		}
 	}
 	
 	public StringBuffer printExpression(int indent, StringBuffer output){
 		
 		super.printExpression(indent, output);
-		for (int i = 0 ; i < dimensions ; i++) {
-			output.append("[]"); //$NON-NLS-1$
+		if ((this.bits & IsVarArgs) != 0) {
+			for (int i= 0 ; i < dimensions - 1; i++) {
+				output.append("[]"); //$NON-NLS-1$
+			}
+			output.append("..."); //$NON-NLS-1$
+		} else {
+			for (int i= 0 ; i < dimensions; i++) {
+				output.append("[]"); //$NON-NLS-1$
+			}
 		}
 		return output;
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
index 915b347..fc0bb69 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
@@ -51,10 +51,9 @@
 		FlowContext flowContext,
 		FlowInfo flowInfo) {
 
-		return position.analyseCode(
-			currentScope,
-			flowContext,
-			receiver.analyseCode(currentScope, flowContext, flowInfo));
+		flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo);
+		receiver.checkNullStatus(currentScope, flowContext, flowInfo, FlowInfo.NON_NULL);
+		return position.analyseCode(currentScope, flowContext, flowInfo);
 	}
 
 	public void generateAssignment(
@@ -123,21 +122,25 @@
 		codeStream.dup2();
 		codeStream.arrayAt(this.resolvedType.id);
 		int operationTypeID;
-		if ((operationTypeID = implicitConversion >> 4) == T_String) {
-			codeStream.generateStringAppend(currentScope, null, expression);
-		} else {
-			// promote the array reference to the suitable operation type
-			codeStream.generateImplicitConversion(implicitConversion);
-			// generate the increment value (will by itself  be promoted to the operation value)
-			if (expression == IntLiteral.One) { // prefix operation
-				codeStream.generateConstant(expression.constant, implicitConversion);
-			} 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);
+		switch(operationTypeID = (implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
+			case T_JavaLangString :
+			case T_JavaLangObject :
+			case T_undefined :
+				codeStream.generateStringConcatenationAppend(currentScope, null, expression);
+				break;
+			default :
+				// 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);
 		}
 		codeStream.arrayAtPut(this.resolvedType.id, valueRequired);
 	}
@@ -164,10 +167,11 @@
 				codeStream.dup_x2();
 			}
 		}
+		codeStream.generateImplicitConversion(implicitConversion);		
 		codeStream.generateConstant(
 			postIncrement.expression.constant,
 			implicitConversion);
-		codeStream.sendOperator(postIncrement.operator, this.resolvedType.id);
+		codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
 		codeStream.generateImplicitConversion(
 			postIncrement.assignmentImplicitConversion);
 		codeStream.arrayAtPut(this.resolvedType.id, false);
@@ -188,15 +192,16 @@
 		}		
 		TypeBinding arrayType = receiver.resolveType(scope);
 		if (arrayType != null) {
+			receiver.computeConversion(scope, arrayType, arrayType);
 			if (arrayType.isArrayType()) {
-				this.resolvedType = ((ArrayBinding) arrayType).elementsType(scope);
+				this.resolvedType = ((ArrayBinding) arrayType).elementsType();
 			} else {
 				scope.problemReporter().referenceMustBeArrayTypeAt(arrayType, this);
 			}
 		}
 		TypeBinding positionType = position.resolveTypeExpecting(scope, IntBinding);
 		if (positionType != null) {
-			position.implicitWidening(IntBinding, positionType);
+			position.computeConversion(scope, IntBinding, positionType);
 		}
 		return this.resolvedType;
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
index eec8865..66d9947 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
@@ -10,11 +10,16 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
-import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 
 public class ArrayTypeReference extends SingleTypeReference {
 	public int dimensions;
+	public int originalSourceEnd;
 
 	/**
 	 * ArrayTypeReference constructor comment.
@@ -25,12 +30,7 @@
 	public ArrayTypeReference(char[] source, int dimensions, long pos) {
 		
 		super(source, pos);
-		this.dimensions = dimensions ;
-	}
-	
-	public ArrayTypeReference(char[] source, TypeBinding tb, int dimensions, long pos) {
-		
-		super(source, tb, pos);
+		this.originalSourceEnd = this.sourceEnd;
 		this.dimensions = dimensions ;
 	}
 	
@@ -38,22 +38,42 @@
 		
 		return dimensions;
 	}
-	
-	public TypeBinding getTypeBinding(Scope scope) {
+	/**
+	 * @return char[][]
+	 */
+	public char [][] getParameterizedTypeName(){
+		int dim = this.dimensions;
+		char[] dimChars = new char[dim*2];
+		for (int i = 0; i < dim; i++) {
+			int index = i*2;
+			dimChars[index] = '[';
+			dimChars[index+1] = ']';
+		}
+		return new char[][]{ CharOperation.concat(token, dimChars) };
+	}	
+	protected TypeBinding getTypeBinding(Scope scope) {
 		
 		if (this.resolvedType != null) return this.resolvedType;
 		if (dimensions > 255) {
 			scope.problemReporter().tooManyDimensions(this);
 		}
-		return scope.createArray(scope.getType(token), dimensions);
+		TypeBinding leafComponentType = scope.getType(token);
+		return scope.createArrayType(leafComponentType, dimensions);
 	
 	}
 	
 	public StringBuffer printExpression(int indent, StringBuffer output){
 	
-		super.printExpression(indent, output)  ;
-		for (int i= 0 ; i < dimensions ; i++) {
-			output.append("[]"); //$NON-NLS-1$
+		super.printExpression(indent, output);
+		if ((this.bits & IsVarArgs) != 0) {
+			for (int i= 0 ; i < dimensions - 1; i++) {
+				output.append("[]"); //$NON-NLS-1$
+			}
+			output.append("..."); //$NON-NLS-1$
+		} else {
+			for (int i= 0 ; i < dimensions; i++) {
+				output.append("[]"); //$NON-NLS-1$
+			}
 		}
 		return output;
 	}
@@ -63,4 +83,10 @@
 		visitor.visit(this, scope);
 		visitor.endVisit(this, scope);
 	}
+	
+	public void traverse(ASTVisitor visitor, ClassScope scope) {
+		
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java
index cf3093a..dedee1f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
@@ -128,7 +129,7 @@
 					case T_void :
 						scope.problemReporter().illegalVoidExpression(exceptionArgument);
 					default:
-					    id = T_Object;
+					    id = T_JavaLangObject;
 					case T_boolean :
 					case T_byte :
 					case T_char :
@@ -137,7 +138,7 @@
 					case T_float :
 					case T_int :
 					case T_long :
-					case T_String :
+					case T_JavaLangString :
 						exceptionArgument.implicitConversion = (id << 4) + id;
 				}
 			}
@@ -168,7 +169,7 @@
 			outerMostClass = (SourceTypeBinding) enclosing;
 		}
 
-		this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticField(this, currentScope);
+		this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticFieldForAssert(currentScope);
 
 		// find <clinit> and enable assertion support
 		TypeDeclaration typeDeclaration = outerMostClass.scope.referenceType();
@@ -176,7 +177,7 @@
 		for (int i = 0, max = methods.length; i < max; i++) {
 			AbstractMethodDeclaration method = methods[i];
 			if (method.isClinit()) {
-				((Clinit) method).setAssertionSupport(assertionSyntheticFieldBinding);
+				((Clinit) method).setAssertionSupport(assertionSyntheticFieldBinding, currentScope.environment().options.sourceLevel < ClassFileConstants.JDK1_5);
 				break;
 			}
 		}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
index 5b86ade..e43c286 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
@@ -42,9 +42,25 @@
 		// a field reference, a blank final field reference, a field of an enclosing instance or 
 		// just a local variable.
 
-		return ((Reference) lhs)
+		LocalVariableBinding local = this.lhs.localVariableBinding();
+		int nullStatus = this.expression.nullStatus(flowInfo);
+		if (local != null && nullStatus == FlowInfo.NULL) {
+				flowContext.recordUsingNullReference(currentScope, local, this.lhs, FlowInfo.NON_NULL, flowInfo);
+		}
+		flowInfo = ((Reference) lhs)
 			.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
 			.unconditionalInits();
+		if (local != null) {
+			switch(nullStatus) {
+				case FlowInfo.NULL :
+					flowInfo.markAsDefinitelyNull(local);
+					break;
+				case FlowInfo.NON_NULL :
+					flowInfo.markAsDefinitelyNonNull(local);
+					break;
+			}
+		}		
+		return flowInfo;
 	}
 
 	void checkAssignmentEffect(BlockScope scope) {
@@ -56,6 +72,19 @@
 		}
 	}
 
+	void checkAssignment(BlockScope scope, TypeBinding lhsType, TypeBinding rhsType) {
+		
+		FieldBinding leftField = getLastField(this.lhs);
+		if (leftField != null &&  rhsType != NullBinding && lhsType.isWildcard() && ((WildcardBinding)lhsType).kind != Wildcard.SUPER) {
+		    scope.problemReporter().wildcardAssignment(lhsType, rhsType, this.expression);
+		} else if (leftField != null && leftField.declaringClass != null /*length pseudo field*/&& leftField.declaringClass.isRawType() 
+		        && (rhsType.isParameterizedType() || rhsType.isGenericType())) {
+		    scope.problemReporter().unsafeRawFieldAssignment(leftField, rhsType, this.lhs);
+		} else if (rhsType.needsUncheckedConversion(lhsType)) {
+		    scope.problemReporter().unsafeRawConversion(this.expression, rhsType, lhsType);
+		}		
+	}
+	
 	public void generateCode(
 		BlockScope currentScope,
 		CodeStream codeStream,
@@ -89,6 +118,28 @@
 		}
 		return null;
 	}
+	FieldBinding getLastField(Expression someExpression) {
+	    if (someExpression instanceof SingleNameReference) {
+	        if ((someExpression.bits & RestrictiveFlagMASK) == Binding.FIELD) {
+	            return (FieldBinding) ((SingleNameReference)someExpression).binding;
+	        }
+	    } else if (someExpression instanceof FieldReference) {
+	        return ((FieldReference)someExpression).binding;
+	    } else if (someExpression instanceof QualifiedNameReference) {
+	        QualifiedNameReference qName = (QualifiedNameReference) someExpression;
+	        if (qName.otherBindings == null && ((someExpression.bits & RestrictiveFlagMASK) == Binding.FIELD)) {
+	            return (FieldBinding)qName.binding;
+	        } else {
+	            return qName.otherBindings[qName.otherBindings.length - 1];
+	        }
+	    }
+	    return null;
+	}	
+
+	public int nullStatus(FlowInfo flowInfo) {
+		return this.expression.nullStatus(flowInfo);
+	}
+	
 	public StringBuffer print(int indent, StringBuffer output) {
 
 		//no () when used as a statement 
@@ -122,26 +173,30 @@
 			scope.problemReporter().expressionShouldBeAVariable(this.lhs);
 			return null;
 		}
-		this.resolvedType = lhs.resolveType(scope); // expressionType contains the assignment type (lhs Type)
+		TypeBinding lhsType = this.resolvedType = lhs.resolveType(scope);
+		expression.setExpectedType(lhsType); // needed in case of generic method invocation
 		TypeBinding rhsType = expression.resolveType(scope);
-		if (this.resolvedType == null || rhsType == null) {
+		if (lhsType == null || rhsType == null) {
 			return null;
 		}
 		checkAssignmentEffect(scope);
-				
+
 		// Compile-time conversion of base-types : implicit narrowing integer into byte/short/character
 		// may require to widen the rhs expression at runtime
-		if ((expression.isConstantValueOfTypeAssignableToType(rhsType, this.resolvedType)
-				|| (this.resolvedType.isBaseType() && BaseTypeBinding.isWidening(this.resolvedType.id, rhsType.id)))
-				|| rhsType.isCompatibleWith(this.resolvedType)) {
-			expression.implicitWidening(this.resolvedType, rhsType);
+		if (lhsType != rhsType) // must call before computeConversion() and typeMismatchError()
+			scope.compilationUnitScope().recordTypeConversion(lhsType, rhsType);
+		if ((expression.isConstantValueOfTypeAssignableToType(rhsType, lhsType)
+				|| (lhsType.isBaseType() && BaseTypeBinding.isWidening(lhsType.id, rhsType.id)))
+				|| rhsType.isCompatibleWith(lhsType)) {
+			expression.computeConversion(scope, lhsType, rhsType);
+			checkAssignment(scope, lhsType, rhsType);
 			return this.resolvedType;
-		}
-		scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
-			expression,
-			rhsType,
-			this.resolvedType);
-		return this.resolvedType;
+		} else if (scope.isBoxingCompatibleWith(rhsType, lhsType)) {
+			expression.computeConversion(scope, lhsType, rhsType);
+			return this.resolvedType;
+		} 
+		scope.problemReporter().typeMismatchError(rhsType, lhsType, expression);
+		return lhsType;
 	}
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveTypeExpecting(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
@@ -151,13 +206,16 @@
 			TypeBinding expectedType) {
 
 		TypeBinding type = super.resolveTypeExpecting(scope, expectedType);
+		if (type == null) return null;
+		TypeBinding lhsType = this.resolvedType; 
+		TypeBinding rhsType = this.expression.resolvedType;
 		// signal possible accidental boolean assignment (instead of using '==' operator)
 		if (expectedType == BooleanBinding 
-				&& this.lhs.resolvedType == BooleanBinding 
+				&& lhsType == BooleanBinding 
 				&& (this.lhs.bits & IsStrictlyAssignedMASK) != 0) {
 			scope.problemReporter().possibleAccidentalBooleanAssignment(this);
 		}
-
+		checkAssignment(scope, lhsType, rhsType);
 		return type;
 	}
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
index b5804d0..d5a0b3e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
@@ -96,8 +96,8 @@
 		switch ((bits & OperatorMASK) >> OperatorSHIFT) {
 			case PLUS :
 				switch (bits & ReturnTypeIDMASK) {
-					case T_String :
-						codeStream.generateStringAppend(currentScope, left, right);
+					case T_JavaLangString :
+						codeStream.generateStringConcatenationAppend(currentScope, left, right);
 						if (!valueRequired)
 							codeStream.pop();
 						break;
@@ -699,7 +699,7 @@
 		Label falseLabel,
 		boolean valueRequired) {
 
-		int promotedTypeID = left.implicitConversion >> 4;
+		int promotedTypeID = (left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
 		// both sides got promoted in the same way
 		if (promotedTypeID == T_int) {
 			// 0 > x
@@ -813,7 +813,7 @@
 		Label falseLabel,
 		boolean valueRequired) {
 
-		int promotedTypeID = left.implicitConversion >> 4;
+		int promotedTypeID = (left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
 		// both sides got promoted in the same way
 		if (promotedTypeID == T_int) {
 			// 0 >= x
@@ -927,7 +927,7 @@
 		Label falseLabel,
 		boolean valueRequired) {
 
-		int promotedTypeID = left.implicitConversion >> 4;
+		int promotedTypeID = (left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
 		// both sides got promoted in the same way
 		if (promotedTypeID == T_int) {
 			// 0 < x
@@ -1037,7 +1037,7 @@
 		Label falseLabel,
 		boolean valueRequired) {
 
-		int promotedTypeID = left.implicitConversion >> 4;
+		int promotedTypeID = (left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
 		// both sides got promoted in the same way
 		if (promotedTypeID == T_int) {
 			// 0 <= x
@@ -1152,7 +1152,7 @@
 		boolean valueRequired) {
 			
 		Constant condConst;
-		if ((left.implicitConversion & 0xF) == T_boolean) {
+		if ((left.implicitConversion & COMPILE_TYPE_MASK) == T_boolean) {
 			if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
 				if (condConst.booleanValue() == true) {
 					// <something equivalent to true> & x
@@ -1290,7 +1290,7 @@
 		boolean valueRequired) {
 			
 		Constant condConst;
-		if ((left.implicitConversion & 0xF) == T_boolean) {
+		if ((left.implicitConversion & COMPILE_TYPE_MASK) == T_boolean) {
 			if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
 				if (condConst.booleanValue() == true) {
 					// <something equivalent to true> | x
@@ -1426,7 +1426,7 @@
 		boolean valueRequired) {
 			
 		Constant condConst;
-		if ((left.implicitConversion & 0xF) == T_boolean) {
+		if ((left.implicitConversion & COMPILE_TYPE_MASK) == T_boolean) {
 			if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
 				if (condConst.booleanValue() == true) {
 					// <something equivalent to true> ^ x
@@ -1525,7 +1525,7 @@
 		codeStream.updateLastRecordedEndPC(codeStream.position);					
 	}
 	
-	public void generateOptimizedStringBuffer(
+	public void generateOptimizedStringConcatenation(
 		BlockScope blockScope,
 		CodeStream codeStream,
 		int typeID) {
@@ -1536,30 +1536,30 @@
 		 */
 
 		if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
-			&& ((bits & ReturnTypeIDMASK) == T_String)) {
+			&& ((bits & ReturnTypeIDMASK) == T_JavaLangString)) {
 			if (constant != NotAConstant) {
 				codeStream.generateConstant(constant, implicitConversion);
-				codeStream.invokeStringBufferAppendForType(implicitConversion & 0xF);
+				codeStream.invokeStringConcatenationAppendForType(implicitConversion & COMPILE_TYPE_MASK);
 			} else {
 				int pc = codeStream.position;
-				left.generateOptimizedStringBuffer(
+				left.generateOptimizedStringConcatenation(
 					blockScope,
 					codeStream,
-					left.implicitConversion & 0xF);
+					left.implicitConversion & COMPILE_TYPE_MASK);
 				codeStream.recordPositionsFrom(pc, left.sourceStart);
 				pc = codeStream.position;
-				right.generateOptimizedStringBuffer(
+				right.generateOptimizedStringConcatenation(
 					blockScope,
 					codeStream,
-					right.implicitConversion & 0xF);
+					right.implicitConversion & COMPILE_TYPE_MASK);
 				codeStream.recordPositionsFrom(pc, right.sourceStart);
 			}
 		} else {
-			super.generateOptimizedStringBuffer(blockScope, codeStream, typeID);
+			super.generateOptimizedStringConcatenation(blockScope, codeStream, typeID);
 		}
 	}
 	
-	public void generateOptimizedStringBufferCreation(
+	public void generateOptimizedStringConcatenationCreation(
 		BlockScope blockScope,
 		CodeStream codeStream,
 		int typeID) {
@@ -1570,29 +1570,29 @@
 		 */
 
 		if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
-			&& ((bits & ReturnTypeIDMASK) == T_String)) {
+			&& ((bits & ReturnTypeIDMASK) == T_JavaLangString)) {
 			if (constant != NotAConstant) {
-				codeStream.newStringBuffer(); // new: java.lang.StringBuffer
+				codeStream.newStringContatenation(); // new: java.lang.StringBuffer
 				codeStream.dup();
 				codeStream.ldc(constant.stringValue());
-				codeStream.invokeStringBufferStringConstructor();
+				codeStream.invokeStringConcatenationStringConstructor();
 				// invokespecial: java.lang.StringBuffer.<init>(Ljava.lang.String;)V
 			} else {
 				int pc = codeStream.position;
-				left.generateOptimizedStringBufferCreation(
+				left.generateOptimizedStringConcatenationCreation(
 					blockScope,
 					codeStream,
-					left.implicitConversion & 0xF);
+					left.implicitConversion & COMPILE_TYPE_MASK);
 				codeStream.recordPositionsFrom(pc, left.sourceStart);
 				pc = codeStream.position;
-				right.generateOptimizedStringBuffer(
+				right.generateOptimizedStringConcatenation(
 					blockScope,
 					codeStream,
-					right.implicitConversion & 0xF);
+					right.implicitConversion & COMPILE_TYPE_MASK);
 				codeStream.recordPositionsFrom(pc, right.sourceStart);
 			}
 		} else {
-			super.generateOptimizedStringBufferCreation(blockScope, codeStream, typeID);
+			super.generateOptimizedStringConcatenationCreation(blockScope, codeStream, typeID);
 		}
 	}
 	
@@ -1670,14 +1670,27 @@
 			constant = Constant.NotAConstant;
 			return null;
 		}
-		int leftTypeId = leftType.id;
-		int rightTypeId = rightType.id;
-		if (leftTypeId > 15
-			|| rightTypeId > 15) { // must convert String + Object || Object + String
-			if (leftTypeId == T_String) {
-				rightTypeId = T_Object;
-			} else if (rightTypeId == T_String) {
-				leftTypeId = T_Object;
+
+		int leftTypeID = leftType.id;
+		int rightTypeID = rightType.id;
+
+		// autoboxing support
+		LookupEnvironment env = scope.environment();
+		boolean use15specifics = env.options.sourceLevel >= JDK1_5;
+		if (use15specifics) {
+			if (!leftType.isBaseType() && rightTypeID != T_JavaLangString && rightTypeID != T_null) {
+				leftTypeID = env.computeBoxingType(leftType).id;
+			}
+			if (!rightType.isBaseType() && leftTypeID != T_JavaLangString && leftTypeID != T_null) {
+				rightTypeID = env.computeBoxingType(rightType).id;
+			}
+		}
+		if (leftTypeID > 15
+			|| rightTypeID > 15) { // must convert String + Object || Object + String
+			if (leftTypeID == T_JavaLangString) {
+				rightTypeID = T_JavaLangObject;
+			} else if (rightTypeID == T_JavaLangString) {
+				leftTypeID = T_JavaLangObject;
 			} else {
 				constant = Constant.NotAConstant;
 				scope.problemReporter().invalidOperator(this, leftType, rightType);
@@ -1685,14 +1698,17 @@
 			}
 		}
 		if (((bits & OperatorMASK) >> OperatorSHIFT) == PLUS) {
-			if (leftTypeId == T_String
-					&& rightType.isArrayType()
-					&& ((ArrayBinding) rightType).elementsType(scope) == CharBinding) {
-				scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(right);
-					} else if (rightTypeId == T_String
-							&& leftType.isArrayType()
-							&& ((ArrayBinding) leftType).elementsType(scope) == CharBinding) {
-				scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(left);
+			if (leftTypeID == T_JavaLangString) {
+				this.left.computeConversion(scope, leftType, leftType);
+				if (rightType.isArrayType() && ((ArrayBinding) rightType).elementsType() == CharBinding) {
+					scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(right);
+				}
+			}
+			if (rightTypeID == T_JavaLangString) {
+				this.right.computeConversion(scope, rightType, rightType);
+				if (leftType.isArrayType() && ((ArrayBinding) leftType).elementsType() == CharBinding) {
+					scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(left);
+				}
 			}
 		}
 
@@ -1704,10 +1720,10 @@
 		// Don't test for result = 0. If it is zero, some more work is done.
 		// On the one hand when it is not zero (correct code) we avoid doing the test	
 		int operator = (bits & OperatorMASK) >> OperatorSHIFT;
-		int operatorSignature = OperatorSignatures[operator][(leftTypeId << 4) + rightTypeId];
-		left.implicitConversion = operatorSignature >>> 12;
-		right.implicitConversion = (operatorSignature >>> 4) & 0x000FF;
+		int operatorSignature = OperatorSignatures[operator][(leftTypeID << 4) + rightTypeID];
 
+		left.computeConversion(	scope, 	TypeBinding.wellKnownType(scope, (operatorSignature >>> 16) & 0x0000F), leftType);
+		right.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 8) & 0x0000F), rightType);
 		bits |= operatorSignature & 0xF;
 		switch (operatorSignature & 0xF) { // record the current ReturnTypeID
 			// only switch on possible result type.....
@@ -1732,7 +1748,7 @@
 			case T_long :
 				this.resolvedType = LongBinding;
 				break;
-			case T_String :
+			case T_JavaLangString :
 				this.resolvedType = scope.getJavaLangString();
 				break;
 			default : //error........
@@ -1743,10 +1759,10 @@
 
 		// check need for operand cast
 		if (leftIsCast || rightIsCast) {
-			CastExpression.checkNeedForArgumentCasts(scope, operator, operatorSignature, left, leftTypeId, leftIsCast, right, rightTypeId, rightIsCast);
+			CastExpression.checkNeedForArgumentCasts(scope, operator, operatorSignature, left, leftTypeID, leftIsCast, right, rightTypeID, rightIsCast);
 		}
 		// compute the constant when valid
-		computeConstant(scope, leftTypeId, rightTypeId);
+		computeConstant(scope, leftTypeID, rightTypeID);
 		return this.resolvedType;
 	}
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
index 56380f7..ea3a9ae 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
@@ -20,6 +20,8 @@
 	
 	public Expression constantExpression;
 	public CaseLabel targetLabel;
+	boolean isEnumConstant;
+	
 	public CaseStatement(Expression constantExpression, int sourceEnd, int sourceStart) {
 		this.constantExpression = constantExpression;
 		this.sourceEnd = sourceEnd;
@@ -32,7 +34,7 @@
 		FlowInfo flowInfo) {
 
 		if (constantExpression != null) {
-			if (constantExpression.constant == NotAConstant) {
+			if (!this.isEnumConstant && constantExpression.constant == NotAConstant) {
 				currentScope.problemReporter().caseExpressionMustBeConstant(constantExpression);
 			}
 			this.constantExpression.analyseCode(currentScope, flowContext, flowInfo);
@@ -73,9 +75,13 @@
 		// no-op : should use resolveCase(...) instead.
 	}
 
+	/**
+	 * Returns the constant intValue or ordinal for enum constants. If constant is NotAConstant, then answers Float.MIN_VALUE
+	 * @see org.eclipse.jdt.internal.compiler.ast.Statement#resolveCase(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.ast.SwitchStatement)
+	 */
 	public Constant resolveCase(
 		BlockScope scope,
-		TypeBinding switchType,
+		TypeBinding switchExpressionType,
 		SwitchStatement switchStatement) {
 
 	    scope.switchCase = this; // record entering in a switch case block
@@ -87,21 +93,36 @@
 	
 			// on error the last default will be the selected one ...	
 			switchStatement.defaultCase = this;
-			return null;
+			return NotAConstant;
 		}
 		// add into the collection of cases of the associated switch statement
 		switchStatement.cases[switchStatement.caseCount++] = this;
+		// tag constant name with enum type for privileged access to its members
+		if (switchExpressionType.isEnum() && (constantExpression instanceof SingleNameReference)) {
+			((SingleNameReference) constantExpression).setActualReceiverType((ReferenceBinding)switchExpressionType);
+		}
 		TypeBinding caseType = constantExpression.resolveType(scope);
-		if (caseType == null || switchType == null) return null;
-		if (constantExpression.isConstantValueOfTypeAssignableToType(caseType, switchType))
+		if (caseType == null || switchExpressionType == null) return NotAConstant;
+		if (constantExpression.isConstantValueOfTypeAssignableToType(caseType, switchExpressionType)
+				|| caseType.isCompatibleWith(switchExpressionType)) {
+			if (caseType.isEnum()) {
+				this.isEnumConstant = true;
+				if (constantExpression instanceof NameReference
+						&& (constantExpression.bits & RestrictiveFlagMASK) == Binding.FIELD) {
+					if (constantExpression instanceof QualifiedNameReference) {
+						 scope.problemReporter().cannotUseQualifiedEnumConstantInCaseLabel((QualifiedNameReference)constantExpression);
+					}
+					return Constant.fromValue(((NameReference)constantExpression).fieldBinding().id); // ordinal value
+				}
+			} else {
+				return constantExpression.constant;
+			}
+		} else if (scope.isBoxingCompatibleWith(switchExpressionType, caseType)) {
+			constantExpression.computeConversion(scope, caseType, switchExpressionType);
 			return constantExpression.constant;
-		if (caseType.isCompatibleWith(switchType))
-			return constantExpression.constant;
-		scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
-			constantExpression,
-			caseType,
-			switchType);
-		return null;
+		}
+		scope.problemReporter().typeMismatchError(caseType, switchExpressionType, constantExpression);
+		return NotAConstant;
 	}
 
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
index ecfe767..bdf85b2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
@@ -11,7 +11,6 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
@@ -23,6 +22,7 @@
 
 	public Expression expression;
 	public Expression type;
+	public TypeBinding expectedType; // when assignment conversion to a given expected type: String s = (String) t;
 	
 	//expression.implicitConversion holds the cast for baseType casting 
 	public CastExpression(Expression expression, Expression type) {
@@ -54,172 +54,6 @@
 	}
 
 	/**
-	 * Returns false if the cast is unnecessary
-	 */
-	public final boolean checkCastTypesCompatibility(
-		BlockScope scope,
-		TypeBinding castType,
-		TypeBinding expressionType) {
-	
-		// see specifications 5.5
-		// handle errors and process constant when needed
-	
-		// if either one of the type is null ==>
-		// some error has been already reported some where ==>
-		// we then do not report an obvious-cascade-error.
-	
-		if (castType == null || expressionType == null) return true;
-	
-		// identity conversion cannot be performed upfront, due to side-effects
-		// like constant propagation
-				
-		if (castType.isBaseType()) {
-			if (expressionType.isBaseType()) {
-				if (expressionType == castType) {
-					expression.implicitWidening(castType, expressionType);
-					constant = expression.constant; //use the same constant
-					return false;
-				}
-				boolean necessary = false;
-				if (expressionType.isCompatibleWith(castType)
-						|| (necessary = BaseTypeBinding.isNarrowing(castType.id, expressionType.id))) {
-					expression.implicitConversion = (castType.id << 4) + expressionType.id;
-					if (expression.constant != Constant.NotAConstant) {
-						constant = expression.constant.castTo(expression.implicitConversion);
-					}
-					return necessary;
-					
-				}
-			}
-			scope.problemReporter().typeCastError(this, castType, expressionType);
-			return true;
-		}
-	
-		//-----------cast to something which is NOT a base type--------------------------	
-		if (expressionType == NullBinding) {
-			//	if (castType.isArrayType()){ // 26903 - need checkcast when casting null to array type
-			//		needRuntimeCheckcast = true;
-			//	}
-			return false; //null is compatible with every thing
-		}
-		if (expressionType.isBaseType()) {
-			scope.problemReporter().typeCastError(this, castType, expressionType);
-			return true;
-		}
-	
-		if (expressionType.isArrayType()) {
-			if (castType == expressionType) return false; // identity conversion
-	
-			if (castType.isArrayType()) {
-				//------- (castType.isArray) expressionType.isArray -----------
-				TypeBinding exprElementType = ((ArrayBinding) expressionType).elementsType(scope);
-				if (exprElementType.isBaseType()) {
-					// <---stop the recursion------- 
-					if (((ArrayBinding) castType).elementsType(scope) == exprElementType) {
-						this.bits |= NeedRuntimeCheckCastMASK;
-					} else {
-						scope.problemReporter().typeCastError(this, castType, expressionType);
-					}
-					return true;
-				}
-				// recursively on the elements...
-				return checkCastTypesCompatibility(
-					scope,
-					((ArrayBinding) castType).elementsType(scope),
-					exprElementType);
-			} else if (
-				castType.isClass()) {
-				//------(castType.isClass) expressionType.isArray ---------------	
-				if (castType.id == T_Object) {
-					return false;
-				}
-			} else { //------- (castType.isInterface) expressionType.isArray -----------
-				if (castType.id == T_JavaLangCloneable || castType.id == T_JavaIoSerializable) {
-					this.bits |= NeedRuntimeCheckCastMASK;
-					return true;
-				}
-			}
-			scope.problemReporter().typeCastError(this, castType, expressionType);
-			return true;
-		}
-	
-		if (expressionType.isClass()) {
-			if (castType.isArrayType()) {
-				// ---- (castType.isArray) expressionType.isClass -------
-				if (expressionType.id == T_Object) { // potential runtime error
-					this.bits |= NeedRuntimeCheckCastMASK;
-					return true;
-				}
-			} else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isClass ------
-				if (expressionType.isCompatibleWith(castType)){ // no runtime error
-					if (castType.id == T_String) constant = expression.constant; // (String) cst is still a constant
-					return false;
-				}
-				if (castType.isCompatibleWith(expressionType)) {
-					// potential runtime  error
-					this.bits |= NeedRuntimeCheckCastMASK;
-					return true;
-				}
-			} else { // ----- (castType.isInterface) expressionType.isClass -------  
-				if (expressionType.isCompatibleWith(castType)) 
-					return false;
-				if (!((ReferenceBinding) expressionType).isFinal()) {
-					// a subclass may implement the interface ==> no check at compile time
-					this.bits |= NeedRuntimeCheckCastMASK;
-					return true;				    
-				}
-				// no subclass for expressionType, thus compile-time check is valid
-			}
-			scope.problemReporter().typeCastError(this, castType, expressionType);
-			return true;
-		}
-	
-		//	if (expressionType.isInterface()) { cannot be anything else
-		if (castType.isArrayType()) {
-			// ----- (castType.isArray) expressionType.isInterface ------
-			if (expressionType.id == T_JavaLangCloneable
-					|| expressionType.id == T_JavaIoSerializable) {// potential runtime error
-				this.bits |= NeedRuntimeCheckCastMASK;
-			} else {
-				scope.problemReporter().typeCastError(this, castType, expressionType);
-			}
-			return true;
-		} else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isInterface --------
-			if (castType.id == T_Object) { // no runtime error
-				return false;
-			}
-			if (((ReferenceBinding) castType).isFinal()) {
-				// no subclass for castType, thus compile-time check is valid
-				if (!castType.isCompatibleWith(expressionType)) {
-					// potential runtime error
-					scope.problemReporter().typeCastError(this, castType, expressionType);
-					return true;
-				}
-			}
-		} else { // ----- (castType.isInterface) expressionType.isInterface -------
-			if (expressionType.isCompatibleWith(castType)) {
-				return false; 
-			}
-			if (!castType.isCompatibleWith(expressionType)) {
-				MethodBinding[] castTypeMethods = ((ReferenceBinding) castType).methods();
-				MethodBinding[] expressionTypeMethods =
-					((ReferenceBinding) expressionType).methods();
-				int exprMethodsLength = expressionTypeMethods.length;
-				for (int i = 0, castMethodsLength = castTypeMethods.length; i < castMethodsLength; i++)
-					for (int j = 0; j < exprMethodsLength; j++) {
-						if ((castTypeMethods[i].returnType != expressionTypeMethods[j].returnType)
-								&& (CharOperation.equals(castTypeMethods[i].selector, expressionTypeMethods[j].selector))
-								&& castTypeMethods[i].areParametersEqual(expressionTypeMethods[j])) {
-							scope.problemReporter().typeCastError(this, castType, expressionType);
-						}
-					}
-			}
-		}
-		this.bits |= NeedRuntimeCheckCastMASK;
-		return true;
-	}
-
-	/**
 	 * Casting an enclosing instance will considered as useful if removing it would actually bind to a different type
 	 */
 	public static void checkNeedForEnclosingInstanceCast(BlockScope scope, Expression enclosingInstance, TypeBinding enclosingInstanceType, TypeBinding memberType) {
@@ -363,10 +197,10 @@
 		}
 		if (leftIsCast || rightIsCast) {
 			if (alternateLeftTypeId > 15 || alternateRightTypeId > 15) { // must convert String + Object || Object + String
-				if (alternateLeftTypeId == T_String) {
-					alternateRightTypeId = T_Object;
-				} else if (alternateRightTypeId == T_String) {
-					alternateLeftTypeId = T_Object;
+				if (alternateLeftTypeId == T_JavaLangString) {
+					alternateRightTypeId = T_JavaLangObject;
+				} else if (alternateRightTypeId == T_JavaLangString) {
+					alternateLeftTypeId = T_JavaLangObject;
 				} else {
 					return; // invalid operator
 				}
@@ -377,8 +211,8 @@
 			//  <<16   <<12       <<8    <<4       <<0
 			final int CompareMASK = (0xF<<16) + (0xF<<8) + 0xF; // mask hiding compile-time types
 			if ((operatorSignature & CompareMASK) == (alternateOperatorSignature & CompareMASK)) { // same promotions and result
-				if (leftIsCast) scope.problemReporter().unnecessaryCastForArgument((CastExpression)left,  TypeBinding.wellKnownType(scope, left.implicitConversion >> 4)); 
-				if (rightIsCast) scope.problemReporter().unnecessaryCastForArgument((CastExpression)right, TypeBinding.wellKnownType(scope,  right.implicitConversion >> 4));
+				if (leftIsCast) scope.problemReporter().unnecessaryCastForArgument((CastExpression)left,  TypeBinding.wellKnownType(scope, (left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4)); 
+				if (rightIsCast) scope.problemReporter().unnecessaryCastForArgument((CastExpression)right, TypeBinding.wellKnownType(scope,  (right.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4));
 			}
 		}
 	}
@@ -386,6 +220,7 @@
 	private static void checkAlternateBinding(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding binding, Expression[] arguments, TypeBinding[] originalArgumentTypes, TypeBinding[] alternateArgumentTypes, final InvocationSite invocationSite) {
 
 			InvocationSite fakeInvocationSite = new InvocationSite(){	
+				public TypeBinding[] genericTypeArguments() { return null; }
 				public boolean isSuperAccess(){ return invocationSite.isSuperAccess(); }
 				public boolean isTypeAccess() { return invocationSite.isTypeAccess(); }
 				public void setActualReceiverType(ReferenceBinding actualReceiverType) { /* ignore */}
@@ -410,6 +245,40 @@
 				}
 			}	
 	}
+	
+	public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding expressionType, TypeBinding match, boolean isNarrowing) {
+		if (match == castType) {
+			if (!isNarrowing && castType == this.resolvedType.leafComponentType()) { // do not tag as unnecessary when recursing through upper bounds
+				tagAsUnnecessaryCast(scope, castType);
+			}
+			return true;
+		}
+		if (castType.isBoundParameterizedType() || castType.isGenericType()) {
+			if (match.isProvablyDistinctFrom(isNarrowing ? expressionType : castType, 0)) {
+				reportIllegalCast(scope, castType, expressionType);
+				return false; 
+			}
+			if (isNarrowing ? !expressionType.isEquivalentTo(match) : !match.isEquivalentTo(castType)) {
+				scope.problemReporter().unsafeCast(this, scope);
+				return true;
+			}
+			if ((castType.tagBits & TagBits.HasDirectWildcard) == 0) {
+				if ((!match.isParameterizedType() && !match.isGenericType())
+						|| expressionType.isRawType()) {
+					scope.problemReporter().unsafeCast(this, scope);
+					return true;
+				}
+			}
+		} else if (isNarrowing && castType.isTypeVariable()) {
+			scope.problemReporter().unsafeCast(this, scope);
+			return true;
+		}
+		if (!isNarrowing && castType == this.resolvedType.leafComponentType()) { // do not tag as unnecessary when recursing through upper bounds
+			tagAsUnnecessaryCast(scope, castType);
+		}
+		return true;
+	}	
+	
 	/**
 	 * Cast expression code generation
 	 *
@@ -421,7 +290,7 @@
 		BlockScope currentScope,
 		CodeStream codeStream,
 		boolean valueRequired) {
-
+	
 		int pc = codeStream.position;
 		boolean needRuntimeCheckcast = (this.bits & NeedRuntimeCheckCastMASK) != 0;
 		if (constant != NotAConstant) {
@@ -429,8 +298,11 @@
 				codeStream.generateConstant(constant, implicitConversion);
 				if (needRuntimeCheckcast) {
 					codeStream.checkcast(this.resolvedType);
-					if (!valueRequired)
+					if (valueRequired) {
+						codeStream.generateImplicitConversion(this.implicitConversion);
+					} else {
 						codeStream.pop();
+					}
 				}
 			}
 			codeStream.recordPositionsFrom(pc, this.sourceStart);
@@ -442,8 +314,11 @@
 			valueRequired || needRuntimeCheckcast);
 		if (needRuntimeCheckcast) {
 			codeStream.checkcast(this.resolvedType);
-			if (!valueRequired)
+			if (valueRequired) {
+				codeStream.generateImplicitConversion(implicitConversion);
+			} else {
 				codeStream.pop();
+			}
 		} else {
 			if (valueRequired)
 				codeStream.generateImplicitConversion(implicitConversion);
@@ -459,6 +334,17 @@
 		return current;
 	}
 
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#localVariableBinding()
+	 */
+	public LocalVariableBinding localVariableBinding() {
+		return this.expression.localVariableBinding();
+	}
+	
+	public int nullStatus(FlowInfo flowInfo) {
+		return this.expression.nullStatus(flowInfo);
+	}
+	
 	public StringBuffer printExpression(int indent, StringBuffer output) {
 
 		output.append('(');
@@ -466,6 +352,10 @@
 		return expression.printExpression(0, output);
 	}
 
+	public void reportIllegalCast(Scope scope, TypeBinding castType, TypeBinding expressionType) {
+		scope.problemReporter().typeCastError(this, castType, expressionType);
+	}
+	
 	public TypeBinding resolveType(BlockScope scope) {
 		// compute a new constant if the cast is effective
 
@@ -480,25 +370,67 @@
 				&& ((type.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) == 0) { // no extra parenthesis around type: ((A))exp
 
 			this.resolvedType = type.resolveType(scope);
+			expression.setExpectedType(this.resolvedType); // needed in case of generic method invocation			
 			TypeBinding expressionType = expression.resolveType(scope);
 			if (this.resolvedType != null && expressionType != null) {
-				boolean necessary = checkCastTypesCompatibility(scope, this.resolvedType, expressionType);
-				if (!necessary && this.expression.resolvedType != null) { // cannot do better if expression is not bound
-					this.bits |= UnnecessaryCastMask;
+				checkCastTypesCompatibility(scope, this.resolvedType, expressionType, this.expression);
+				this.expression.computeConversion(scope, this.resolvedType, expressionType);
+				if ((this.bits & UnnecessaryCastMask) != 0) {
 					if ((this.bits & IgnoreNeedForCastCheckMASK) == 0) {
-						scope.problemReporter().unnecessaryCast(this);
+						if (!usedForGenericMethodReturnTypeInference()) // used for generic type inference ?
+							scope.problemReporter().unnecessaryCast(this);
 					}
 				}
 			}
 			return this.resolvedType;
-		} else { // expression as a cast !!!!!!!!
+		} else { // expression as a cast
 			TypeBinding expressionType = expression.resolveType(scope);
 			if (expressionType == null) return null;
 			scope.problemReporter().invalidTypeReference(type);
 			return null;
 		}
 	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#setExpectedType(org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
+	 */
+	public void setExpectedType(TypeBinding expectedType) {
+		this.expectedType = expectedType;
+	}
 
+	/**
+	 * Determines whether apparent unnecessary cast wasn't actually used to
+	 * perform return type inference of generic method invocation.
+	 */
+	private boolean usedForGenericMethodReturnTypeInference() {
+		if (this.expression instanceof MessageSend) {
+			MethodBinding method = ((MessageSend)this.expression).binding;
+			if (method instanceof ParameterizedGenericMethodBinding
+						&& ((ParameterizedGenericMethodBinding)method).inferredReturnType) {
+				if (this.expectedType == null) 
+					return true;
+				if (this.resolvedType != this.expectedType)
+					return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#tagAsNeedCheckCast()
+	 */
+	public void tagAsNeedCheckCast() {
+		this.bits |= NeedRuntimeCheckCastMASK;
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#tagAsUnnecessaryCast(Scope, TypeBinding)
+	 */
+	public void tagAsUnnecessaryCast(Scope scope, TypeBinding castType) {
+		if (this.expression.resolvedType == null) return; // cannot do better if expression is not bound
+		this.bits |= UnnecessaryCastMask;
+	}
+	
 	public void traverse(
 		ASTVisitor visitor,
 		BlockScope blockScope) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java
index c2d90b0..8aad9ab 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java
@@ -84,11 +84,9 @@
  */
 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
 	int pc = codeStream.position;
-	if (valueRequired)
-		if ((implicitConversion >> 4) == T_char)
-			codeStream.generateInlinedValue(value);
-		else
-			codeStream.generateConstant(constant, implicitConversion);
+	if (valueRequired) {
+		codeStream.generateConstant(constant, implicitConversion);
+	}
 	codeStream.recordPositionsFrom(pc, this.sourceStart);
 }
 public TypeBinding literalType(BlockScope scope) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
index 4a4136e..4e35315 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.compiler.ast;
 
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -35,10 +36,11 @@
 		// if reachable, request the addition of a synthetic field for caching the class descriptor
 		SourceTypeBinding sourceType =
 			currentScope.outerMostMethodScope().enclosingSourceType();
-		if (!(sourceType.isInterface()
-			// no field generated in interface case (would'nt verify) see 1FHHEZL
-			|| sourceType.isBaseType())) {
-			syntheticField = sourceType.addSyntheticField(targetType, currentScope);
+		if ((!(sourceType.isInterface()
+				// no field generated in interface case (would'nt verify) see 1FHHEZL
+				|| sourceType.isBaseType()))
+				&& currentScope.environment().options.sourceLevel <= ClassFileConstants.JDK1_5) {
+			syntheticField = sourceType.addSyntheticFieldForClassLiteral(targetType, currentScope);
 		}
 		return flowInfo;
 	}
@@ -57,8 +59,10 @@
 		int pc = codeStream.position;
 
 		// in interface case, no caching occurs, since cannot make a cache field for interface
-		if (valueRequired)
+		if (valueRequired) {
 			codeStream.generateClassLiteralAccessForType(type.resolvedType, syntheticField);
+			codeStream.generateImplicitConversion(this.implicitConversion);
+		}
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 
@@ -70,16 +74,24 @@
 	public TypeBinding resolveType(BlockScope scope) {
 
 		constant = NotAConstant;
-		if ((targetType = type.resolveType(scope)) == null)
+		if ((targetType = type.resolveType(scope, true /* check bounds*/)) == null)
 			return null;
 
 		if (targetType.isArrayType()
 			&& ((ArrayBinding) targetType).leafComponentType == VoidBinding) {
 			scope.problemReporter().cannotAllocateVoidArray(this);
 			return null;
+		} else if (targetType.isTypeVariable()) {
+			scope.problemReporter().illegalClassLiteralForTypeVariable((TypeVariableBinding)targetType, this);
 		}
-
-		return this.resolvedType = scope.getJavaLangClass();
+		ReferenceBinding classType = scope.getJavaLangClass();
+		if (classType.isGenericType()) {
+		    // Integer.class --> Class<Integer>, perform boxing of base types (int.class --> Class<Integer>)
+		    this.resolvedType = scope.createParameterizedType(classType, new TypeBinding[]{ scope.boxing(targetType) }, null/*not a member*/);
+		} else {
+		    this.resolvedType = classType;
+		}
+		return this.resolvedType;
 	}
 
 	public void traverse(
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java
index 2bbac9c..22dbe6d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java
@@ -13,6 +13,7 @@
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.parser.*;
@@ -20,15 +21,13 @@
 
 public class Clinit extends AbstractMethodDeclaration {
 	
-	public final static char[] ConstantPoolName = "<clinit>".toCharArray(); //$NON-NLS-1$
-
 	private FieldBinding assertionSyntheticFieldBinding = null;
 	private FieldBinding classLiteralSyntheticField = null;
 
 	public Clinit(CompilationResult compilationResult) {
 		super(compilationResult);
 		modifiers = 0;
-		selector = ConstantPoolName;
+		selector = TypeConstants.CLINIT;
 	}
 
 	public void analyseCode(
@@ -60,7 +59,7 @@
 					&& (!flowInfo.isDefinitelyAssigned(fields[i]))) {
 					scope.problemReporter().uninitializedBlankFinalField(
 						field,
-						scope.referenceType().declarationOf(field));
+						scope.referenceType().declarationOf(field.original()));
 					// can complain against the field decl, since only one <clinit>
 				}
 			}
@@ -150,7 +149,7 @@
 		if (this.assertionSyntheticFieldBinding != null) {
 			// generate code related to the activation of assertion for this class
 			codeStream.generateClassLiteralAccessForType(
-				classScope.enclosingSourceType(),
+					classScope.enclosingSourceType(),
 				classLiteralSyntheticField);
 			codeStream.invokeJavaLangClassDesiredAssertionStatus();
 			Label falseLabel = new Label(codeStream);
@@ -163,15 +162,63 @@
 			jumpLabel.place();
 			codeStream.putstatic(this.assertionSyntheticFieldBinding);
 		}
-		// generate initializers
-		if (declaringType.fields != null) {
-			for (int i = 0, max = declaringType.fields.length; i < max; i++) {
-				FieldDeclaration fieldDecl;
-				if ((fieldDecl = declaringType.fields[i]).isStatic()) {
-					fieldDecl.generateCode(staticInitializerScope, codeStream);
+		// generate static fields/initializers/enum constants
+		final FieldDeclaration[] fieldDeclarations = declaringType.fields;
+		if (declaringType.kind() == IGenericType.ENUM_DECL) {
+			int enumCount = 0;
+			int notEnumConstants = 0;
+			if (fieldDeclarations != null) {
+				for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
+					FieldDeclaration fieldDecl = fieldDeclarations[i];
+					if (fieldDecl.isStatic()) {
+						if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+							fieldDecl.generateCode(staticInitializerScope, codeStream);
+							enumCount++;
+						} else {
+							notEnumConstants++;
+						}
+					}
+				}
+			}
+			// enum need to initialize $VALUES synthetic cache of enum constants
+			if (enumCount > 0) {
+				if (fieldDeclarations != null) {
+					// $VALUES := new <EnumType>[<enumCount>]
+					codeStream.generateInlinedValue(enumCount);
+					codeStream.anewarray(declaringType.binding);
+					for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
+						FieldDeclaration fieldDecl = fieldDeclarations[i];
+						// $VALUES[i] = <enum-constant-i>
+						if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+							codeStream.dup();
+							codeStream.generateInlinedValue(fieldDecl.binding.id);
+							codeStream.getstatic(fieldDecl.binding);
+							codeStream.aastore();
+						}
+					}
+					codeStream.putstatic(declaringType.enumValuesSyntheticfield);
+				}
+			}
+			if (notEnumConstants != 0) {
+				// if fields that are not enum constants need to be generated (static initializer/static field)
+				for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
+					FieldDeclaration fieldDecl = fieldDeclarations[i];
+					if (fieldDecl.isStatic() && fieldDecl.getKind() != AbstractVariableDeclaration.ENUM_CONSTANT) {
+						fieldDecl.generateCode(staticInitializerScope, codeStream);
+					}
+				}
+			}
+		} else {
+			if (fieldDeclarations != null) {
+				for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
+					FieldDeclaration fieldDecl = fieldDeclarations[i];
+					if (fieldDecl.isStatic()) {
+						fieldDecl.generateCode(staticInitializerScope, codeStream);
+					}
 				}
 			}
 		}
+		
 		if (codeStream.position == 0) {
 			// do not need to output a Clinit if no bytecodes
 			// so we reset the offset inside the byte array contents.
@@ -231,16 +278,17 @@
 		visitor.endVisit(this, classScope);
 	}
 
-	// 1.4 feature
-	public void setAssertionSupport(FieldBinding assertionSyntheticFieldBinding) {
+	public void setAssertionSupport(FieldBinding assertionSyntheticFieldBinding, boolean needClassLiteralField) {
 
 		this.assertionSyntheticFieldBinding = assertionSyntheticFieldBinding;
 
 		// we need to add the field right now, because the field infos are generated before the methods
 		SourceTypeBinding sourceType =
 			this.scope.outerMostMethodScope().enclosingSourceType();
-		this.classLiteralSyntheticField =
-			sourceType.addSyntheticField(sourceType, scope);
+		if (needClassLiteralField) {
+			this.classLiteralSyntheticField =
+				sourceType.addSyntheticFieldForClassLiteral(sourceType, scope);
+		}
 	}
 
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
index d736614..df96e49 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
@@ -19,6 +19,8 @@
 public class CompilationUnitDeclaration
 	extends ASTNode
 	implements ProblemSeverities, ReferenceContext {
+	
+	private static final char[] PACKAGE_INFO_FILE_NAME = "package-info.java".toCharArray(); //$NON-NLS-1$
 		
 	public ImportReference currentPackage;
 	public ImportReference[] imports;
@@ -266,7 +268,12 @@
 	}
 
 	public void resolve() {
-
+		if (this.currentPackage != null) {
+			if (this.currentPackage.annotations != null
+					&& !CharOperation.endsWith(getFileName(), PACKAGE_INFO_FILE_NAME)) {
+				scope.problemReporter().invalidFileNameForPackageAnnotations(this.currentPackage.annotations[0]);
+			}
+		}
 		try {
 			if (types != null) {
 				for (int i = 0, count = types.length; i < count; i++) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
index 47745f1..8e0f2f3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
@@ -54,6 +54,10 @@
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 	
+	public int nullStatus(FlowInfo flowInfo) {
+		return FlowInfo.NON_NULL;
+	}
+	
 	public String operatorToString() {
 		switch (operator) {
 			case PLUS :
@@ -94,23 +98,41 @@
 			scope.problemReporter().expressionShouldBeAVariable(this.lhs);
 			return null;
 		}
-		TypeBinding lhsType = lhs.resolveType(scope);
-		TypeBinding expressionType = expression.resolveType(scope);
-		if (lhsType == null || expressionType == null)
+		TypeBinding originalLhsType = lhs.resolveType(scope);
+		TypeBinding originalExpressionType = expression.resolveType(scope);
+		if (originalLhsType == null || originalExpressionType == null)
 			return null;
 	
-		int lhsId = lhsType.id;
-		int expressionId = expressionType.id;
+		// autoboxing support
+		LookupEnvironment env = scope.environment();
+		TypeBinding lhsType = originalLhsType, expressionType = originalExpressionType;
+		boolean use15specifics = scope.environment().options.sourceLevel >= JDK1_5;
+		boolean unboxedLhs = false;
+		if (use15specifics) {
+			if (!lhsType.isBaseType() && expressionType.id != T_JavaLangString && expressionType.id != T_null) {
+				TypeBinding unboxedType = env.computeBoxingType(lhsType);
+				if (unboxedType != lhsType) {
+					lhsType = unboxedType;
+					unboxedLhs = true;
+				}
+			}
+			if (!expressionType.isBaseType() && lhsType.id != T_JavaLangString  && lhsType.id != T_null) {
+				expressionType = env.computeBoxingType(expressionType);
+			}
+		}
+		
 		if (restrainUsageToNumericTypes() && !lhsType.isNumericType()) {
 			scope.problemReporter().operatorOnlyValidOnNumericType(this, lhsType, expressionType);
 			return null;
 		}
-		if (lhsId > 15 || expressionId > 15) {
-			if (lhsId != T_String) { // String += Thread is valid whereas Thread += String  is not
+		int lhsID = lhsType.id;
+		int expressionID = expressionType.id;
+		if (lhsID > 15 || expressionID > 15) {
+			if (lhsID != T_JavaLangString) { // String += Thread is valid whereas Thread += String  is not
 				scope.problemReporter().invalidOperator(this, lhsType, expressionType);
 				return null;
 			}
-			expressionId = T_Object; // use the Object has tag table
+			expressionID = T_JavaLangObject; // use the Object has tag table
 		}
 	
 		// the code is an int
@@ -119,28 +141,30 @@
 		//  <<16   <<12       <<8     <<4        <<0
 	
 		// the conversion is stored INTO the reference (info needed for the code gen)
-		int result = OperatorExpression.OperatorSignatures[operator][ (lhsId << 4) + expressionId];
+		int result = OperatorExpression.OperatorSignatures[operator][ (lhsID << 4) + expressionID];
 		if (result == T_undefined) {
 			scope.problemReporter().invalidOperator(this, lhsType, expressionType);
 			return null;
 		}
 		if (operator == PLUS){
-			if(lhsId == T_JavaLangObject) {
+			if(lhsID == T_JavaLangObject) {
 				// <Object> += <String> is illegal (39248)
 				scope.problemReporter().invalidOperator(this, lhsType, expressionType);
 				return null;
 			} else {
 				// <int | boolean> += <String> is illegal
-				if ((lhsType.isNumericType() || lhsId == T_boolean) && !expressionType.isNumericType()){
+				if ((lhsType.isNumericType() || lhsID == T_boolean) && !expressionType.isNumericType()){
 					scope.problemReporter().invalidOperator(this, lhsType, expressionType);
 					return null;
 				}
 			}
 		}
-		lhs.implicitConversion = result >>> 12;
-		expression.implicitConversion = (result >>> 4) & 0x000FF;
-		assignmentImplicitConversion = (lhsId << 4) + (result & 0x0000F);
-		return this.resolvedType = lhsType;
+		this.lhs.implicitConversion = (unboxedLhs ? UNBOXING : 0) | (result >>> 12);
+		scope.problemReporter().autoboxing(this.lhs, originalLhsType, lhsType);
+		this.expression.computeConversion(scope, TypeBinding.wellKnownType(scope, (result >>> 8) & 0x0000F), originalExpressionType);
+		this.assignmentImplicitConversion =  (unboxedLhs ? BOXING : 0) | (lhsID << 4) | (result & 0x0000F);
+		scope.problemReporter().autoboxing(this, lhsType, originalLhsType);
+		return this.resolvedType = originalLhsType;
 	}
 	
 	public boolean restrainUsageToNumericTypes(){
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
index cf86373..2572232 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -200,7 +201,7 @@
 		boolean valueRequired) {
 
 		if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean) // constant
-			|| (valueIfTrue.implicitConversion >> 4) != T_boolean) { // non boolean values
+			|| ((valueIfTrue.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_boolean) { // non boolean values
 			super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
 			return;
 		}
@@ -246,9 +247,7 @@
 		if (needFalsePart) {
 			internalFalseLabel.place();
 			if (falseInitStateIndex != -1) {
-				codeStream.removeNotDefinitelyAssignedVariables(
-					currentScope,
-					falseInitStateIndex);
+				codeStream.removeNotDefinitelyAssignedVariables(currentScope, falseInitStateIndex);
 				codeStream.addDefinitelyAssignedVariables(currentScope, falseInitStateIndex);
 			}
 			valueIfFalse.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
@@ -258,9 +257,7 @@
 		}
 		// May loose some local variable initializations : affecting the local variable attributes
 		if (mergedInitStateIndex != -1) {
-			codeStream.removeNotDefinitelyAssignedVariables(
-				currentScope,
-				mergedInitStateIndex);
+			codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
 		}
 		// no implicit conversion for boolean values
 		codeStream.updateLastRecordedEndPC(codeStream.position);
@@ -281,17 +278,30 @@
 	public TypeBinding resolveType(BlockScope scope) {
 		// specs p.368
 		constant = NotAConstant;
+		LookupEnvironment env = scope.environment();
+		boolean use15specifics = env.options.sourceLevel >= ClassFileConstants.JDK1_5;
 		TypeBinding conditionType = condition.resolveTypeExpecting(scope, BooleanBinding);
 		
 		if (valueIfTrue instanceof CastExpression) valueIfTrue.bits |= IgnoreNeedForCastCheckMASK; // will check later on
-		TypeBinding valueIfTrueType = valueIfTrue.resolveType(scope);
+		TypeBinding originalValueIfTrueType = valueIfTrue.resolveType(scope);
 
 		if (valueIfFalse instanceof CastExpression) valueIfFalse.bits |= IgnoreNeedForCastCheckMASK; // will check later on
-		TypeBinding valueIfFalseType = valueIfFalse.resolveType(scope);
+		TypeBinding originalValueIfFalseType = valueIfFalse.resolveType(scope);
 
-		if (conditionType == null || valueIfTrueType == null || valueIfFalseType == null)
+		if (conditionType == null || originalValueIfTrueType == null || originalValueIfFalseType == null)
 			return null;
 
+		TypeBinding valueIfTrueType = originalValueIfTrueType;
+		TypeBinding valueIfFalseType = originalValueIfFalseType;
+		if (use15specifics) {
+			if (valueIfTrueType != NullBinding && valueIfTrueType.isBaseType()) {
+				if (!valueIfFalseType.isBaseType()) {
+					valueIfFalseType = env.computeBoxingType(valueIfFalseType);
+				}
+			} else if (valueIfFalseType != NullBinding && valueIfFalseType.isBaseType()) {
+				valueIfTrueType = env.computeBoxingType(valueIfTrueType);
+			}
+		}
 		// Propagate the constant value from the valueIfTrue and valueIFFalse expression if it is possible
 		Constant condConstant, trueConstant, falseConstant;
 		if ((condConstant = condition.constant) != NotAConstant
@@ -302,8 +312,8 @@
 			constant = condConstant.booleanValue() ? trueConstant : falseConstant;
 		}
 		if (valueIfTrueType == valueIfFalseType) { // harmed the implicit conversion 
-			valueIfTrue.implicitWidening(valueIfTrueType, valueIfTrueType);
-			valueIfFalse.implicitConversion = valueIfTrue.implicitConversion;
+			valueIfTrue.computeConversion(scope, valueIfTrueType, originalValueIfTrueType);
+			valueIfFalse.computeConversion(scope, valueIfFalseType, originalValueIfFalseType);
 			if (valueIfTrueType == BooleanBinding) {
 				this.optimizedIfTrueConstant = valueIfTrue.optimizedBooleanConstant();
 				this.optimizedIfFalseConstant = valueIfFalse.optimizedBooleanConstant();
@@ -326,16 +336,16 @@
 			// (Short x Byte) or (Byte x Short)"
 			if ((valueIfTrueType == ByteBinding && valueIfFalseType == ShortBinding)
 				|| (valueIfTrueType == ShortBinding && valueIfFalseType == ByteBinding)) {
-				valueIfTrue.implicitWidening(ShortBinding, valueIfTrueType);
-				valueIfFalse.implicitWidening(ShortBinding, valueIfFalseType);
+				valueIfTrue.computeConversion(scope, ShortBinding, originalValueIfTrueType);
+				valueIfFalse.computeConversion(scope, ShortBinding, originalValueIfFalseType);
 				return this.resolvedType = ShortBinding;
 			}
 			// <Byte|Short|Char> x constant(Int)  ---> <Byte|Short|Char>   and reciprocally
 			if ((valueIfTrueType == ByteBinding || valueIfTrueType == ShortBinding || valueIfTrueType == CharBinding)
 					&& (valueIfFalseType == IntBinding
 						&& valueIfFalse.isConstantValueOfTypeAssignableToType(valueIfFalseType, valueIfTrueType))) {
-				valueIfTrue.implicitWidening(valueIfTrueType, valueIfTrueType);
-				valueIfFalse.implicitWidening(valueIfTrueType, valueIfFalseType);
+				valueIfTrue.computeConversion(scope, valueIfTrueType, originalValueIfTrueType);
+				valueIfFalse.computeConversion(scope, valueIfTrueType, originalValueIfFalseType);
 				return this.resolvedType = valueIfTrueType;
 			}
 			if ((valueIfFalseType == ByteBinding
@@ -343,35 +353,35 @@
 					|| valueIfFalseType == CharBinding)
 					&& (valueIfTrueType == IntBinding
 						&& valueIfTrue.isConstantValueOfTypeAssignableToType(valueIfTrueType, valueIfFalseType))) {
-				valueIfTrue.implicitWidening(valueIfFalseType, valueIfTrueType);
-				valueIfFalse.implicitWidening(valueIfFalseType, valueIfFalseType);
+				valueIfTrue.computeConversion(scope, valueIfFalseType, originalValueIfTrueType);
+				valueIfFalse.computeConversion(scope, valueIfFalseType, originalValueIfFalseType);
 				return this.resolvedType = valueIfFalseType;
 			}
 			// Manual binary numeric promotion
 			// int
 			if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_int)
 					&& BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_int)) {
-				valueIfTrue.implicitWidening(IntBinding, valueIfTrueType);
-				valueIfFalse.implicitWidening(IntBinding, valueIfFalseType);
+				valueIfTrue.computeConversion(scope, IntBinding, originalValueIfTrueType);
+				valueIfFalse.computeConversion(scope, IntBinding, originalValueIfFalseType);
 				return this.resolvedType = IntBinding;
 			}
 			// long
 			if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_long)
 					&& BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_long)) {
-				valueIfTrue.implicitWidening(LongBinding, valueIfTrueType);
-				valueIfFalse.implicitWidening(LongBinding, valueIfFalseType);
+				valueIfTrue.computeConversion(scope, LongBinding, originalValueIfTrueType);
+				valueIfFalse.computeConversion(scope, LongBinding, originalValueIfFalseType);
 				return this.resolvedType = LongBinding;
 			}
 			// float
 			if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_float)
 					&& BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_float)) {
-				valueIfTrue.implicitWidening(FloatBinding, valueIfTrueType);
-				valueIfFalse.implicitWidening(FloatBinding, valueIfFalseType);
+				valueIfTrue.computeConversion(scope, FloatBinding, originalValueIfTrueType);
+				valueIfFalse.computeConversion(scope, FloatBinding, originalValueIfFalseType);
 				return this.resolvedType = FloatBinding;
 			}
 			// double
-			valueIfTrue.implicitWidening(DoubleBinding, valueIfTrueType);
-			valueIfFalse.implicitWidening(DoubleBinding, valueIfFalseType);
+			valueIfTrue.computeConversion(scope, DoubleBinding, originalValueIfTrueType);
+			valueIfFalse.computeConversion(scope, DoubleBinding, originalValueIfFalseType);
 			return this.resolvedType = DoubleBinding;
 		}
 		// Type references (null null is already tested)
@@ -384,15 +394,24 @@
 			return null;
 		}
 		if (valueIfFalseType.isCompatibleWith(valueIfTrueType)) {
-			valueIfTrue.implicitWidening(valueIfTrueType, valueIfTrueType);
-			valueIfFalse.implicitWidening(valueIfTrueType, valueIfFalseType);
+			valueIfTrue.computeConversion(scope, valueIfTrueType, originalValueIfTrueType);
+			valueIfFalse.computeConversion(scope, valueIfTrueType, originalValueIfFalseType);
 			return this.resolvedType = valueIfTrueType;
 		}
 		if (valueIfTrueType.isCompatibleWith(valueIfFalseType)) {
-			valueIfTrue.implicitWidening(valueIfFalseType, valueIfTrueType);
-			valueIfFalse.implicitWidening(valueIfFalseType, valueIfFalseType);
+			valueIfTrue.computeConversion(scope, valueIfFalseType, originalValueIfTrueType);
+			valueIfFalse.computeConversion(scope, valueIfFalseType, originalValueIfFalseType);
 			return this.resolvedType = valueIfFalseType;
 		}
+		// 1.5 addition: allow most common supertype 
+		if (use15specifics) {
+			TypeBinding commonType = scope.lowerUpperBound(new TypeBinding[] { valueIfTrueType, valueIfFalseType });
+			if (commonType != null) {
+				valueIfTrue.computeConversion(scope, commonType, valueIfTrueType);
+				valueIfFalse.computeConversion(scope, commonType, valueIfFalseType);
+				return this.resolvedType = commonType;
+			}
+		}
 		scope.problemReporter().conditionalArgumentsIncompatibleTypes(
 			this,
 			valueIfTrueType,
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
index 7170bbf..892b91b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
@@ -24,8 +24,9 @@
 public class ConstructorDeclaration extends AbstractMethodDeclaration {
 
 	public ExplicitConstructorCall constructorCall;
-	public final static char[] ConstantPoolName = "<init>".toCharArray(); //$NON-NLS-1$
+	
 	public boolean isDefaultConstructor = false;
+	public TypeParameter[] typeParameters;
 
 	public ConstructorDeclaration(CompilationResult compilationResult){
 		super(compilationResult);
@@ -76,6 +77,13 @@
 				}
 			}
 			
+			// tag parameters as being set
+			if (this.arguments != null) {
+				for (int i = 0, count = this.arguments.length; i < count; i++) {
+					flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
+				}
+			}
+			
 			// propagate to constructor call
 			if (constructorCall != null) {
 				// if calling 'this(...)', then flag all non-static fields as definitely
@@ -212,7 +220,7 @@
 		
 		classFile.generateMethodInfoHeader(binding);
 		int methodAttributeOffset = classFile.contentsOffset;
-		int attributeNumber = classFile.generateMethodInfoAttribute(binding);
+		int attributeNumber = classFile.generateMethodInfoAttribute(this.binding);
 		if ((!binding.isNative()) && (!binding.isAbstract())) {
 			
 			TypeDeclaration declaringType = classScope.referenceContext;
@@ -224,18 +232,19 @@
 			// initialize local positions - including initializer scope.
 			ReferenceBinding declaringClass = binding.declaringClass;
 
-			int argSlotSize = 1; // this==aload0
-			
+			int enumOffset = declaringClass.isEnum() ? 2 : 0; // String name, int ordinal
+			int argSlotSize = 1 + enumOffset; // this==aload0
+
 			if (declaringClass.isNestedType()){
 				NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;
 				this.scope.extraSyntheticArguments = nestedType.syntheticOuterLocalVariables();
 				scope.computeLocalVariablePositions(// consider synthetic arguments if any
-					nestedType.enclosingInstancesSlotSize + 1,
+					nestedType.enclosingInstancesSlotSize + 1 + enumOffset,
 					codeStream);
 				argSlotSize += nestedType.enclosingInstancesSlotSize;
 				argSlotSize += nestedType.outerLocalVariablesSlotSize;
 			} else {
-				scope.computeLocalVariablePositions(1,  codeStream);
+				scope.computeLocalVariablePositions(1 + enumOffset,  codeStream);
 			}
 				
 			if (arguments != null) {
@@ -321,13 +330,10 @@
 		return true;
 	}
 
-	/**
+	/*
 	 * Returns true if the constructor is directly involved in a cycle.
 	 * Given most constructors aren't, we only allocate the visited list
 	 * lazily.
-	 * 
-	 * @param visited
-	 * @return
 	 */
 	public boolean isRecursive(ArrayList visited) {
 
@@ -340,7 +346,7 @@
 		}
 		
 		ConstructorDeclaration targetConstructor = 
-			((ConstructorDeclaration)this.scope.referenceType().declarationOf(constructorCall.binding));
+			((ConstructorDeclaration)this.scope.referenceType().declarationOf(constructorCall.binding.original()));
 		if (this == targetConstructor) return true; // direct case
 
 		if (visited == null) { // lazy allocation
@@ -359,10 +365,10 @@
 		//fill up the constructor body with its statements
 		if (ignoreFurtherInvestigation)
 			return;
-		if (isDefaultConstructor){
-			constructorCall = SuperReference.implicitSuperConstructorCall();
-			constructorCall.sourceStart = sourceStart;
-			constructorCall.sourceEnd = sourceEnd; 
+		if (isDefaultConstructor && this.constructorCall == null){
+			this.constructorCall = SuperReference.implicitSuperConstructorCall();
+			this.constructorCall.sourceStart = this.sourceStart;
+			this.constructorCall.sourceEnd = this.sourceEnd; 
 			return;
 		}
 		parser.parse(this, unit);
@@ -406,11 +412,14 @@
 			scope.problemReporter().missingReturnType(this);
 		}
 
+		if (this.binding != null && this.binding.declaringClass.isAnnotationType()) {
+			scope.problemReporter().annotationTypeDeclarationCannotHaveConstructor(this);
+		}
 		// if null ==> an error has occurs at parsing time ....
 		if (this.constructorCall != null) {
 			// e.g. using super() in java.lang.Object
 			if (this.binding != null
-				&& this.binding.declaringClass.id == T_Object
+				&& this.binding.declaringClass.id == T_JavaLangObject
 				&& this.constructorCall.accessMode != ExplicitConstructorCall.This) {
 					if (this.constructorCall.accessMode == ExplicitConstructorCall.Super) {
 						scope.problemReporter().cannotUseSuperInJavaLangObject(this.constructorCall);
@@ -430,7 +439,19 @@
 		ASTVisitor visitor,
 		ClassScope classScope) {
 
+		
 		if (visitor.visit(this, classScope)) {
+			if (this.annotations != null) {
+				int annotationsLength = this.annotations.length;
+				for (int i = 0; i < annotationsLength; i++)
+					this.annotations[i].traverse(visitor, scope);
+			}
+			if (this.typeParameters != null) {
+				int typeParametersLength = this.typeParameters.length;
+				for (int i = 0; i < typeParametersLength; i++) {
+					this.typeParameters[i].traverse(visitor, scope);
+				}
+			}			
 			if (arguments != null) {
 				int argumentLength = arguments.length;
 				for (int i = 0; i < argumentLength; i++)
@@ -451,4 +472,7 @@
 		}
 		visitor.endVisit(this, classScope);
 	}
+	public TypeParameter[] typeParameters() {
+	    return this.typeParameters;
+	}		
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
index 0dc995d..a12254a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
@@ -59,11 +59,12 @@
 
 		int previousMode = flowInfo.reachMode();
 				
+		FlowInfo actionInfo = flowInfo.copy().unconditionalInits().discardNullRelatedInitializations();
 		if ((action != null) && !action.isEmptyBlock()) {
-			flowInfo = action.analyseCode(currentScope, loopingContext, flowInfo);
+			actionInfo = action.analyseCode(currentScope, loopingContext, actionInfo);
 
 			// code generation can be optimized when no need to continue in the loop
-			if (!flowInfo.isReachable() && !loopingContext.initsOnContinue.isReachable()) {
+			if (!actionInfo.isReachable() && !loopingContext.initsOnContinue.isReachable()) {
 				continueLabel = null;
 			}
 		}
@@ -72,24 +73,24 @@
 		 *   do { if (true) break; else blank = 0; } while(false);
 		 *   blank = 1; // may be initialized already 
 		 */
-		flowInfo.setReachMode(previousMode);
+		actionInfo.setReachMode(previousMode);
 		
-		flowInfo =
+		actionInfo =
 			condition.analyseCode(
 				currentScope,
 				loopingContext,
 				(action == null
-					? flowInfo
-					: (flowInfo.mergedWith(loopingContext.initsOnContinue))));
+					? actionInfo
+					: (actionInfo.mergedWith(loopingContext.initsOnContinue))));
 		if (!isConditionOptimizedFalse && continueLabel != null) {
-			loopingContext.complainOnFinalAssignmentsInLoop(currentScope, flowInfo);
+			loopingContext.complainOnDeferredChecks(currentScope, actionInfo);
 		}
 
 		// end of loop
 		FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
 				loopingContext.initsOnBreak, 
 				isConditionOptimizedTrue, 
-				flowInfo.initsWhenFalse(), 
+				actionInfo.initsWhenFalse().addInitializationsFrom(flowInfo), // recover null inits from before condition analysis
 				false, // never consider opt false case for DO loop, since break can always occur (47776)
 				!isConditionTrue /*do{}while(true); unreachable(); */);
 		mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
@@ -155,7 +156,7 @@
 	public void resolve(BlockScope scope) {
 
 		TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
-		condition.implicitWidening(type, type);
+		condition.computeConversion(scope, type, type);
 		if (action != null)
 			action.resolve(scope);
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java
index 139c813..1c8a8c1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java
@@ -14,58 +14,100 @@
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.util.FloatUtil;
 
 public class DoubleLiteral extends NumberLiteral {
 	double value;
-public DoubleLiteral(char[] token, int s, int e) {
-	super(token, s,e);
-}
-public void computeConstant() {
+	public DoubleLiteral(char[] token, int s, int e) {
+		super(token, s, e);
+	}
+	public void computeConstant() {
+		Double computedValue;
+		try {
+			computedValue = Double.valueOf(String.valueOf(source));
+		} catch (NumberFormatException e) {
+			// hex floating point literal
+			// being rejected by 1.4 libraries where Double.valueOf(...) doesn't handle hex decimal floats
+			try {
+				double v = FloatUtil.valueOfHexDoubleLiteral(source);
+				if (v == Double.POSITIVE_INFINITY) {
+					// error: the number is too large to represent
+					return;
+				}
+				if (Double.isNaN(v)) {
+					// error: the number is too small to represent
+					return;
+				}
+				value = v;
+				constant = Constant.fromValue(v);
+			} catch (NumberFormatException e1) {
+				// if the computation of the constant fails
+			}
+			return;
+		}
 
-	//the source is correctly formated so the exception should never occurs
-
-	Double computedValue;
-	try { computedValue = Double.valueOf(String.valueOf(source));}
-	catch(NumberFormatException e){return ;} //how can it happen ????
-
-	if (computedValue.doubleValue() > Double.MAX_VALUE) return ; //may be Infinity
-	if (computedValue.doubleValue() < Double.MIN_VALUE)
-	{	//only a true 0 can be made of zeros
-		//2.00000000000000000e-324 is illegal .... 
-		label :
-			for (int i=0;i<source.length;i++)
-			{	//it is welled formated so just test against '0' and potential . D d  
-				switch (source[i]){
+		final double doubleValue = computedValue.doubleValue();
+		if (doubleValue > Double.MAX_VALUE) {
+			// error: the number is too large to represent
+			return;
+		}
+		if (doubleValue < Double.MIN_VALUE) {
+			// see 1F6IGUU
+			// a true 0 only has '0' and '.' in mantissa
+			// 1.0e-5000d is non-zero, but underflows to 0
+			boolean isHexaDecimal = false;
+			label : for (int i = 0; i < source.length; i++) { //it is welled formated so just test against '0' and potential . D d  
+				switch (source[i]) {
 					case '0' :
 					case '.' :
+						break;
+					case 'x' :
+					case 'X' :
+						isHexaDecimal = true;
+						break;
+					case 'e' :
+					case 'E' :
+					case 'f' :
+					case 'F' :
 					case 'd' :
-					case 'D' : break ;
-					case 'e' : 
-					case 'E' : break label ; //exposant are valid....!
-					default  : return;}}} //error
-
-	constant = Constant.fromValue(value = computedValue.doubleValue());}
-/**
- * Code generation for the double literak
- *
- * @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 (valueRequired)
-		if ((implicitConversion >> 4) == T_double)
-			codeStream.generateInlinedValue(value);
-		else
+					case 'D' :
+						if (isHexaDecimal) {
+							return;
+						}
+						// starting the exponent - mantissa is all zero
+						// no exponent - mantissa is all zero
+						break label;
+					case 'p' :
+					case 'P' :
+						break label;
+					default :
+						// error: the number is too small to represent
+						return;
+				}
+			}
+		}
+		value = doubleValue;
+		constant = Constant.fromValue(value);
+	}
+	/**
+	 * Code generation for the double literak
+	 *
+	 * @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 (valueRequired) {
 			codeStream.generateConstant(constant, implicitConversion);
-	codeStream.recordPositionsFrom(pc, this.sourceStart);
-}
-public TypeBinding literalType(BlockScope scope) {
-	return DoubleBinding;
-}
-public void traverse(ASTVisitor visitor, BlockScope blockScope) {
-	visitor.visit(this, blockScope);
-	visitor.endVisit(this, blockScope);
-}
+		}
+		codeStream.recordPositionsFrom(pc, this.sourceStart);
+	}
+	public TypeBinding literalType(BlockScope scope) {
+		return DoubleBinding;
+	}
+	public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+		visitor.visit(this, blockScope);
+		visitor.endVisit(this, blockScope);
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
index 0caeb81..4b2fec9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
@@ -10,7 +10,6 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
@@ -19,386 +18,313 @@
 
 public class EqualExpression extends BinaryExpression {
 
-public EqualExpression(Expression left, Expression right,int operator) {
-	super(left,right,operator);
-}
-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.booleanValue()) { //  true == anything
-				//  this is equivalent to the right argument inits 
-				return right.analyseCode(currentScope, flowContext, flowInfo);
-			} else { // false == anything
-				//  this is equivalent to the right argument inits negated
-				return right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
-			}
-		}
-		if ((right.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);
-			} else { // anything == false
-				//  this is equivalent to the right argument inits negated
-				return left.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
-			}
-		}
-		return right.analyseCode(
-			currentScope, flowContext, 
-			left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).unconditionalInits();
-	} else { //NOT_EQUAL :
-		if ((left.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);
-			} else { // true != anything
-				//  this is equivalent to the right argument inits negated
-				return right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
-			}
-		}
-		if ((right.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);
-			} else { // anything != true
-				//  this is equivalent to the right argument inits negated
-				return left.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
-			}
-		}
-		return right.analyseCode(
-			currentScope, flowContext, 
-			left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).asNegatedCondition().unconditionalInits();
+	public EqualExpression(Expression left, Expression right,int operator) {
+		super(left,right,operator);
 	}
-}
-public final boolean areTypesCastCompatible(BlockScope scope, TypeBinding castType, TypeBinding expressionType) {
-	//see specifications 5.5
-	//A more complete version of this method is provided on
-	//CastExpression (it deals with constant and need runtime checkcast)
-
-	if (castType == expressionType) return true;
-
-	//========ARRAY===============
-	if (expressionType.isArrayType()) {
-		if (castType.isArrayType()) { //------- (castTb.isArray) expressionTb.isArray -----------
-			TypeBinding expressionEltType = ((ArrayBinding) expressionType).elementsType(scope);
-			if (expressionEltType.isBaseType())
-				// <---stop the recursion------- 
-				return ((ArrayBinding) castType).elementsType(scope) == expressionEltType;
-			//recursivly on the elts...
-			return areTypesCastCompatible(scope, ((ArrayBinding) castType).elementsType(scope), expressionEltType);
+	public void checkNullComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse) {
+		
+		LocalVariableBinding local = this.left.localVariableBinding();
+		if (local != null) {
+			checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, right.nullStatus(flowInfo), this.left);
 		}
-		if (castType.isBaseType()) {
-			return false;
+		local = this.right.localVariableBinding();
+		if (local != null) {
+			checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, left.nullStatus(flowInfo), this.right);
 		}
-		if (castType.isClass()) { //------(castTb.isClass) expressionTb.isArray ---------------	
-			if (castType.id == T_Object)
-				return true;
-			return false;
-		}
-		if (castType.isInterface()) { //------- (castTb.isInterface) expressionTb.isArray -----------
-			if (castType.id == T_JavaLangCloneable || castType.id == T_JavaIoSerializable) {
-				return true;
-			}
-			return false;
-		}
-
-		return false;
 	}
-
-	//------------(castType) null--------------
-	if (expressionType == NullBinding) {
-		return !castType.isBaseType();
-	}
-
-	//========BASETYPE==============
-	if (expressionType.isBaseType()) {
-		return false;
-	}
-
-
-	//========REFERENCE TYPE===================
-
-	if (expressionType.isClass()) {
-		if (castType.isArrayType()) { // ---- (castTb.isArray) expressionTb.isClass -------
-			if (expressionType.id == T_Object)
-				return true;
-		}
-		if (castType.isBaseType()) {
-			return false;
-		}
-		if (castType.isClass()) { // ----- (castTb.isClass) expressionTb.isClass ------ 
-			if (expressionType.isCompatibleWith(castType))
-				return true;
-			else {
-				if (castType.isCompatibleWith(expressionType)) {
-					return true;
+	private void checkVariableComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse, LocalVariableBinding local, int nullStatus, Expression reference) {
+		switch (nullStatus) {
+			case FlowInfo.NULL :
+				flowContext.recordUsingNullReference(scope, local, reference, FlowInfo.NULL, flowInfo);
+				if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
+					initsWhenTrue.markAsDefinitelyNull(local); // from thereon it is set
+					initsWhenFalse.markAsDefinitelyNonNull(local); // from thereon it is set
+				} else {
+					initsWhenTrue.markAsDefinitelyNonNull(local); // from thereon it is set
+					initsWhenFalse.markAsDefinitelyNull(local); // from thereon it is set
 				}
-				return false;
-			}
-		}
-		if (castType.isInterface()) { // ----- (castTb.isInterface) expressionTb.isClass -------  
-			if (expressionType.isCompatibleWith(castType))
-				return true;		    
-			if (!((ReferenceBinding) expressionType).isFinal()) {
-				return true;
-			}
-			//no subclass for expressionTb, thus compile-time check is valid			
-		}
-
-		return false;
-	}
-	if (expressionType.isInterface()) {
-		if (castType.isArrayType()) { // ----- (castTb.isArray) expressionTb.isInterface ------
-			if (expressionType.id == T_JavaLangCloneable || expressionType.id == T_JavaIoSerializable)
-				//potential runtime error
-				{
-				return true;
-			}
-			return false;
-		}
-		if (castType.isBaseType()) {
-			return false;
-		}
-		if (castType.isClass()) { // ----- (castTb.isClass) expressionTb.isInterface --------
-			if (castType.id == T_Object)
-				return true;
-			if (((ReferenceBinding) castType).isFinal()) { //no subclass for castTb, thus compile-time check is valid
-				if (castType.isCompatibleWith(expressionType)) {
-					return true;
+				break;
+			case FlowInfo.NON_NULL :
+				flowContext.recordUsingNullReference(scope, local, reference, FlowInfo.NON_NULL, flowInfo);
+				if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
+					initsWhenTrue.markAsDefinitelyNonNull(local); // from thereon it is set
 				}
-				return false;
-			}
-			return true;
-		}
-		if (castType.isInterface()) { // ----- (castTb.isInterface) expressionTb.isInterface -------
-			if (expressionType.isCompatibleWith(castType))
-				return true;
-			if (!castType.isCompatibleWith(expressionType)) {
-				MethodBinding[] castTbMethods = ((ReferenceBinding) castType).methods();
-				int castTbMethodsLength = castTbMethods.length;
-				MethodBinding[] expressionTbMethods = ((ReferenceBinding) expressionType).methods();
-				int expressionTbMethodsLength = expressionTbMethods.length;
-				for (int i = 0; i < castTbMethodsLength; i++) {
-					for (int j = 0; j < expressionTbMethodsLength; j++) {
-						if (CharOperation.equals(castTbMethods[i].selector, expressionTbMethods[j].selector)) {
-							if (castTbMethods[i].returnType != expressionTbMethods[j].returnType) {
-								if (castTbMethods[i].areParametersEqual(expressionTbMethods[j])) {
-									return false;
-								}
-							}
-						}
-					}
-				}
-			}
-			return true;
-		}
-		return false;
-	}
-	return false;
-}
-public final void computeConstant(TypeBinding leftType, TypeBinding rightType) {
-	if ((this.left.constant != NotAConstant) && (this.right.constant != NotAConstant)) {
-		this.constant =
-			Constant.computeConstantOperationEQUAL_EQUAL(
-				left.constant,
-				leftType.id,
-				EQUAL_EQUAL,
-				right.constant,
-				rightType.id);
-		if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT_EQUAL)
-			constant = Constant.fromValue(!constant.booleanValue());
-	} else {
-		this.constant = NotAConstant;
-		// no optimization for null == null
-	}
-}
-/**
- * Normal == or != 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) {
-
-	if (constant != NotAConstant) {
-		int pc = codeStream.position;
-		if (valueRequired) 
-			codeStream.generateConstant(constant, implicitConversion);
-		codeStream.recordPositionsFrom(pc, this.sourceStart);
-		return;
-	}
-	Label falseLabel;
-	bits |= OnlyValueRequiredMASK;
-	generateOptimizedBoolean(
-		currentScope, 
-		codeStream, 
-		null, 
-		falseLabel = new Label(codeStream), 
-		valueRequired);
-	if (falseLabel.hasForwardReferences()) {
-		if (valueRequired){
-			// comparison is TRUE 
-			codeStream.iconst_1();
-			if ((bits & ValueForReturnMASK) != 0){
-				codeStream.ireturn();
-				// 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 {
-			falseLabel.place();
+				break;
 		}	
 	}
-}
-/**
- * Boolean operator code generation
- *	Optimized operations are: == and !=
- */
-public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
-
-	if (constant != Constant.NotAConstant) {
-		super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
-		return;
-	}
-	if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
-		if ((left.implicitConversion & 0xF) /*compile-time*/ == T_boolean) {
-			generateOptimizedBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
-		} else {
-			generateOptimizedNonBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
-		}
-	} else {
-		if ((left.implicitConversion & 0xF) /*compile-time*/ == T_boolean) {
-			generateOptimizedBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
-		} else {
-			generateOptimizedNonBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
-		}
-	}
-}
-/**
- * Boolean generation for == with boolean operands
- *
- * Note this code does not optimize conditional constants !!!!
- */
-public void generateOptimizedBooleanEqual(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
-
-	// optimized cases: true == x, false == x
-	if (left.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) {
-		boolean inline = right.constant.booleanValue();
-		left.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired);
-		return;
-	}
-	// default case
-	left.generateCode(currentScope, codeStream, valueRequired);
-	right.generateCode(currentScope, codeStream, valueRequired);
-	if (valueRequired) {
-		if (falseLabel == null) {
-			if (trueLabel != null) {
-				// implicit falling through the FALSE case
-				codeStream.if_icmpeq(trueLabel);
+	
+	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.booleanValue()) { //  true == anything
+					//  this is equivalent to the right argument inits 
+					return right.analyseCode(currentScope, flowContext, flowInfo);
+				} else { // false == anything
+					//  this is equivalent to the right argument inits negated
+					return right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
+				}
 			}
+			if ((right.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);
+				} else { // anything == false
+					//  this is equivalent to the right argument inits negated
+					return left.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
+				}
+			}
+			return right.analyseCode(
+				currentScope, flowContext, 
+				left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).unconditionalInits();
+		} else { //NOT_EQUAL :
+			if ((left.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);
+				} else { // true != anything
+					//  this is equivalent to the right argument inits negated
+					return right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
+				}
+			}
+			if ((right.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);
+				} else { // anything != true
+					//  this is equivalent to the right argument inits negated
+					return left.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
+				}
+			}
+			return right.analyseCode(
+				currentScope, flowContext, 
+				left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).asNegatedCondition().unconditionalInits();
+		}
+	}
+	
+	public final void computeConstant(TypeBinding leftType, TypeBinding rightType) {
+		if ((this.left.constant != NotAConstant) && (this.right.constant != NotAConstant)) {
+			this.constant =
+				Constant.computeConstantOperationEQUAL_EQUAL(
+					left.constant,
+					leftType.id,
+					right.constant,
+					rightType.id);
+			if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT_EQUAL)
+				constant = Constant.fromValue(!constant.booleanValue());
 		} else {
-			// implicit falling through the TRUE case
-			if (trueLabel == null) {
-				codeStream.if_icmpne(falseLabel);
+			this.constant = NotAConstant;
+			// no optimization for null == null
+		}
+	}
+	/**
+	 * Normal == or != 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) {
+	
+		if (constant != NotAConstant) {
+			int pc = codeStream.position;
+			if (valueRequired) 
+				codeStream.generateConstant(constant, implicitConversion);
+			codeStream.recordPositionsFrom(pc, this.sourceStart);
+			return;
+		}
+		Label falseLabel;
+		bits |= OnlyValueRequiredMASK;
+		generateOptimizedBoolean(
+			currentScope, 
+			codeStream, 
+			null, 
+			falseLabel = new Label(codeStream), 
+			valueRequired);
+		if (falseLabel.hasForwardReferences()) {
+			if (valueRequired){
+				// comparison is TRUE 
+				codeStream.iconst_1();
+				if ((bits & ValueForReturnMASK) != 0){
+					codeStream.ireturn();
+					// 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 {
-				// no implicit fall through TRUE/FALSE --> should never occur
-			}
+				falseLabel.place();
+			}	
 		}
 	}
-	// reposition the endPC
-	codeStream.updateLastRecordedEndPC(codeStream.position);					
-}
-/**
- * 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) {
-		// optimized case: x == 0
-		if (((left.implicitConversion >> 4) == T_int) && (inline.intValue() == 0)) {
-			left.generateCode(currentScope, codeStream, valueRequired);
-			if (valueRequired) {
-				if (falseLabel == null) {
-					if (trueLabel != null) {
-						// implicit falling through the FALSE case
-						codeStream.ifeq(trueLabel);
-					}
-				} else {
-					// implicit falling through the TRUE case
-					if (trueLabel == null) {
-						codeStream.ifne(falseLabel);
-					} else {
-						// no implicit fall through TRUE/FALSE --> should never occur
-					}
-				}
-			}
-			codeStream.recordPositionsFrom(pc, this.sourceStart);
+	/**
+	 * Boolean operator code generation
+	 *	Optimized operations are: == and !=
+	 */
+	public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
+	
+		if (constant != Constant.NotAConstant) {
+			super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
 			return;
 		}
-	}
-	if ((inline = left.constant) != NotAConstant) {
-		// optimized case: 0 == x
-		if (((left.implicitConversion >> 4) == T_int)
-			&& (inline.intValue() == 0)) {
-			right.generateCode(currentScope, codeStream, valueRequired);
-			if (valueRequired) {
-				if (falseLabel == null) {
-					if (trueLabel != null) {
-						// implicit falling through the FALSE case
-						codeStream.ifeq(trueLabel);
-					}
-				} else {
-					// implicit falling through the TRUE case
-					if (trueLabel == null) {
-						codeStream.ifne(falseLabel);
-					} else {
-						// no implicit fall through TRUE/FALSE --> should never occur
-					}
-				}
-			}
-			codeStream.recordPositionsFrom(pc, this.sourceStart);
-			return;
-		}
-	}
-	// null cases
-	// optimized case: x == null
-	if (right instanceof NullLiteral) {
-		if (left instanceof NullLiteral) {
-			// null == null
-			if (valueRequired) {
-					if ((bits & OnlyValueRequiredMASK) != 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 (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
+			if ((left.implicitConversion & COMPILE_TYPE_MASK) /*compile-time*/ == T_boolean) {
+				generateOptimizedBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+			} else {
+				generateOptimizedNonBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
 			}
 		} else {
-			left.generateCode(currentScope, codeStream, valueRequired);
+			if ((left.implicitConversion & COMPILE_TYPE_MASK) /*compile-time*/ == T_boolean) {
+				generateOptimizedBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
+			} else {
+				generateOptimizedNonBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
+			}
+		}
+	}
+	/**
+	 * Boolean generation for == with boolean operands
+	 *
+	 * Note this code does not optimize conditional constants !!!!
+	 */
+	public void generateOptimizedBooleanEqual(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
+	
+		// optimized cases: true == x, false == x
+		if (left.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) {
+			boolean inline = right.constant.booleanValue();
+			left.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired);
+			return;
+		}
+		// default case
+		left.generateCode(currentScope, codeStream, valueRequired);
+		right.generateCode(currentScope, codeStream, valueRequired);
+		if (valueRequired) {
+			if (falseLabel == null) {
+				if (trueLabel != null) {
+					// implicit falling through the FALSE case
+					codeStream.if_icmpeq(trueLabel);
+				}
+			} else {
+				// implicit falling through the TRUE case
+				if (trueLabel == null) {
+					codeStream.if_icmpne(falseLabel);
+				} else {
+					// no implicit fall through TRUE/FALSE --> should never occur
+				}
+			}
+		}
+		// reposition the endPC
+		codeStream.updateLastRecordedEndPC(codeStream.position);					
+	}
+	/**
+	 * 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) {
+			// optimized case: x == 0
+			if ((((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int) && (inline.intValue() == 0)) {
+				left.generateCode(currentScope, codeStream, valueRequired);
+				if (valueRequired) {
+					if (falseLabel == null) {
+						if (trueLabel != null) {
+							// implicit falling through the FALSE case
+							codeStream.ifeq(trueLabel);
+						}
+					} else {
+						// implicit falling through the TRUE case
+						if (trueLabel == null) {
+							codeStream.ifne(falseLabel);
+						} else {
+							// no implicit fall through TRUE/FALSE --> should never occur
+						}
+					}
+				}
+				codeStream.recordPositionsFrom(pc, this.sourceStart);
+				return;
+			}
+		}
+		if ((inline = left.constant) != NotAConstant) {
+			// optimized case: 0 == x
+			if ((((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int)
+				&& (inline.intValue() == 0)) {
+				right.generateCode(currentScope, codeStream, valueRequired);
+				if (valueRequired) {
+					if (falseLabel == null) {
+						if (trueLabel != null) {
+							// implicit falling through the FALSE case
+							codeStream.ifeq(trueLabel);
+						}
+					} else {
+						// implicit falling through the TRUE case
+						if (trueLabel == null) {
+							codeStream.ifne(falseLabel);
+						} else {
+							// no implicit fall through TRUE/FALSE --> should never occur
+						}
+					}
+				}
+				codeStream.recordPositionsFrom(pc, this.sourceStart);
+				return;
+			}
+		}
+		// null cases
+		// optimized case: x == null
+		if (right instanceof NullLiteral) {
+			if (left instanceof NullLiteral) {
+				// null == null
+				if (valueRequired) {
+						if ((bits & OnlyValueRequiredMASK) != 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);
+								}
+							}
+					}
+				}
+			} else {
+				left.generateCode(currentScope, codeStream, valueRequired);
+				if (valueRequired) {
+					if (falseLabel == null) {
+						if (trueLabel != null) {
+							// implicit falling through the FALSE case
+							codeStream.ifnull(trueLabel);
+						}
+					} else {
+						// implicit falling through the TRUE case
+						if (trueLabel == null) {
+							codeStream.ifnonnull(falseLabel);
+						} else {
+							// no implicit fall through TRUE/FALSE --> should never occur
+						}
+					}
+				}
+			}
+			codeStream.recordPositionsFrom(pc, this.sourceStart);
+			return;
+		} else if (left instanceof NullLiteral) { // optimized case: null == x
+			right.generateCode(currentScope, codeStream, valueRequired);
 			if (valueRequired) {
 				if (falseLabel == null) {
 					if (trueLabel != null) {
@@ -414,165 +340,162 @@
 					}
 				}
 			}
+			codeStream.recordPositionsFrom(pc, this.sourceStart);
+			return;
 		}
-		codeStream.recordPositionsFrom(pc, this.sourceStart);
-		return;
-	} else if (left instanceof NullLiteral) { // optimized case: null == x
+	
+		// default case
+		left.generateCode(currentScope, codeStream, valueRequired);
 		right.generateCode(currentScope, codeStream, valueRequired);
 		if (valueRequired) {
 			if (falseLabel == null) {
 				if (trueLabel != null) {
 					// implicit falling through the FALSE case
-					codeStream.ifnull(trueLabel);
+					switch ((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { // operand runtime type
+						case T_int :
+							codeStream.if_icmpeq(trueLabel);
+							break;
+						case T_float :
+							codeStream.fcmpl();
+							codeStream.ifeq(trueLabel);
+							break;
+						case T_long :
+							codeStream.lcmp();
+							codeStream.ifeq(trueLabel);
+							break;
+						case T_double :
+							codeStream.dcmpl();
+							codeStream.ifeq(trueLabel);
+							break;
+						default :
+							codeStream.if_acmpeq(trueLabel);
+					}
 				}
 			} else {
 				// implicit falling through the TRUE case
 				if (trueLabel == null) {
-					codeStream.ifnonnull(falseLabel);
+					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 {
 					// no implicit fall through TRUE/FALSE --> should never occur
 				}
 			}
 		}
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
-		return;
 	}
-
-	// default case
-	left.generateCode(currentScope, codeStream, valueRequired);
-	right.generateCode(currentScope, codeStream, valueRequired);
-	if (valueRequired) {
-		if (falseLabel == null) {
-			if (trueLabel != null) {
-				// implicit falling through the FALSE case
-				switch (left.implicitConversion >> 4) { // operand runtime type
-					case T_int :
-						codeStream.if_icmpeq(trueLabel);
-						break;
-					case T_float :
-						codeStream.fcmpl();
-						codeStream.ifeq(trueLabel);
-						break;
-					case T_long :
-						codeStream.lcmp();
-						codeStream.ifeq(trueLabel);
-						break;
-					case T_double :
-						codeStream.dcmpl();
-						codeStream.ifeq(trueLabel);
-						break;
-					default :
-						codeStream.if_acmpeq(trueLabel);
-				}
-			}
-		} else {
-			// implicit falling through the TRUE case
-			if (trueLabel == null) {
-				switch (left.implicitConversion >> 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 {
-				// no implicit fall through TRUE/FALSE --> should never occur
-			}
-		}
+	public boolean isCompactableOperation() {
+		return false;
 	}
-	codeStream.recordPositionsFrom(pc, this.sourceStart);
-}
-public boolean isCompactableOperation() {
-	return false;
-}
-public TypeBinding resolveType(BlockScope scope) {
-
-		boolean leftIsCast, rightIsCast;
-		if ((leftIsCast = left instanceof CastExpression) == true) left.bits |= IgnoreNeedForCastCheckMASK; // will check later on
-		TypeBinding leftType = left.resolveType(scope);
-
-		if ((rightIsCast = right instanceof CastExpression) == true) right.bits |= IgnoreNeedForCastCheckMASK; // will check later on
-		TypeBinding rightType = right.resolveType(scope);
-
-	// always return BooleanBinding
-	if (leftType == null || rightType == null){
-		constant = NotAConstant;		
-		return null;
-	}
-
-	// both base type
-	if (leftType.isBaseType() && rightType.isBaseType()) {
-		// the code is an int
-		// (cast)  left   == (cast)  right --> result
-		//  0000   0000       0000   0000      0000
-		//  <<16   <<12       <<8    <<4       <<0
-		int operatorSignature = OperatorSignatures[EQUAL_EQUAL][ (leftType.id << 4) + rightType.id];
-		left.implicitConversion = operatorSignature >>> 12;
-		right.implicitConversion = (operatorSignature >>> 4) & 0x000FF;
-		bits |= operatorSignature & 0xF;		
-		if ((operatorSignature & 0x0000F) == T_undefined) {
-			constant = Constant.NotAConstant;
-			scope.problemReporter().invalidOperator(this, leftType, rightType);
+	public TypeBinding resolveType(BlockScope scope) {
+	
+			boolean leftIsCast, rightIsCast;
+			if ((leftIsCast = left instanceof CastExpression) == true) left.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+			TypeBinding originalLeftType = left.resolveType(scope);
+	
+			if ((rightIsCast = right instanceof CastExpression) == true) right.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+			TypeBinding originalRightType = right.resolveType(scope);
+	
+		// always return BooleanBinding
+		if (originalLeftType == null || originalRightType == null){
+			constant = NotAConstant;		
 			return null;
 		}
-		// check need for operand cast
-		if (leftIsCast || rightIsCast) {
-			CastExpression.checkNeedForArgumentCasts(scope, EQUAL_EQUAL, operatorSignature, left, leftType.id, leftIsCast, right, rightType.id, rightIsCast);
-		}
-		computeConstant(leftType, rightType);
-		return this.resolvedType = BooleanBinding;
-	}
-
-	// Object references 
-	// spec 15.20.3
-	if (areTypesCastCompatible(scope, rightType, leftType) || areTypesCastCompatible(scope, leftType, rightType)) {
-		// (special case for String)
-		if ((rightType.id == T_String) && (leftType.id == T_String)) {
-			computeConstant(leftType, rightType);
-		} else {
-			constant = NotAConstant;
-		}
-		if (rightType.id == T_String) {
-			right.implicitConversion = String2String;
-		}
-		if (leftType.id == T_String) {
-			left.implicitConversion = String2String;
-		}
-		// check need for operand cast
-		boolean unnecessaryLeftCast = (left.bits & UnnecessaryCastMask) != 0;
-		boolean unnecessaryRightCast = (right.bits & UnnecessaryCastMask) != 0;
-		if (unnecessaryLeftCast || unnecessaryRightCast) {
-			TypeBinding alternateLeftType = unnecessaryLeftCast ? ((CastExpression)left).expression.resolvedType : leftType;
-			TypeBinding alternateRightType = unnecessaryRightCast ? ((CastExpression)right).expression.resolvedType : rightType;
-			if (areTypesCastCompatible(scope, alternateLeftType, alternateRightType)
-					|| areTypesCastCompatible(scope, alternateRightType, alternateLeftType)) {
-				if (unnecessaryLeftCast) scope.problemReporter().unnecessaryCast((CastExpression)left); 
-				if (unnecessaryRightCast) scope.problemReporter().unnecessaryCast((CastExpression)right);
+	
+		// autoboxing support
+		LookupEnvironment env = scope.environment();
+		boolean use15specifics = env.options.sourceLevel >= JDK1_5;
+		TypeBinding leftType = originalLeftType, rightType = originalRightType;
+		if (use15specifics) {
+			if (leftType != NullBinding && leftType.isBaseType()) {
+				if (!rightType.isBaseType()) {
+					rightType = env.computeBoxingType(rightType);
+				}
+			} else {
+				if (rightType != NullBinding && rightType.isBaseType()) {
+					leftType = env.computeBoxingType(leftType);
+				}
 			}
 		}
-		return this.resolvedType = BooleanBinding;
+		// both base type
+		if (leftType.isBaseType() && rightType.isBaseType()) {
+			int leftTypeID = leftType.id;
+			int rightTypeID = rightType.id;
+	
+			// the code is an int
+			// (cast)  left   == (cast)  right --> result
+			//  0000   0000       0000   0000      0000
+			//  <<16   <<12       <<8    <<4       <<0
+			int operatorSignature = OperatorSignatures[EQUAL_EQUAL][ (leftTypeID << 4) + rightTypeID];
+			left.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 16) & 0x0000F), originalLeftType);
+			right.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 8) & 0x0000F), originalRightType);
+			bits |= operatorSignature & 0xF;		
+			if ((operatorSignature & 0x0000F) == T_undefined) {
+				constant = Constant.NotAConstant;
+				scope.problemReporter().invalidOperator(this, leftType, rightType);
+				return null;
+			}
+			// check need for operand cast
+			if (leftIsCast || rightIsCast) {
+				CastExpression.checkNeedForArgumentCasts(scope, EQUAL_EQUAL, operatorSignature, left, leftType.id, leftIsCast, right, rightType.id, rightIsCast);
+			}
+			computeConstant(leftType, rightType);
+			return this.resolvedType = BooleanBinding;
+		}
+	
+		// Object references 
+		// spec 15.20.3
+		if (this.checkCastTypesCompatibility(scope, leftType, rightType, null) 
+				|| this.checkCastTypesCompatibility(scope, rightType, leftType, null)) {
+
+			// (special case for String)
+			if ((rightType.id == T_JavaLangString) && (leftType.id == T_JavaLangString)) {
+				computeConstant(leftType, rightType);
+			} else {
+				constant = NotAConstant;
+			}
+			TypeBinding objectType = scope.getJavaLangObject();
+			left.computeConversion(scope, objectType, leftType);
+			right.computeConversion(scope, objectType, rightType);
+			// check need for operand cast
+			boolean unnecessaryLeftCast = (left.bits & UnnecessaryCastMask) != 0;
+			boolean unnecessaryRightCast = (right.bits & UnnecessaryCastMask) != 0;
+			if (unnecessaryLeftCast || unnecessaryRightCast) {
+				TypeBinding alternateLeftType = unnecessaryLeftCast ? ((CastExpression)left).expression.resolvedType : leftType;
+				TypeBinding alternateRightType = unnecessaryRightCast ? ((CastExpression)right).expression.resolvedType : rightType;
+				if (this.checkCastTypesCompatibility(scope, alternateLeftType, alternateRightType, null) 
+						|| this.checkCastTypesCompatibility(scope, alternateRightType, alternateLeftType, null)) {
+					if (unnecessaryLeftCast) scope.problemReporter().unnecessaryCast((CastExpression)left); 
+					if (unnecessaryRightCast) scope.problemReporter().unnecessaryCast((CastExpression)right);
+				}
+			}
+			return this.resolvedType = BooleanBinding;
+		}
+		constant = NotAConstant;
+		scope.problemReporter().notCompatibleTypesError(this, leftType, rightType);
+		return null;
 	}
-	constant = NotAConstant;
-	scope.problemReporter().notCompatibleTypesError(this, leftType, rightType);
-	return null;
-}
-public void traverse(ASTVisitor visitor, BlockScope scope) {
-	if (visitor.visit(this, scope)) {
-		left.traverse(visitor, scope);
-		right.traverse(visitor, scope);
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		if (visitor.visit(this, scope)) {
+			left.traverse(visitor, scope);
+			right.traverse(visitor, scope);
+		}
+		visitor.endVisit(this, scope);
 	}
-	visitor.endVisit(this, scope);
-}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
index ec709ff..a0b814e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
@@ -15,24 +15,26 @@
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
-public class ExplicitConstructorCall
-	extends Statement
-	implements InvocationSite {
+public class ExplicitConstructorCall extends Statement implements InvocationSite {
 		
 	public Expression[] arguments;
 	public Expression qualification;
-	public MethodBinding binding;
-
+	public MethodBinding binding;							// exact binding resulting from lookup
+	protected MethodBinding codegenBinding;		// actual binding used for code generation (if no synthetic accessor)
+	MethodBinding syntheticAccessor;						// synthetic accessor for inner-emulation
 	public int accessMode;
-
+	public TypeReference[] typeArguments;
+	public TypeBinding[] genericTypeArguments;
+	
 	public final static int ImplicitSuper = 1;
 	public final static int Super = 2;
 	public final static int This = 3;
 
 	public VariableBinding[][] implicitArguments;
 	boolean discardEnclosingInstance;
-
-	MethodBinding syntheticAccessor;
+	
+	// TODO Remove once DOMParser is activated
+	public int typeArgumentsSourceStart;
 
 	public ExplicitConstructorCall(int accessMode) {
 		this.accessMode = accessMode;
@@ -101,8 +103,14 @@
 			int pc = codeStream.position;
 			codeStream.aload_0();
 
+			ReferenceBinding targetType = this.codegenBinding.declaringClass;
+			
+			// special name&ordinal argument generation for enum constructors
+			if (targetType.erasure().id == T_JavaLangEnum || targetType.isEnum()) {
+				codeStream.aload_1(); // pass along name param as name arg
+				codeStream.iload_2(); // pass along ordinal param as ordinal arg
+			}
 			// handling innerclass constructor invocation
-			ReferenceBinding targetType = binding.declaringClass;
 			// handling innerclass instance allocation - enclosing instance arguments
 			if (targetType.isNestedType()) {
 				codeStream.generateSyntheticEnclosingInstanceValues(
@@ -111,12 +119,9 @@
 					discardEnclosingInstance ? null : qualification,
 					this);
 			}
-			// regular code gen
-			if (arguments != null) {
-				for (int i = 0, max = arguments.length; i < max; i++) {
-					arguments[i].generateCode(currentScope, codeStream, true);
-				}
-			}
+			// generate arguments
+			generateArguments(binding, arguments, currentScope, codeStream);			
+			
 			// handling innerclass instance allocation - outer local arguments
 			if (targetType.isNestedType()) {
 				codeStream.generateSyntheticOuterArgumentValues(
@@ -127,21 +132,26 @@
 			if (syntheticAccessor != null) {
 				// synthetic accessor got some extra arguments appended to its signature, which need values
 				for (int i = 0,
-					max = syntheticAccessor.parameters.length - binding.parameters.length;
+					max = syntheticAccessor.parameters.length - this.codegenBinding.parameters.length;
 					i < max;
 					i++) {
 					codeStream.aconst_null();
 				}
 				codeStream.invokespecial(syntheticAccessor);
 			} else {
-				codeStream.invokespecial(binding);
+				codeStream.invokespecial(this.codegenBinding);
 			}
 			codeStream.recordPositionsFrom(pc, this.sourceStart);
 		} finally {
 			((MethodScope) currentScope).isConstructorCall = false;
 		}
 	}
-
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+	 */
+	public TypeBinding[] genericTypeArguments() {
+		return this.genericTypeArguments;
+	}
 	public boolean isImplicitSuper() {
 		//return true if I'm of these compiler added statement super();
 
@@ -166,18 +176,18 @@
 	 * exact need.
 	 */
 	void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
-		ReferenceBinding superType;
+		ReferenceBinding superTypeErasure = (ReferenceBinding) binding.declaringClass.erasure();
 
 		if (!flowInfo.isReachable()) return;
 		// perform some emulation work in case there is some and we are inside a local type only
-		if ((superType = binding.declaringClass).isNestedType()
+		if (superTypeErasure.isNestedType()
 			&& currentScope.enclosingSourceType().isLocalType()) {
 
-			if (superType.isLocalType()) {
-				((LocalTypeBinding) superType).addInnerEmulationDependent(currentScope, qualification != null);
+			if (superTypeErasure.isLocalType()) {
+				((LocalTypeBinding) superTypeErasure).addInnerEmulationDependent(currentScope, qualification != null);
 			} else {
 				// locally propagate, since we already now the desired shape for sure
-				currentScope.propagateInnerEmulation(superType, qualification != null);
+				currentScope.propagateInnerEmulation(superTypeErasure, qualification != null);
 			}
 		}
 	}
@@ -185,19 +195,19 @@
 	public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 
 		if (!flowInfo.isReachable()) return;
+		// if constructor from parameterized type got found, use the original constructor at codegen time
+		this.codegenBinding = this.binding.original();
+		
 		// perform some emulation work in case there is some and we are inside a local type only
-		if (binding.isPrivate() && (accessMode != This)) {
+		if (binding.isPrivate() && accessMode != This) {
 
-			if (currentScope
-				.environment()
-				.options
-				.isPrivateConstructorAccessChangingVisibility) {
-				binding.tagForClearingPrivateModifier();
+			if (currentScope.environment().options.isPrivateConstructorAccessChangingVisibility) {
+				this.codegenBinding.tagForClearingPrivateModifier();
 				// constructor will not be dumped as private, no emulation required thus
 			} else {
 				syntheticAccessor =
-					((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding, isSuperAccess());
-				currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
+					((SourceTypeBinding) this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isSuperAccess());
+				currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this);
 			}
 		}
 	}
@@ -206,6 +216,16 @@
 
 		printIndent(indent, output);
 		if (qualification != null) qualification.printExpression(0, output).append('.');
+		if (typeArguments != null) {
+			output.append('<');//$NON-NLS-1$
+			int max = typeArguments.length - 1;
+			for (int j = 0; j < max; j++) {
+				typeArguments[j].print(0, output);
+				output.append(", ");//$NON-NLS-1$
+			}
+			typeArguments[max].print(0, output);
+			output.append('>');
+		}		
 		if (accessMode == This) {
 			output.append("this("); //$NON-NLS-1$
 		} else {
@@ -243,7 +263,10 @@
 			if (receiverType == null) {
 				return;
 			}
-
+			// prevent (explicit) super constructor invocation from within enum
+			if (this.accessMode == Super && receiverType.erasure().id == T_JavaLangEnum) {
+				scope.problemReporter().cannotInvokeSuperConstructorInEnum(this, methodScope.referenceMethod().binding);
+			}
 			// qualification should be from the type of the enclosingType
 			if (qualification != null) {
 				if (accessMode != Super) {
@@ -259,10 +282,24 @@
 					discardEnclosingInstance = true;
 				} else {
 					TypeBinding qTb = qualification.resolveTypeExpecting(scope, enclosingType);
-					qualification.implicitWidening(qTb, qTb);
+					qualification.computeConversion(scope, qTb, qTb);
 				}
 			}
-
+			// resolve type arguments (for generic constructor call)
+			if (this.typeArguments != null) {
+				int length = this.typeArguments.length;
+				boolean argHasError = false; // typeChecks all arguments
+				this.genericTypeArguments = new TypeBinding[length];
+				for (int i = 0; i < length; i++) {
+					if ((this.genericTypeArguments[i] = this.typeArguments[i].resolveType(scope, true /* check bounds*/)) == null) {
+						argHasError = true;
+					}
+				}
+				if (argHasError) {
+					return;
+				}
+			}			
+	
 			// arguments buffering for the method lookup
 			TypeBinding[] argumentTypes = NoParameters;
 			boolean argsContainCast = false;
@@ -283,24 +320,17 @@
 				if (argHasError) {
 					return;
 				}
+			} else if (receiverType.erasure().id == T_JavaLangEnum) {
+				// TODO (philippe) get rid of once well-known binding is available
+				argumentTypes = new TypeBinding[] { scope.getJavaLangString(), BaseTypes.IntBinding };
 			}
 			if ((binding = scope.getConstructor(receiverType, argumentTypes, this)).isValidBinding()) {
 				if (isMethodUseDeprecated(binding, scope))
 					scope.problemReporter().deprecatedMethod(binding, this);
-
-				// see for user-implicit widening conversion 
-				if (arguments != null) {
-					int length = arguments.length;
-					TypeBinding[] paramTypes = binding.parameters;
-					for (int i = 0; i < length; i++) {
-						arguments[i].implicitWidening(paramTypes[i], argumentTypes[i]);
-					}
-					if (argsContainCast) {
-						CastExpression.checkNeedForArgumentCasts(scope, null, receiverType, binding, this.arguments, argumentTypes, this);
-					}
-				}
+				if (this.arguments != null)
+					checkInvocationArguments(scope, null, receiverType, binding, this.arguments, argumentTypes, argsContainCast, this);
 				if (binding.isPrivate()) {
-					binding.modifiers |= AccPrivateUsed;
+					binding.original().modifiers |= AccPrivateUsed;
 				}				
 			} else {
 				if (binding.declaringClass == null)
@@ -330,6 +360,11 @@
 			if (this.qualification != null) {
 				this.qualification.traverse(visitor, scope);
 			}
+			if (this.typeArguments != null) {
+				for (int i = 0, typeArgumentsLength = this.typeArguments.length; i < typeArgumentsLength; i++) {
+					this.typeArguments[i].traverse(visitor, scope);
+				}			
+			}
 			if (this.arguments != null) {
 				for (int i = 0, argumentLength = this.arguments.length; i < argumentLength; i++)
 					this.arguments[i].traverse(visitor, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
index ae3b502..3b93b9d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
@@ -10,6 +10,10 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
+import java.util.ArrayList;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
@@ -19,41 +23,6 @@
 
 public abstract class Expression extends Statement {
 	
-	//Some expression may not be used - from a java semantic point
-	//of view only - as statements. Other may. In order to avoid the creation
-	//of wrappers around expression in order to tune them as expression
-	//Expression is a subclass of Statement. See the message isValidJavaStatement()
-
-	public int implicitConversion;
-	public TypeBinding resolvedType;
-	
-	public Constant constant;
-
-	public Expression() {
-		super();
-	}
-
-	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-
-		return flowInfo;
-	}
-
-	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
-
-		return analyseCode(currentScope, flowContext, flowInfo);
-	}
-
-	/**
-	 * Constant usable for bytecode pattern optimizations, but cannot be inlined
-	 * since it is not strictly equivalent to the definition of constant expressions.
-	 * In particular, some side-effects may be required to occur (only the end value
-	 * is known).
-	 * @return Constant known to be of boolean type
-	 */ 
-	public Constant optimizedBooleanConstant() {
-		return this.constant;
-	}
-
 	public static final boolean isConstantValueRepresentable(
 		Constant constant,
 		int constantTypeID,
@@ -208,7 +177,392 @@
 				return false; //boolean
 		} 
 	}
+	
+	public Constant constant;
+	
+	//Some expression may not be used - from a java semantic point
+	//of view only - as statements. Other may. In order to avoid the creation
+	//of wrappers around expression in order to tune them as expression
+	//Expression is a subclass of Statement. See the message isValidJavaStatement()
 
+	public int implicitConversion;
+	public TypeBinding resolvedType;
+
+	public Expression() {
+		super();
+	}
+
+	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+		return flowInfo;
+	}
+
+	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
+
+		return analyseCode(currentScope, flowContext, flowInfo);
+	}
+
+	/**
+	 * Returns false if cast is not legal. 
+	 */
+	public final boolean checkCastTypesCompatibility(
+		Scope scope,
+		TypeBinding castType,
+		TypeBinding expressionType,
+		Expression expression) {
+	
+		// see specifications 5.5
+		// handle errors and process constant when needed
+	
+		// if either one of the type is null ==>
+		// some error has been already reported some where ==>
+		// we then do not report an obvious-cascade-error.
+	
+		if (castType == null || expressionType == null) return true;
+	
+		// identity conversion cannot be performed upfront, due to side-effects
+		// like constant propagation
+		LookupEnvironment env = scope.environment();
+		boolean use15specifics = env.options.sourceLevel >= JDK1_5;
+		if (castType.isBaseType()) {
+			if (expressionType.isBaseType()) {
+				if (expressionType == castType) {
+					if (expression != null) {
+						this.constant = expression.constant; //use the same constant
+					}
+					tagAsUnnecessaryCast(scope, castType);
+					return true;
+				}
+				boolean necessary = false;
+				if (expressionType.isCompatibleWith(castType)
+						|| (necessary = BaseTypeBinding.isNarrowing(castType.id, expressionType.id))) {
+					if (expression != null) {
+						expression.implicitConversion = (castType.id << 4) + expressionType.id;
+						if (expression.constant != Constant.NotAConstant) {
+							constant = expression.constant.castTo(expression.implicitConversion);
+						}
+					}
+					if (!necessary) tagAsUnnecessaryCast(scope, castType);
+					return true;
+					
+				}
+			} else if (use15specifics) { // unboxing - only exact match is allowed
+				if (env.computeBoxingType(expressionType) == castType) {
+					// TODO (philippe) could tagAsUnnecessaryCast(scope, castType);  
+					return true;
+				}
+			}
+			reportIllegalCast(scope, castType, expressionType);
+			return false;
+		} else if (use15specifics && expressionType.isBaseType()) { // boxing - only exact match is allowed
+			if (env.computeBoxingType(castType) == expressionType) {
+				// TODO (philippe) could tagAsUnnecessaryCast(scope, castType);  
+				return true;
+			}
+		}
+	
+		//-----------cast to something which is NOT a base type--------------------------	
+		if (expressionType == NullBinding) {
+			tagAsUnnecessaryCast(scope, castType);
+			return true; //null is compatible with every thing
+		}
+		if (expressionType.isBaseType()) {
+			reportIllegalCast(scope, castType, expressionType);
+			return false;
+		}
+	
+		if (expressionType.isArrayType()) {
+			if (castType == expressionType) {
+				tagAsUnnecessaryCast(scope, castType);
+				return true; // identity conversion
+			}
+	
+			if (castType.isArrayType()) {
+				//------- (castType.isArray) expressionType.isArray -----------
+				TypeBinding exprElementType = ((ArrayBinding) expressionType).elementsType();
+				if (exprElementType.isBaseType()) {
+					// <---stop the recursion------- 
+					if (((ArrayBinding) castType).elementsType() == exprElementType) {
+						tagAsNeedCheckCast();
+						return true;
+					} else {
+						reportIllegalCast(scope, castType, expressionType);
+						return false;
+					}
+				}
+				// recursively on the elements...
+				return checkCastTypesCompatibility(
+					scope,
+					((ArrayBinding) castType).elementsType(),
+					exprElementType,
+					expression);
+			} else if (castType.isTypeVariable()) {
+				TypeBinding match = ((ReferenceBinding)expressionType).findSuperTypeErasingTo((ReferenceBinding)castType);
+				if (match == null) {
+					checkUnsafeCast(scope, castType, expressionType, match, true);
+				}
+				// recursively on the type variable upper bound
+				return checkCastTypesCompatibility(
+					scope,
+					castType.erasure(),
+					expressionType,
+					expression);
+			} else if (castType.isClass()) {
+				//------(castType.isClass) expressionType.isArray ---------------	
+				if (castType.id == T_JavaLangObject) {
+					tagAsUnnecessaryCast(scope, castType);
+					return true;
+				}
+			} else { //------- (castType.isInterface) expressionType.isArray -----------
+				if (castType.id == T_JavaLangCloneable || castType.id == T_JavaIoSerializable) {
+					tagAsNeedCheckCast();
+					return true;
+				}
+			}
+			reportIllegalCast(scope, castType, expressionType);
+			return false;
+		}
+		if (expressionType.isTypeVariable() || expressionType.isWildcard()) {
+			TypeBinding match = ((ReferenceBinding)expressionType).findSuperTypeErasingTo((ReferenceBinding)castType);
+			if (match != null) {
+				tagAsUnnecessaryCast(scope, castType);
+				return true;
+			}
+			// recursively on the type variable upper bound
+			return checkCastTypesCompatibility(
+				scope,
+				castType,
+				expressionType.erasure(),
+				expression);
+		}
+		
+		if (expressionType.isClass()) {
+			if (castType.isArrayType()) {
+				// ---- (castType.isArray) expressionType.isClass -------
+				if (expressionType.id == T_JavaLangObject) { // potential runtime error
+					tagAsNeedCheckCast();
+					return true;
+				}
+			} else if (castType.isTypeVariable()) {
+				TypeBinding match = ((ReferenceBinding)expressionType).findSuperTypeErasingTo((ReferenceBinding)castType);
+				if (match == null) {
+					checkUnsafeCast(scope, castType, expressionType, match, true);
+				}
+				// recursively on the type variable upper bound
+				return checkCastTypesCompatibility(
+					scope,
+					castType.erasure(),
+					expressionType,
+					expression);
+			} else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isClass ------
+				TypeBinding match = ((ReferenceBinding)expressionType).findSuperTypeErasingTo((ReferenceBinding)castType.erasure());
+				if (match != null) {
+					if (expression != null && castType.id == T_JavaLangString) this.constant = expression.constant; // (String) cst is still a constant
+					return checkUnsafeCast(scope, castType, expressionType, match, false);
+				}
+				match = ((ReferenceBinding)castType).findSuperTypeErasingTo((ReferenceBinding)expressionType.erasure());
+				if (match != null) {
+					tagAsNeedCheckCast();
+					return checkUnsafeCast(scope, castType, expressionType, match, true);
+				}
+			} else { // ----- (castType.isInterface) expressionType.isClass -------  
+
+				TypeBinding match = ((ReferenceBinding)expressionType).findSuperTypeErasingTo((ReferenceBinding)castType.erasure());
+				if (match != null) {
+					return checkUnsafeCast(scope, castType, expressionType, match, false);
+				}
+				// a subclass may implement the interface ==> no check at compile time
+				if (!((ReferenceBinding) expressionType).isFinal()) {
+					tagAsNeedCheckCast();
+					match = ((ReferenceBinding)castType).findSuperTypeErasingTo((ReferenceBinding)expressionType.erasure());
+					if (match != null) {
+						return checkUnsafeCast(scope, castType, expressionType, match, true);
+					}
+					return true;
+				}
+				// no subclass for expressionType, thus compile-time check is valid
+			}
+			reportIllegalCast(scope, castType, expressionType);
+			return false;
+		}
+	
+		//	if (expressionType.isInterface()) { cannot be anything else
+		if (castType.isArrayType()) {
+			// ----- (castType.isArray) expressionType.isInterface ------
+			if (expressionType.id == T_JavaLangCloneable
+					|| expressionType.id == T_JavaIoSerializable) {// potential runtime error
+				tagAsNeedCheckCast();
+				return true;
+			} else {
+				reportIllegalCast(scope, castType, expressionType);
+				return false;
+			}
+		} else if (castType.isTypeVariable()) {
+			TypeBinding match = ((ReferenceBinding)expressionType).findSuperTypeErasingTo((ReferenceBinding)castType);
+			if (match == null) {
+				checkUnsafeCast(scope, castType, expressionType, match, true);
+			}
+			// recursively on the type variable upper bound
+			return checkCastTypesCompatibility(
+				scope,
+				castType.erasure(),
+				expressionType,
+				expression);
+		} else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isInterface --------
+
+			if (castType.id == T_JavaLangObject) { // no runtime error
+				tagAsUnnecessaryCast(scope, castType);
+				return true;
+			}
+			if (((ReferenceBinding) castType).isFinal()) {
+				// no subclass for castType, thus compile-time check is valid
+				TypeBinding match = ((ReferenceBinding)castType).findSuperTypeErasingTo((ReferenceBinding)expressionType.erasure());
+				if (match == null) {
+					// potential runtime error
+					reportIllegalCast(scope, castType, expressionType);
+					return false;
+				}				
+			}
+		} else { // ----- (castType.isInterface) expressionType.isInterface -------
+
+			TypeBinding match = ((ReferenceBinding)expressionType).findSuperTypeErasingTo((ReferenceBinding)castType.erasure());
+			if (match != null) {
+				return checkUnsafeCast(scope, castType, expressionType, match, false);
+			}
+			
+			match = ((ReferenceBinding)castType).findSuperTypeErasingTo((ReferenceBinding)expressionType.erasure());
+			if (match != null) {
+				tagAsNeedCheckCast();
+				return checkUnsafeCast(scope, castType, expressionType, match, true);
+			}  else {
+				MethodBinding[] castTypeMethods = getAllInheritedMethods((ReferenceBinding) castType);
+				MethodBinding[] expressionTypeMethods =
+					getAllInheritedMethods((ReferenceBinding) expressionType);
+				int exprMethodsLength = expressionTypeMethods.length;
+				for (int i = 0, castMethodsLength = castTypeMethods.length; i < castMethodsLength; i++) {
+					for (int j = 0; j < exprMethodsLength; j++) {
+						if ((castTypeMethods[i].returnType != expressionTypeMethods[j].returnType)
+								&& (CharOperation.equals(castTypeMethods[i].selector, expressionTypeMethods[j].selector))
+								&& castTypeMethods[i].areParametersEqual(expressionTypeMethods[j])) {
+							reportIllegalCast(scope, castType, expressionType);
+							return false;
+
+						}
+					}
+				}
+			}
+		}
+		tagAsNeedCheckCast();
+		return true;
+	}	
+	
+	public FlowInfo checkNullStatus(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, int nullStatus) {
+
+		LocalVariableBinding local = this.localVariableBinding();
+		if (local != null) {
+			switch(nullStatus) {
+				case FlowInfo.NULL :
+					flowContext.recordUsingNullReference(scope, local, this, FlowInfo.NULL, flowInfo);
+					flowInfo.markAsDefinitelyNull(local); // from thereon it is set
+					break;
+				case FlowInfo.NON_NULL :
+					flowContext.recordUsingNullReference(scope, local, this, FlowInfo.NON_NULL, flowInfo);
+					flowInfo.markAsDefinitelyNonNull(local); // from thereon it is set
+					break;
+				case FlowInfo.UNKNOWN :
+					break;
+			}
+		}
+		return flowInfo;
+	}
+
+	private MethodBinding[] getAllInheritedMethods(ReferenceBinding binding) {
+		ArrayList collector = new ArrayList();
+		getAllInheritedMethods0(binding, collector);
+		return (MethodBinding[]) collector.toArray(new MethodBinding[collector.size()]);
+	}
+	
+	private void getAllInheritedMethods0(ReferenceBinding binding, ArrayList collector) {
+		if (!binding.isInterface()) return;
+		MethodBinding[] methodBindings = binding.methods();
+		for (int i = 0, max = methodBindings.length; i < max; i++) {
+			collector.add(methodBindings[i]);
+		}
+		ReferenceBinding[] superInterfaces = binding.superInterfaces();
+		for (int i = 0, max = superInterfaces.length; i < max; i++) {
+			getAllInheritedMethods0(superInterfaces[i], collector);
+		}
+	}
+	public void checkNullComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse) {
+		// do nothing by default - see EqualExpression
+	}
+
+	public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding expressionType, TypeBinding match, boolean isNarrowing) {
+		if (match == castType) {
+			if (!isNarrowing) tagAsUnnecessaryCast(scope, castType);
+			return true;
+		}
+		if (castType.isBoundParameterizedType() || castType.isGenericType()) {
+			if (match.isProvablyDistinctFrom(isNarrowing ? expressionType : castType, 0)) {
+				reportIllegalCast(scope, castType, expressionType);
+				return false; 
+			}
+		}
+		if (!isNarrowing) tagAsUnnecessaryCast(scope, castType);
+		return true;
+	}
+	
+	/**
+	 * Base types need that the widening is explicitly done by the compiler using some bytecode like i2f.
+	 * Also check unsafe type operations.
+	 */ 
+	public void computeConversion(Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) {
+
+		if (runtimeTimeType == null || compileTimeType == null)
+			return;
+		if (this.implicitConversion != 0) return; // already set independantly
+
+		// it is possible for a Byte to be unboxed to a byte & then converted to an int
+		// but it is not possible for a byte to become Byte & then assigned to an Integer,
+		// or to become an int before boxed into an Integer
+		if (runtimeTimeType != NullBinding && runtimeTimeType.isBaseType()) {
+			if (!compileTimeType.isBaseType()) {
+				TypeBinding unboxedType = scope.environment().computeBoxingType(compileTimeType);
+				this.implicitConversion = UNBOXING;
+				scope.problemReporter().autoboxing(this, compileTimeType, runtimeTimeType);
+				compileTimeType = unboxedType;
+			}
+		} else {
+			if (compileTimeType != NullBinding && compileTimeType.isBaseType()) {
+				TypeBinding boxedType = scope.environment().computeBoxingType(runtimeTimeType);
+				if (boxedType == runtimeTimeType) // Object o = 12;
+					boxedType = compileTimeType; 
+				this.implicitConversion = BOXING | (boxedType.id << 4) + compileTimeType.id;
+				scope.problemReporter().autoboxing(this, compileTimeType, runtimeTimeType);
+				return;
+			}
+		}
+
+		switch (runtimeTimeType.id) {
+			case T_byte :
+			case T_short :
+			case T_char :
+				this.implicitConversion |= (T_int << 4) + compileTimeType.id;
+				break;
+			case T_JavaLangString :
+			case T_float :
+			case T_boolean :
+			case T_double :
+			case T_int : //implicitConversion may result in i2i which will result in NO code gen
+			case T_long :
+				this.implicitConversion |= (runtimeTimeType.id << 4) + compileTimeType.id;
+				break;
+			default : // regular object ref
+//				if (compileTimeType.isRawType() && runtimeTimeType.isBoundParameterizedType()) {
+//				    scope.problemReporter().unsafeRawExpression(this, compileTimeType, runtimeTimeType);
+//				}		
+		}
+	}	
 	/**
 	 * Expression statements are plain expressions, however they generate like
 	 * normal expressions with no value required.
@@ -317,93 +671,58 @@
 	 * creation, further operands should rather be only appended to the current one.
 	 * By default: no optimization.
 	 */
-	public void generateOptimizedStringBuffer(
+	public void generateOptimizedStringConcatenation(
 		BlockScope blockScope,
-		org.eclipse.jdt.internal.compiler.codegen.CodeStream codeStream,
+		CodeStream codeStream,
 		int typeID) {
 
-		if (typeID == T_String && this.constant != NotAConstant && this.constant.stringValue().length() == 0) {
+		if (typeID == T_JavaLangString && this.constant != NotAConstant && this.constant.stringValue().length() == 0) {
 			return; // optimize str + ""
 		}
 		generateCode(blockScope, codeStream, true);
-		codeStream.invokeStringBufferAppendForType(typeID);
+		codeStream.invokeStringConcatenationAppendForType(typeID);
 	}
 
 	/* Optimized (java) code generation for string concatenations that involve StringBuffer
 	 * creation: going through this path means that there is no need for a new StringBuffer
 	 * creation, further operands should rather be only appended to the current one.
 	 */
-	public void generateOptimizedStringBufferCreation(
+	public void generateOptimizedStringConcatenationCreation(
 		BlockScope blockScope,
 		CodeStream codeStream,
 		int typeID) {
 
-		// Optimization only for integers and strings
-		if (typeID == T_Object) {
-			// in the case the runtime value of valueOf(Object) returns null, we have to use append(Object) instead of directly valueOf(Object)
-			// append(Object) returns append(valueOf(Object)), which means that the null case is handled by append(String).
-			codeStream.newStringBuffer();
-			codeStream.dup();
-			codeStream.invokeStringBufferDefaultConstructor();
-			generateCode(blockScope, codeStream, true);
-			codeStream.invokeStringBufferAppendForType(T_Object);
-			return;
-		}
-		codeStream.newStringBuffer();
+		codeStream.newStringContatenation();
 		codeStream.dup();
-		if (typeID == T_String || typeID == T_null) {
-			if (constant != NotAConstant) {
-				String stringValue = constant.stringValue();
-				if (stringValue.length() == 0) {  // optimize ""+<str> 
-					codeStream.invokeStringBufferDefaultConstructor();
-					return;
-				}
-				codeStream.ldc(stringValue);
-			} else {
+		switch (typeID) {
+			case T_JavaLangObject :
+			case T_undefined :
+				// in the case the runtime value of valueOf(Object) returns null, we have to use append(Object) instead of directly valueOf(Object)
+				// append(Object) returns append(valueOf(Object)), which means that the null case is handled by the next case.
+				codeStream.invokeStringConcatenationDefaultConstructor();
 				generateCode(blockScope, codeStream, true);
-				codeStream.invokeStringValueOf(T_Object);
-			}
-		} else {
-			generateCode(blockScope, codeStream, true);
-			codeStream.invokeStringValueOf(typeID);
-		}
-		codeStream.invokeStringBufferStringConstructor();
-	}
-
-	// Base types need that the widening is explicitly done by the compiler using some bytecode like i2f
-	public void implicitWidening(
-		TypeBinding runtimeTimeType,
-		TypeBinding compileTimeType) {
-
-		if (runtimeTimeType == null || compileTimeType == null)
-			return;
-
-//		if (compileTimeType.id == T_null) {
-//			// this case is possible only for constant null
-//			// The type of runtime is a reference type
-//			// The code gen use the constant id thus any value
-//			// for the runtime id (akak the <<4) could be used.
-//			// T_Object is used as some general T_reference
-//			implicitConversion = (T_Object << 4) + T_null;
-//			return;
-//		}
-
-		switch (runtimeTimeType.id) {
-			case T_byte :
-			case T_short :
-			case T_char :
-				implicitConversion = (T_int << 4) + compileTimeType.id;
+				codeStream.invokeStringConcatenationAppendForType(T_JavaLangObject);
+				return;
+			case T_JavaLangString :
+			case T_null :
+				if (constant != NotAConstant) {
+					String stringValue = constant.stringValue();
+					if (stringValue.length() == 0) {  // optimize ""+<str> 
+						codeStream.invokeStringConcatenationDefaultConstructor();
+						return;
+					}
+					codeStream.ldc(stringValue);
+				} else {
+					// null case is not a constant
+					generateCode(blockScope, codeStream, true);
+					codeStream.invokeStringValueOf(T_JavaLangObject);
+				}
 				break;
-			case T_String :
-			case T_float :
-			case T_boolean :
-			case T_double :
-			case T_int : //implicitConversion may result in i2i which will result in NO code gen
-			case T_long :
-				implicitConversion = (runtimeTimeType.id << 4) + compileTimeType.id;
-				break;
-			default : //nothing on regular object ref
+			default :
+				generateCode(blockScope, codeStream, true);
+				codeStream.invokeStringValueOf(typeID);
 		}
+		codeStream.invokeStringConcatenationStringConstructor();
 	}
 
 	public boolean isCompactableOperation() {
@@ -413,11 +732,9 @@
 
 	//Return true if the conversion is done AUTOMATICALLY by the vm
 	//while the javaVM is an int based-machine, thus for example pushing
-	//a byte onto the stack , will automatically creates a int on the stack
+	//a byte onto the stack , will automatically create an int on the stack
 	//(this request some work d be done by the VM on signed numbers)
-	public boolean isConstantValueOfTypeAssignableToType(
-		TypeBinding constantType,
-		TypeBinding targetType) {
+	public boolean isConstantValueOfTypeAssignableToType(TypeBinding constantType, TypeBinding targetType) {
 
 		if (constant == Constant.NotAConstant)
 			return false;
@@ -438,7 +755,49 @@
 	public boolean isTypeReference() {
 		return false;
 	}
+	
+	public int nullStatus(FlowInfo flowInfo) {
+		
+		if (this.constant != null && this.constant != NotAConstant)
+			return FlowInfo.NON_NULL; // constant expression cannot be null
+		
+		LocalVariableBinding local = localVariableBinding();
+		if (local != null) {
+			if (flowInfo.isDefinitelyNull(local))
+				return FlowInfo.NULL;
+			if (flowInfo.isDefinitelyNonNull(local))
+				return FlowInfo.NON_NULL;
+			return FlowInfo.UNKNOWN;
+		}
+		return FlowInfo.NON_NULL;
+	}
+	
+	/**
+	 * Constant usable for bytecode pattern optimizations, but cannot be inlined
+	 * since it is not strictly equivalent to the definition of constant expressions.
+	 * In particular, some side-effects may be required to occur (only the end value
+	 * is known).
+	 * @return Constant known to be of boolean type
+	 */ 
+	public Constant optimizedBooleanConstant() {
+		return this.constant;
+	}
 
+	public StringBuffer print(int indent, StringBuffer output) {
+		printIndent(indent, output);
+		return printExpression(indent, output);
+	}
+
+	public abstract StringBuffer printExpression(int indent, StringBuffer output);
+	
+	public StringBuffer printStatement(int indent, StringBuffer output) {
+		return print(indent, output).append(";"); //$NON-NLS-1$
+	}
+
+	public void reportIllegalCast(Scope scope, TypeBinding castType, TypeBinding expressionType) {
+		// do nothing by default
+	}
+	
 	public void resolve(BlockScope scope) {
 		// drops the returning expression's type whatever the type is.
 
@@ -461,28 +820,39 @@
 		BlockScope scope,
 		TypeBinding expectedType) {
 
+		this.setExpectedType(expectedType); // needed in case of generic method invocation
 		TypeBinding expressionType = this.resolveType(scope);
 		if (expressionType == null) return null;
 		if (expressionType == expectedType) return expressionType;
 		
 		if (!expressionType.isCompatibleWith(expectedType)) {
-			scope.problemReporter().typeMismatchError(expressionType, expectedType, this);
-			return null;
+			if (scope.isBoxingCompatibleWith(expressionType, expectedType)) {
+				this.computeConversion(scope, expectedType, expressionType);
+			} else {
+				scope.problemReporter().typeMismatchError(expressionType, expectedType, this);
+				return null;
+			}
 		}
 		return expressionType;
 	}
 
-	public StringBuffer print(int indent, StringBuffer output) {
-		printIndent(indent, output);
-		return printExpression(indent, output);
+	/**
+	 * Record the type expectation before this expression is typechecked.
+	 * e.g. String s = foo();, foo() will be tagged as being expected of type String
+	 * Used to trigger proper inference of generic method invocations.
+	 */
+	public void setExpectedType(TypeBinding expectedType) {
+	    // do nothing by default
 	}
 
-	public abstract StringBuffer printExpression(int indent, StringBuffer output);
+	public void tagAsUnnecessaryCast(Scope scope, TypeBinding castType) {
+	    // do nothing by default
+	}
 	
-	public StringBuffer printStatement(int indent, StringBuffer output) {
-		return print(indent, output).append(";"); //$NON-NLS-1$
+	public void tagAsNeedCheckCast() {
+	    // do nothing by default		
 	}
-
+	
 	public Expression toTypeReference() {
 		//by default undefined
 
@@ -493,4 +863,21 @@
 
 		return this;
 	}
+	
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		// do nothing by default
+	}
+	public void traverse(ASTVisitor visitor, ClassScope scope) {
+		// do nothing by default
+	}
+	public void traverse(ASTVisitor visitor, CompilationUnitScope scope) {
+		// do nothing by default
+	}
+	/**
+	 * Returns the local variable referenced by this node. Can be a direct reference (SingleNameReference)
+	 * or thru a cast expression etc...
+	 */
+	public LocalVariableBinding localVariableBinding() {
+		return null;
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java
index 82bc72d..6219111 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java
@@ -21,8 +21,8 @@
 	super(s,e);
 }
 public void computeConstant() {
-
-	constant = Constant.fromValue(false);}
+	constant = Constant.fromValue(false);
+}
 /**
  * Code generation for false literal
  *
@@ -32,8 +32,9 @@
  */
 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
 	int pc = codeStream.position;
-	if (valueRequired)
-		codeStream.iconst_0();
+	if (valueRequired) {
+		codeStream.generateConstant(this.constant, this.implicitConversion);
+	}
 	codeStream.recordPositionsFrom(pc, this.sourceStart);
 }
 public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
index 7f001c3..576d51a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
@@ -17,6 +17,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class FieldDeclaration extends AbstractVariableDeclaration {
+	
 	public FieldBinding binding;
 	boolean hasBeenResolved = false;
 	public Javadoc javadoc;
@@ -62,17 +63,28 @@
 		}
 		// cannot define static non-constant field inside nested class
 		if (this.binding != null
-			&& this.binding.isValidBinding()
-			&& this.binding.isStatic()
-			&& this.binding.constant == NotAConstant
-			&& this.binding.declaringClass.isNestedType()
-			&& this.binding.declaringClass.isClass()
-			&& !this.binding.declaringClass.isStatic()) {
+				&& this.binding.isValidBinding()
+				&& this.binding.isStatic()
+				&& !this.binding.isConstantValue()
+				&& this.binding.declaringClass.isNestedType()
+				&& this.binding.declaringClass.isClass()
+				&& !this.binding.declaringClass.isStatic()) {
 			initializationScope.problemReporter().unexpectedStaticModifierForField(
 				(SourceTypeBinding) this.binding.declaringClass,
 				this);
 		}
 
+		checkAnnotationField: {
+			if (!this.binding.declaringClass.isAnnotationType())
+				break checkAnnotationField;
+			if (this.initialization != null) {
+				if (this.binding.type.isArrayType() && (this.initialization instanceof ArrayInitializer))
+					break checkAnnotationField;
+				if (this.initialization.constant != NotAConstant)
+					break checkAnnotationField;
+			}
+			initializationScope.problemReporter().annotationFieldNeedConstantInitialization(this);
+		}
 		if (this.initialization != null) {
 			flowInfo =
 				this.initialization
@@ -100,7 +112,7 @@
 		int pc = codeStream.position;
 		boolean isStatic;
 		if (this.initialization != null
-			&& !((isStatic = this.binding.isStatic()) && this.binding.constant != NotAConstant)) {
+			&& !((isStatic = this.binding.isStatic()) && this.binding.isConstantValue())) {
 			// non-static field, need receiver
 			if (!isStatic)
 				codeStream.aload_0();
@@ -116,16 +128,13 @@
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 
-	public TypeBinding getTypeBinding(Scope scope) {
-
-		return this.type.getTypeBinding(scope);
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
+	 */
+	public int getKind() {
+		return this.type == null ? ENUM_CONSTANT : FIELD;
 	}
-
-	public boolean isField() {
-
-		return true;
-	}
-
+	
 	public boolean isStatic() {
 
 		if (this.binding != null)
@@ -144,6 +153,8 @@
 
 			this.hasBeenResolved = true;
 
+			resolveAnnotations(initializationScope, this.annotations, this.binding);
+
 			// check if field is hiding some variable - issue is that field binding already got inserted in scope
 			// thus must lookup separately in super type and outer context
 			ClassScope classScope = initializationScope.enclosingClassScope();
@@ -153,7 +164,7 @@
 				boolean checkLocal = true;
 				if (declaringType.superclass != null) {
 					Binding existingVariable = classScope.findField(declaringType.superclass, this.name, this,  false /*do not resolve hidden field*/);
-					if (existingVariable != null && existingVariable.isValidBinding()){
+					if (existingVariable != null && this.binding != existingVariable && existingVariable.isValidBinding()){
 						initializationScope.problemReporter().fieldHiding(this, existingVariable);
 						checkLocal = false; // already found a matching field
 					}
@@ -162,17 +173,21 @@
 					Scope outerScope = classScope.parent;
 					// only corner case is: lookup of outer field through static declaringType, which isn't detected by #getBinding as lookup starts
 					// from outer scope. Subsequent static contexts are detected for free.
-					Binding existingVariable = outerScope.getBinding(this.name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
-					if (existingVariable != null && existingVariable.isValidBinding()
-							&& (!(existingVariable instanceof FieldBinding)
-									|| ((FieldBinding) existingVariable).isStatic() 
-									|| !declaringType.isStatic())) {
-						initializationScope.problemReporter().fieldHiding(this, existingVariable);
+					if (outerScope.kind != Scope.COMPILATION_UNIT_SCOPE) {
+						Binding existingVariable = outerScope.getBinding(this.name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
+						if (existingVariable != null && this.binding != existingVariable && existingVariable.isValidBinding()
+								&& (!(existingVariable instanceof FieldBinding)
+										|| ((FieldBinding) existingVariable).isStatic() 
+										|| !declaringType.isStatic())) {
+							initializationScope.problemReporter().fieldHiding(this, existingVariable);
+						}
 					}
 				}
 			}
 			
-			this.type.resolvedType = this.binding.type; // update binding for type reference
+			if (this.type != null ) { // enum constants have no declared type
+				this.type.resolvedType = this.binding.type; // update binding for type reference
+			}
 
 			FieldBinding previousField = initializationScope.initializedField;
 			int previousFieldID = initializationScope.lastVisibleFieldID;
@@ -180,45 +195,48 @@
 				initializationScope.initializedField = this.binding;
 				initializationScope.lastVisibleFieldID = this.binding.id;
 
-				if (isTypeUseDeprecated(this.binding.type, initializationScope)) {
-					initializationScope.problemReporter().deprecatedType(this.binding.type, this.type);
-				}
 				// the resolution of the initialization hasn't been done
 				if (this.initialization == null) {
-					this.binding.constant = Constant.NotAConstant;
+					this.binding.setConstant(Constant.NotAConstant);
 				} else {
 					// break dead-lock cycles by forcing constant to NotAConstant
-					this.binding.constant = Constant.NotAConstant;
+					this.binding.setConstant(Constant.NotAConstant);
 					
-					TypeBinding typeBinding = this.binding.type;
-					TypeBinding initializationTypeBinding;
-					
+					TypeBinding fieldType = this.binding.type;
+					TypeBinding initializationType;
+					this.initialization.setExpectedType(fieldType); // needed in case of generic method invocation
 					if (this.initialization instanceof ArrayInitializer) {
 
-						if ((initializationTypeBinding = this.initialization.resolveTypeExpecting(initializationScope, typeBinding)) != null) {
-							((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationTypeBinding;
-							this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
+						if ((initializationType = this.initialization.resolveTypeExpecting(initializationScope, fieldType)) != null) {
+							((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationType;
+							this.initialization.computeConversion(initializationScope, fieldType, initializationType);
 						}
-					} else if ((initializationTypeBinding = this.initialization.resolveType(initializationScope)) != null) {
+					} else if ((initializationType = this.initialization.resolveType(initializationScope)) != null) {
 
-						if (this.initialization.isConstantValueOfTypeAssignableToType(initializationTypeBinding, typeBinding)
-							|| (typeBinding.isBaseType() && BaseTypeBinding.isWidening(typeBinding.id, initializationTypeBinding.id))) {
-
-							this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
-
-						}	else if (initializationTypeBinding.isCompatibleWith(typeBinding)) {
-							this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
-
+						if (fieldType != initializationType) // must call before computeConversion() and typeMismatchError()
+							initializationScope.compilationUnitScope().recordTypeConversion(fieldType, initializationType);
+						if (this.initialization.isConstantValueOfTypeAssignableToType(initializationType, fieldType)
+								|| (fieldType.isBaseType() && BaseTypeBinding.isWidening(fieldType.id, initializationType.id))
+								|| initializationType.isCompatibleWith(fieldType)) {
+							this.initialization.computeConversion(initializationScope, fieldType, initializationType);
+							if (initializationType.needsUncheckedConversion(fieldType)) {
+								    initializationScope.problemReporter().unsafeRawConversion(this.initialization, initializationType, fieldType);
+							}									
+						} else if (initializationScope.environment().options.sourceLevel >= JDK1_5 // autoboxing
+										&& (initializationScope.isBoxingCompatibleWith(initializationType, fieldType) 
+												|| (initializationType.isBaseType()  // narrowing then boxing ?
+														&& initializationType != null 
+														&& !fieldType.isBaseType()
+														&& initialization.isConstantValueOfTypeAssignableToType(initializationType, initializationScope.environment().computeBoxingType(fieldType))))) {
+							this.initialization.computeConversion(initializationScope, fieldType, initializationType);
 						} else {
-							initializationScope.problemReporter().typeMismatchError(initializationTypeBinding, typeBinding, this);
+							initializationScope.problemReporter().typeMismatchError(initializationType, fieldType, this);
 						}
 						if (this.binding.isFinal()){ // cast from constant actual type to variable type
-							this.binding.constant =
-								this.initialization.constant.castTo(
-									(this.binding.type.id << 4) + this.initialization.constant.typeID());
+							this.binding.setConstant(this.initialization.constant.castTo((this.binding.type.id << 4) + this.initialization.constant.typeID()));
 						}
 					} else {
-						this.binding.constant = NotAConstant;
+						this.binding.setConstant(NotAConstant);
 					}
 				}
 				// Resolve Javadoc comment if one is present
@@ -235,8 +253,8 @@
 			} finally {
 				initializationScope.initializedField = previousField;
 				initializationScope.lastVisibleFieldID = previousFieldID;
-				if (this.binding.constant == null)
-					this.binding.constant = Constant.NotAConstant;
+				if (this.binding.constant() == null)
+					this.binding.setConstant(Constant.NotAConstant);
 			}
 		}
 	}
@@ -244,7 +262,14 @@
 	public void traverse(ASTVisitor visitor, MethodScope scope) {
 
 		if (visitor.visit(this, scope)) {
-			this.type.traverse(visitor, scope);
+			if (this.annotations != null) {
+				int annotationsLength = this.annotations.length;
+				for (int i = 0; i < annotationsLength; i++)
+					this.annotations[i].traverse(visitor, scope);
+			}
+			if (this.type != null) {
+				this.type.traverse(visitor, scope);
+			}
 			if (this.initialization != null)
 				this.initialization.traverse(visitor, scope);
 		}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
index 9c4a86d..1e00105 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
@@ -21,11 +21,16 @@
 
 	public Expression receiver;
 	public char[] token;
-	public FieldBinding binding, codegenBinding;
+	public FieldBinding binding;															// exact binding resulting from lookup
+	protected FieldBinding codegenBinding;									// actual binding used for code generation (if no synthetic accessor)
+	public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor
+	public static final int READ = 0;
+	public static final int WRITE = 1;
+	
 	public long nameSourcePosition; //(start<<32)+end
-	MethodBinding syntheticReadAccessor, syntheticWriteAccessor;
 	public TypeBinding receiverType;
-
+	public TypeBinding genericCast;
+	
 	public FieldReference(char[] source, long pos) {
 
 		token = source;
@@ -33,7 +38,7 @@
 		//by default the position are the one of the field (not true for super access)
 		sourceStart = (int) (pos >>> 32);
 		sourceEnd = (int) (pos & 0x00000000FFFFFFFFL);
-		bits |= BindingIds.FIELD;
+		bits |= Binding.FIELD;
 
 	}
 
@@ -53,7 +58,7 @@
 				currentScope.problemReporter().uninitializedBlankFinalField(binding, this);
 				// we could improve error msg here telling "cannot use compound assignment on final blank field"
 			}
-			manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
+			manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/);
 		}
 		flowInfo =
 			receiver
@@ -66,7 +71,7 @@
 					.analyseCode(currentScope, flowContext, flowInfo)
 					.unconditionalInits();
 		}
-		manageSyntheticWriteAccessIfNecessary(currentScope, flowInfo);
+		manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/);
 
 		// check if assigning a final field 
 		if (binding.isFinal()) {
@@ -107,13 +112,35 @@
 		FlowInfo flowInfo,
 		boolean valueRequired) {
 
-		receiver.analyseCode(currentScope, flowContext, flowInfo, !binding.isStatic());
+		boolean nonStatic = !binding.isStatic();
+		receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic);
+		if (nonStatic) receiver.checkNullStatus(currentScope, flowContext, flowInfo, FlowInfo.NON_NULL);
+		
 		if (valueRequired) {
-			manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
+			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) {
+			        this.genericCast = originalBinding.type.genericCast(scope.boxing(runtimeTimeType)); // runtimeType could be base type in boxing case
+			    }
+			}
+		} 	
+		super.computeConversion(scope, runtimeTimeType, compileTimeType);
+	}
+
 	public FieldBinding fieldBinding() {
 
 		return binding;
@@ -133,11 +160,12 @@
 		fieldStore(
 			codeStream,
 			this.codegenBinding,
-			syntheticWriteAccessor,
+			syntheticAccessors == null ? null : syntheticAccessors[WRITE],
 			valueRequired);
 		if (valueRequired) {
 			codeStream.generateImplicitConversion(assignment.implicitConversion);
 		}
+		// no need for generic cast as value got dupped
 	}
 
 	/**
@@ -161,27 +189,28 @@
 			boolean isStatic = this.codegenBinding.isStatic();
 			receiver.generateCode(currentScope, codeStream, !isStatic);
 			if (valueRequired) {
-				if (this.codegenBinding.constant == NotAConstant) {
+				if (!this.codegenBinding.isConstantValue()) {
 					if (this.codegenBinding.declaringClass == null) { // array length
 						codeStream.arraylength();
 					} else {
-						if (syntheticReadAccessor == null) {
+						if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
 							if (isStatic) {
 								codeStream.getstatic(this.codegenBinding);
 							} else {
 								codeStream.getfield(this.codegenBinding);
 							}
 						} else {
-							codeStream.invokestatic(syntheticReadAccessor);
+							codeStream.invokestatic(syntheticAccessors[READ]);
 						}
 					}
+					if (this.genericCast != null) codeStream.checkcast(this.genericCast);			
 					codeStream.generateImplicitConversion(implicitConversion);
 				} else {
 					if (!isStatic) {
 						codeStream.invokeObjectGetClass(); // perform null check
 						codeStream.pop();
 					}
-					codeStream.generateConstant(this.codegenBinding.constant, implicitConversion);
+					codeStream.generateConstant(this.codegenBinding.constant(), implicitConversion);
 				}
 			} else {
 				if (!isStatic){
@@ -207,41 +236,46 @@
 			codeStream,
 			!(isStatic = this.codegenBinding.isStatic()));
 		if (isStatic) {
-			if (syntheticReadAccessor == null) {
+			if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
 				codeStream.getstatic(this.codegenBinding);
 			} else {
-				codeStream.invokestatic(syntheticReadAccessor);
+				codeStream.invokestatic(syntheticAccessors[READ]);
 			}
 		} else {
 			codeStream.dup();
-			if (syntheticReadAccessor == null) {
+			if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
 				codeStream.getfield(this.codegenBinding);
 			} else {
-				codeStream.invokestatic(syntheticReadAccessor);
+				codeStream.invokestatic(syntheticAccessors[READ]);
 			}
 		}
 		int operationTypeID;
-		if ((operationTypeID = implicitConversion >> 4) == T_String) {
-			codeStream.generateStringAppend(currentScope, null, expression);
-		} else {
-			// promote the array reference to the suitable operation type
-			codeStream.generateImplicitConversion(implicitConversion);
-			// generate the increment value (will by itself  be promoted to the operation value)
-			if (expression == IntLiteral.One) { // prefix operation
-				codeStream.generateConstant(expression.constant, implicitConversion);
-			} 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);
+		switch(operationTypeID = (implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
+			case T_JavaLangString :
+			case T_JavaLangObject :
+			case T_undefined :
+				codeStream.generateStringConcatenationAppend(currentScope, null, expression);
+				break;
+			default :
+				// 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,
-			syntheticWriteAccessor,
+			syntheticAccessors == null ? null : syntheticAccessors[WRITE],
 			valueRequired);
+		// no need for generic cast as value got dupped
 	}
 
 	public void generatePostIncrement(
@@ -256,17 +290,17 @@
 			codeStream,
 			!(isStatic = this.codegenBinding.isStatic()));
 		if (isStatic) {
-			if (syntheticReadAccessor == null) {
+			if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
 				codeStream.getstatic(this.codegenBinding);
 			} else {
-				codeStream.invokestatic(syntheticReadAccessor);
+				codeStream.invokestatic(syntheticAccessors[READ]);
 			}
 		} else {
 			codeStream.dup();
-			if (syntheticReadAccessor == null) {
+			if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
 				codeStream.getfield(this.codegenBinding);
 			} else {
-				codeStream.invokestatic(syntheticReadAccessor);
+				codeStream.invokestatic(syntheticAccessors[READ]);
 			}
 		}
 		if (valueRequired) {
@@ -286,15 +320,21 @@
 				}
 			}
 		}
+		codeStream.generateImplicitConversion(implicitConversion);		
 		codeStream.generateConstant(
 			postIncrement.expression.constant,
 			implicitConversion);
-		codeStream.sendOperator(postIncrement.operator, this.codegenBinding.type.id);
+		codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
 		codeStream.generateImplicitConversion(
 			postIncrement.assignmentImplicitConversion);
-		fieldStore(codeStream, this.codegenBinding, syntheticWriteAccessor, false);
+		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,
@@ -318,12 +358,14 @@
 			return NotAConstant;
 		}
 		if (!binding.isFinal()) {
-			return binding.constant = NotAConstant;
+			binding.setConstant(NotAConstant);
+			return NotAConstant;
 		}
-		if (binding.constant != null) {
+		Constant fieldConstant = binding.constant();
+		if (fieldConstant != null) {
 			if (isImplicit || (reference instanceof QualifiedNameReference
 					&& binding == ((QualifiedNameReference)reference).binding)) {
-				return binding.constant;
+				return fieldConstant;
 			}
 			return NotAConstant;
 		}
@@ -333,17 +375,18 @@
 		//has already been compiled. It can only be from a class within
 		//compilation units to process. Thus the field is NOT from a BinaryTypeBinbing
 
-		SourceTypeBinding typeBinding = (SourceTypeBinding) binding.declaringClass;
-		TypeDeclaration typeDecl = typeBinding.scope.referenceContext;
-		FieldDeclaration fieldDecl = typeDecl.declarationOf(binding);
+		FieldBinding originalField = binding.original();
+		SourceTypeBinding sourceType = (SourceTypeBinding) originalField.declaringClass;
+		TypeDeclaration typeDecl = sourceType.scope.referenceContext;
+		FieldDeclaration fieldDecl = typeDecl.declarationOf(originalField);
 
-		fieldDecl.resolve(binding.isStatic() //side effect on binding 
+		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 binding.constant();
 		}
 		return NotAConstant;
 	}
@@ -361,15 +404,19 @@
 	/*
 	 * No need to emulate access to protected fields since not implicitly accessed
 	 */
-	public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+	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() != binding.declaringClass)
-				&& (binding.constant == NotAConstant)) {
-				syntheticReadAccessor =
-					((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding, true);
-				currentScope.problemReporter().needToEmulateFieldReadAccess(binding, this);
+			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;
 			}
 
@@ -379,8 +426,10 @@
 			SourceTypeBinding destinationType =
 				(SourceTypeBinding) (((QualifiedSuperReference) receiver)
 					.currentCompatibleType);
-			syntheticReadAccessor = destinationType.addSyntheticMethod(binding, true);
-			currentScope.problemReporter().needToEmulateFieldReadAccess(binding, this);
+			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()) {
@@ -393,86 +442,31 @@
 				SourceTypeBinding currentCompatibleType =
 					(SourceTypeBinding) enclosingSourceType.enclosingTypeAt(
 						(bits & DepthMASK) >> DepthSHIFT);
-				syntheticReadAccessor = currentCompatibleType.addSyntheticMethod(binding, true);
-				currentScope.problemReporter().needToEmulateFieldReadAccess(binding, this);
+				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
-		if (binding.declaringClass != this.receiverType
+		if (this.binding.declaringClass != this.receiverType
 			&& !this.receiverType.isArrayType()
-			&& binding.declaringClass != null // array.length
-			&& binding.constant == NotAConstant
+			&& this.binding.declaringClass != null // array.length
+			&& !this.binding.isConstantValue()
 			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
-				&& binding.declaringClass.id != T_Object)
+				&& this.binding.declaringClass.id != T_JavaLangObject)
 			//no change for Object fields (in case there was)
-				|| !binding.declaringClass.canBeSeenBy(currentScope))) {
+				|| !this.codegenBinding.declaringClass.canBeSeenBy(currentScope))) {
 			this.codegenBinding =
 				currentScope.enclosingSourceType().getUpdatedFieldBinding(
-					binding,
-					(ReferenceBinding) this.receiverType);
+					this.codegenBinding,
+					(ReferenceBinding) this.receiverType.erasure());
 		}
 	}
 
-	/*
-	 * No need to emulate access to protected fields since not implicitly accessed
-	 */
-	public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
-
-		if (!flowInfo.isReachable()) return;
-		if (binding.isPrivate()) {
-			if (currentScope.enclosingSourceType() != binding.declaringClass) {
-				syntheticWriteAccessor =
-					((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding, false);
-				currentScope.problemReporter().needToEmulateFieldWriteAccess(binding, this);
-				return;
-			}
-
-		} else if (receiver instanceof QualifiedSuperReference) { // qualified super
-
-			// qualified super need emulation always
-			SourceTypeBinding destinationType =
-				(SourceTypeBinding) (((QualifiedSuperReference) receiver)
-					.currentCompatibleType);
-			syntheticWriteAccessor = destinationType.addSyntheticMethod(binding, false);
-			currentScope.problemReporter().needToEmulateFieldWriteAccess(binding, this);
-			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);
-				syntheticWriteAccessor =
-					currentCompatibleType.addSyntheticMethod(binding, false);
-				currentScope.problemReporter().needToEmulateFieldWriteAccess(binding, this);
-				return;
-			}
-		}
-		// if the binding declaring class is not visible, need special action
-		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
-		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
-		if (binding.declaringClass != this.receiverType
-			&& !this.receiverType.isArrayType()
-			&& binding.declaringClass != null // array.length
-			&& binding.constant == NotAConstant
-			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
-				&& binding.declaringClass.id != T_Object)
-			//no change for Object fields (in case there was)
-				|| !binding.declaringClass.canBeSeenBy(currentScope))) {
-			this.codegenBinding =
-				currentScope.enclosingSourceType().getUpdatedFieldBinding(
-					binding,
-					(ReferenceBinding) this.receiverType);
-		}
-	}
 
 	public StringBuffer printExpression(int indent, StringBuffer output) {
 
@@ -509,7 +503,7 @@
 			scope.problemReporter().invalidField(this, this.receiverType);
 			return null;
 		}
-
+		this.receiver.computeConversion(scope, this.receiverType, this.receiverType);
 		if (isFieldUseDeprecated(binding, scope, (this.bits & IsStrictlyAssignedMASK) !=0)) {
 			scope.problemReporter().deprecatedField(binding, this);
 		}
@@ -521,9 +515,8 @@
 		if (binding.isStatic()) {
 			// static field accessed through receiver? legal but unoptimal (optional warning)
 			if (!(isImplicitThisRcv
-					|| receiver.isSuper()
 					|| (receiver instanceof NameReference 
-						&& (((NameReference) receiver).bits & BindingIds.TYPE) != 0))) {
+						&& (((NameReference) receiver).bits & Binding.TYPE) != 0))) {
 				scope.problemReporter().nonStaticAccessToStaticField(this, binding);
 			}
 			if (!isImplicitThisRcv && binding.declaringClass != receiverType) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java
index c7d53d6..0fa1908 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java
@@ -11,72 +11,105 @@
 package org.eclipse.jdt.internal.compiler.ast;
 
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
+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.TypeBinding;
+import org.eclipse.jdt.internal.compiler.util.FloatUtil;
 
 public class FloatLiteral extends NumberLiteral {
 	float value;
 	final static float Float_MIN_VALUE = Float.intBitsToFloat(1); // work-around VAJ problem 1F6IGUU
-public FloatLiteral(char[] token, int s, int e) {
-	super(token, s,e);
-}
-public void computeConstant() {
-
-	//the source is correctly formated so the exception should never occurs
-
-	Float computedValue;
-	try {
-		computedValue = Float.valueOf(String.valueOf(source));
-	} catch (NumberFormatException e) {
-		return;
-	} 
-
-	if (computedValue.doubleValue() > Float.MAX_VALUE){
-		return; //may be Infinity
+	public FloatLiteral(char[] token, int s, int e) {
+		super(token, s, e);
 	}
-	if (computedValue.floatValue() < Float_MIN_VALUE){
-		// see 1F6IGUU
-		//only a true 0 can be made of zeros
-		//1.00000000e-46f is illegal ....
-		label : for (int i = 0; i < source.length; i++) { 
-			switch (source[i]) {
-				case '.' :
-				case 'f' :
-				case 'F' :
-				case '0' :
-					break;
-				case 'e' :
-				case 'E' :
-					break label; //exposant are valid !....
-				default :
-					return; //error
+	public void computeConstant() {
+		Float computedValue;
+		try {
+			computedValue = Float.valueOf(String.valueOf(source));
+		} catch (NumberFormatException e) {
+			// hex floating point literal
+			// being rejected by 1.4 libraries where Float.valueOf(...) doesn't handle hex decimal floats
+			try {
+				float v = FloatUtil.valueOfHexFloatLiteral(source);
+				if (v == Float.POSITIVE_INFINITY) {
+					// error: the number is too large to represent
+					return;
+				}
+				if (Float.isNaN(v)) {
+					// error: the number is too small to represent
+					return;
+				}
+				value = v;
+				constant = Constant.fromValue(v);
+			} catch (NumberFormatException e1) {
+				// if the computation of the constant fails
+			}
+			return;
+		}
+
+		final float floatValue = computedValue.floatValue();
+		if (floatValue > Float.MAX_VALUE) {
+			// error: the number is too large to represent
+			return;
+		}
+		if (floatValue < Float.MIN_VALUE) {
+			// see 1F6IGUU
+			// a true 0 only has '0' and '.' in mantissa
+			// 1.0e-5000d is non-zero, but underflows to 0
+			boolean isHexaDecimal = false;
+			label : for (int i = 0; i < source.length; i++) { //it is welled formated so just test against '0' and potential . D d  
+				switch (source[i]) {
+					case '0' :
+					case '.' :
+						break;
+					case 'x' :
+					case 'X' :
+						isHexaDecimal = true;
+						break;
+					case 'e' :
+					case 'E' :
+					case 'f' :
+					case 'F' :
+					case 'd' :
+					case 'D' :
+						if (isHexaDecimal) {
+							return;
+						}
+						// starting the exponent - mantissa is all zero
+						// no exponent - mantissa is all zero
+						break label;
+					case 'p' :
+					case 'P' :
+						break label;
+					default :
+						// error: the number is too small to represent
+						return;
+				}
 			}
 		}
+		value = floatValue;
+		constant = Constant.fromValue(value);
 	}
-	constant = Constant.fromValue(value = computedValue.floatValue());
-}
-/**
- * Code generation for float literal
- *
- * @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 (valueRequired)
-		if ((implicitConversion >> 4) == T_float)
-			codeStream.generateInlinedValue(value);
-		else
+	/**
+	 * Code generation for float literal
+	 *
+	 * @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 (valueRequired) {
 			codeStream.generateConstant(constant, implicitConversion);
-	codeStream.recordPositionsFrom(pc, this.sourceStart);
-}
-public TypeBinding literalType(BlockScope scope) {
-	return FloatBinding;
-}
-public void traverse(ASTVisitor visitor, BlockScope blockScope) {
-	visitor.visit(this, blockScope);
-	visitor.endVisit(this, blockScope);
-}
+		}
+		codeStream.recordPositionsFrom(pc, this.sourceStart);
+	}
+	public TypeBinding literalType(BlockScope scope) {
+		return FloatBinding;
+	}
+	public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+		visitor.visit(this, blockScope);
+		visitor.endVisit(this, blockScope);
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
index 51c5db6..ad6c97a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
@@ -83,14 +83,15 @@
 		
 		// process the condition
 		LoopingFlowContext condLoopContext = null;
+		FlowInfo condInfo = flowInfo.copy().unconditionalInits().discardNullRelatedInitializations();
 		if (condition != null) {
 			if (!isConditionTrue) {
-				flowInfo =
+				condInfo =
 					condition.analyseCode(
 						scope,
 						(condLoopContext =
 							new LoopingFlowContext(flowContext, this, null, null, scope)),
-						flowInfo);
+						condInfo);
 			}
 		}
 
@@ -100,28 +101,28 @@
 		if (action == null 
 			|| (action.isEmptyBlock() && currentScope.environment().options.complianceLevel <= ClassFileConstants.JDK1_3)) {
 			if (condLoopContext != null)
-				condLoopContext.complainOnFinalAssignmentsInLoop(scope, flowInfo);
+				condLoopContext.complainOnDeferredChecks(scope, condInfo);
 			if (isConditionTrue) {
 				return FlowInfo.DEAD_END;
 			} else {
 				if (isConditionFalse){
 					continueLabel = null; // for(;false;p());
 				}
-				actionInfo = flowInfo.initsWhenTrue().copy();
+				actionInfo = condInfo.initsWhenTrue().copy().unconditionalInits().discardNullRelatedInitializations();
 				loopingContext =
 					new LoopingFlowContext(flowContext, this, breakLabel, continueLabel, scope);
 			}
 		} else {
 			loopingContext =
 				new LoopingFlowContext(flowContext, this, breakLabel, continueLabel, scope);
-			FlowInfo initsWhenTrue = flowInfo.initsWhenTrue();
+			FlowInfo initsWhenTrue = condInfo.initsWhenTrue();
 			condIfTrueInitStateIndex =
 				currentScope.methodScope().recordInitializationStates(initsWhenTrue);
 
 				if (isConditionFalse) {
 					actionInfo = FlowInfo.DEAD_END;
 				} else {
-					actionInfo = initsWhenTrue.copy();
+					actionInfo = initsWhenTrue.copy().unconditionalInits().discardNullRelatedInitializations();
 					if (isConditionOptimizedFalse){
 						actionInfo.setReachMode(FlowInfo.UNREACHABLE);
 					}
@@ -135,26 +136,31 @@
 				continueLabel = null;
 			} else {
 				if (condLoopContext != null)
-					condLoopContext.complainOnFinalAssignmentsInLoop(scope, flowInfo);
+					condLoopContext.complainOnDeferredChecks(scope, condInfo);
 				actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue.unconditionalInits());
-				loopingContext.complainOnFinalAssignmentsInLoop(scope, actionInfo);
+				loopingContext.complainOnDeferredChecks(scope, actionInfo);
 			}
 		}
 		// for increments
-		if ((continueLabel != null) && (increments != null)) {
-			LoopingFlowContext loopContext =
-				new LoopingFlowContext(flowContext, this, null, null, scope);
-			for (int i = 0, count = increments.length; i < count; i++) {
-				actionInfo = increments[i].analyseCode(scope, loopContext, actionInfo);
+		FlowInfo exitBranch = condInfo.initsWhenFalse();
+		exitBranch.addInitializationsFrom(flowInfo); // recover null inits from before condition analysis
+		if (continueLabel != null) {
+			if (increments != null) {
+				LoopingFlowContext loopContext =
+					new LoopingFlowContext(flowContext, this, null, null, scope);
+				for (int i = 0, count = increments.length; i < count; i++) {
+					actionInfo = increments[i].analyseCode(scope, loopContext, actionInfo);
+				}
+				loopContext.complainOnDeferredChecks(scope, actionInfo);
 			}
-			loopContext.complainOnFinalAssignmentsInLoop(scope, actionInfo);
+			exitBranch.addPotentialInitializationsFrom(actionInfo.unconditionalInits());
 		}
 
 		//end of loop
 		FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
 				loopingContext.initsOnBreak, 
 				isConditionOptimizedTrue, 
-				flowInfo.initsWhenFalse(), 
+				exitBranch, 
 				isConditionOptimizedFalse, 
 				!isConditionTrue /*for(;;){}while(true); unreachable(); */);
 		mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
@@ -221,9 +227,7 @@
 
 		// May loose some local variable initializations : affecting the local variable attributes
 		if (preCondInitStateIndex != -1) {
-			codeStream.removeNotDefinitelyAssignedVariables(
-				currentScope,
-				preCondInitStateIndex);
+			codeStream.removeNotDefinitelyAssignedVariables(currentScope, preCondInitStateIndex);
 		}
 
 		// generate the condition
@@ -290,7 +294,7 @@
 				initializations[i].resolve(scope);
 		if (condition != null) {
 			TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
-			condition.implicitWidening(type, type);
+			condition.computeConversion(scope, type, type);
 		}
 		if (increments != null)
 			for (int i = 0, length = increments.length; i < length; i++)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
new file mode 100644
index 0000000..6985b7b
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
@@ -0,0 +1,463 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.codegen.Label;
+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.lookup.ArrayBinding;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+
+public class ForeachStatement extends Statement {
+    
+	public LocalDeclaration elementVariable;
+	public int elementVariableImplicitWidening = -1; 
+	public Expression collection;
+	public Statement action;
+	
+	// set the kind of foreach
+	private int kind;
+	// possible kinds of iterating behavior
+	private static final int ARRAY = 0;
+	private static final int RAW_ITERABLE = 1;
+	private static final int GENERIC_ITERABLE = 2;
+
+	private TypeBinding collectionElementType;
+
+	// loop labels
+	private Label breakLabel;
+	private Label continueLabel;
+	
+	public BlockScope scope;
+
+	// secret variables for codegen
+	public LocalVariableBinding indexVariable;
+	public LocalVariableBinding collectionVariable;	// to store the collection expression value
+	public LocalVariableBinding maxVariable;
+	// secret variable names
+	private static final char[] SecretIndexVariableName = " index".toCharArray(); //$NON-NLS-1$
+	private static final char[] SecretCollectionVariableName = " collection".toCharArray(); //$NON-NLS-1$
+	private static final char[] SecretMaxVariableName = " max".toCharArray(); //$NON-NLS-1$
+	
+	int postCollectionInitStateIndex = -1;
+	int mergedInitStateIndex = -1;
+	
+	public ForeachStatement(
+		LocalDeclaration elementVariable,
+		Expression collection,
+		int start) {
+
+		this.elementVariable = elementVariable;
+		this.collection = collection;
+		this.sourceStart = start;
+		this.kind = -1;
+	}
+
+	public FlowInfo analyseCode(
+		BlockScope currentScope,
+		FlowContext flowContext,
+		FlowInfo flowInfo) {
+		// initialize break and continue labels
+		breakLabel = new Label();
+		continueLabel = new Label();
+
+		// process the element variable and collection
+		flowInfo = this.elementVariable.analyseCode(scope, flowContext, flowInfo);
+		FlowInfo condInfo = flowInfo.copy().unconditionalInits().discardNullRelatedInitializations();
+		condInfo = this.collection.analyseCode(scope, flowContext, condInfo);
+
+		// element variable will be assigned when iterating
+		condInfo.markAsDefinitelyAssigned(this.elementVariable.binding);
+
+		this.postCollectionInitStateIndex = currentScope.methodScope().recordInitializationStates(condInfo);
+		
+		// process the action
+		LoopingFlowContext loopingContext = new LoopingFlowContext(flowContext, this, breakLabel, continueLabel, scope);
+		FlowInfo actionInfo = condInfo.initsWhenTrue().copy();
+		FlowInfo exitBranch;
+		if (!(action == null || (action.isEmptyBlock() 
+		        	&& currentScope.environment().options.complianceLevel <= ClassFileConstants.JDK1_3))) {
+
+			if (!this.action.complainIfUnreachable(actionInfo, scope, false)) {
+				actionInfo = action.analyseCode(scope, loopingContext, actionInfo);
+			}
+
+			// code generation can be optimized when no need to continue in the loop
+			exitBranch = condInfo.initsWhenFalse();
+			exitBranch.addInitializationsFrom(flowInfo); // recover null inits from before condition analysis			
+			if (!actionInfo.isReachable() && !loopingContext.initsOnContinue.isReachable()) {
+				continueLabel = null;
+			} else {
+				actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue.unconditionalInits());
+				loopingContext.complainOnDeferredChecks(scope, actionInfo);
+				exitBranch.addPotentialInitializationsFrom(actionInfo.unconditionalInits());
+			}
+		} else {
+			exitBranch = condInfo.initsWhenFalse();
+		}
+
+		// we need the variable to iterate the collection even if the 
+		// element variable is not used
+		if (!(this.action == null
+				|| this.action.isEmptyBlock()
+				|| ((this.action.bits & IsUsefulEmptyStatementMASK) != 0))) {
+			switch(this.kind) {
+				case ARRAY :
+					this.collectionVariable.useFlag = LocalVariableBinding.USED;
+					this.indexVariable.useFlag = LocalVariableBinding.USED;
+					this.maxVariable.useFlag = LocalVariableBinding.USED;
+					break;
+				case RAW_ITERABLE :
+				case GENERIC_ITERABLE :
+					this.indexVariable.useFlag = LocalVariableBinding.USED;
+					break;
+			}
+		}
+		//end of loop
+		FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
+				loopingContext.initsOnBreak, 
+				false, 
+				exitBranch, 
+				false, 
+				true /*for(;;){}while(true); unreachable(); */);
+		mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
+		return mergedInfo;
+	}
+
+	/**
+	 * For statement code generation
+	 *
+	 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+	 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+	 */
+	public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+	    
+		if ((bits & IsReachableMASK) == 0) {
+			return;
+		}
+		int pc = codeStream.position;
+		if (this.action == null
+				|| this.action.isEmptyBlock()
+				|| ((this.action.bits & IsUsefulEmptyStatementMASK) != 0)) {
+			codeStream.exitUserScope(scope);
+			if (mergedInitStateIndex != -1) {
+				codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+				codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);				
+			}
+			codeStream.recordPositionsFrom(pc, this.sourceStart);
+			return;
+		}
+		// generate the initializations
+		switch(this.kind) {
+			case ARRAY :
+				collection.generateCode(scope, codeStream, true);
+				codeStream.store(this.collectionVariable, false);
+				codeStream.iconst_0();
+				codeStream.store(this.indexVariable, false);
+				codeStream.load(this.collectionVariable);
+				codeStream.arraylength();
+				codeStream.store(this.maxVariable, false);
+				break;
+			case RAW_ITERABLE :
+			case GENERIC_ITERABLE :
+				collection.generateCode(scope, codeStream, true);
+				// declaringClass.iterator();
+				final TypeBinding collectionTypeBinding = collection.resolvedType;
+				MethodBinding iteratorMethodBinding =
+					new MethodBinding(
+							AccPublic,
+							"iterator".toCharArray(),//$NON-NLS-1$
+							scope.getJavaUtilIterator(),
+							TypeConstants.NoParameters,
+							TypeConstants.NoExceptions,
+							(ReferenceBinding) collectionTypeBinding);
+				if (collectionTypeBinding.isInterface()) {
+					codeStream.invokeinterface(iteratorMethodBinding);
+				} else {
+					codeStream.invokevirtual(iteratorMethodBinding);
+				}
+				codeStream.store(this.indexVariable, false);
+				break;
+		}
+		
+		// label management
+		Label actionLabel = new Label(codeStream);
+		Label conditionLabel = new Label(codeStream);
+		breakLabel.initialize(codeStream);
+		if (this.continueLabel != null) {
+			this.continueLabel.initialize(codeStream);
+		}
+		// jump over the actionBlock
+		codeStream.goto_(conditionLabel);
+
+		// generate the loop action
+		actionLabel.place();
+
+		// generate the loop action
+		if (this.elementVariable.binding.resolvedPosition != -1) {
+			switch(this.kind) {
+				case ARRAY :
+					codeStream.load(this.collectionVariable);
+					codeStream.load(this.indexVariable);
+					codeStream.arrayAt(this.collectionElementType.id);
+					if (this.elementVariableImplicitWidening != -1) {
+						codeStream.generateImplicitConversion(this.elementVariableImplicitWidening);
+					}
+					codeStream.store(this.elementVariable.binding, false);
+					break;
+				case RAW_ITERABLE :
+				case GENERIC_ITERABLE :
+					codeStream.load(this.indexVariable);
+					codeStream.invokeJavaUtilIteratorNext();
+					if (this.elementVariable.binding.type.id != T_JavaLangObject) {
+						if (this.elementVariableImplicitWidening != -1) {
+							codeStream.checkcast(this.collectionElementType);
+							codeStream.generateImplicitConversion(this.elementVariableImplicitWidening);
+						} else {
+							codeStream.checkcast(this.elementVariable.binding.type);
+						}
+					}
+					codeStream.store(this.elementVariable.binding, false);
+					break;
+			}
+			codeStream.addVisibleLocalVariable(this.elementVariable.binding);
+			if (this.postCollectionInitStateIndex != -1) {
+				codeStream.addDefinitelyAssignedVariables(
+					currentScope,
+					this.postCollectionInitStateIndex);
+			}
+		}
+		this.action.generateCode(scope, codeStream);
+
+		// continuation point
+		int continuationPC = codeStream.position;
+		if (this.continueLabel != null) {
+			this.continueLabel.place();
+			// generate the increments for next iteration
+			switch(this.kind) {
+				case ARRAY :
+					codeStream.iinc(this.indexVariable.resolvedPosition, 1);
+					break;
+				case RAW_ITERABLE :
+				case GENERIC_ITERABLE :
+					break;
+			}
+		}
+		// generate the condition
+		conditionLabel.place();
+		if (this.postCollectionInitStateIndex != -1) {
+			codeStream.removeNotDefinitelyAssignedVariables(currentScope, postCollectionInitStateIndex);
+		}
+		switch(this.kind) {
+			case ARRAY :
+				codeStream.load(this.indexVariable);
+				codeStream.load(this.maxVariable);
+				codeStream.if_icmplt(actionLabel);
+				break;
+			case RAW_ITERABLE :
+			case GENERIC_ITERABLE :
+				codeStream.load(this.indexVariable);
+				codeStream.invokeJavaUtilIteratorHasNext();
+				codeStream.ifne(actionLabel);
+				break;
+		}
+		codeStream.recordPositionsFrom(continuationPC, this.elementVariable.sourceStart);
+
+		breakLabel.place();
+		codeStream.exitUserScope(scope);
+		if (mergedInitStateIndex != -1) {
+			codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+			codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);			
+		}
+		codeStream.recordPositionsFrom(pc, this.sourceStart);
+	}
+
+	public StringBuffer printStatement(int tab, StringBuffer output) {
+
+		printIndent(tab, output).append("for ("); //$NON-NLS-1$
+		this.elementVariable.print(0, output); 
+		output.append(" : ");//$NON-NLS-1$
+		this.collection.print(0, output).append(") "); //$NON-NLS-1$
+		//block
+		if (this.action == null) {
+			output.append(';');
+		} else {
+			output.append('\n');
+			this.action.printStatement(tab + 1, output); //$NON-NLS-1$
+		}
+		return output;
+	}
+
+	public void resolve(BlockScope upperScope) {
+		// use the scope that will hold the init declarations
+		scope = new BlockScope(upperScope);
+		this.elementVariable.resolve(scope); // collection expression can see itemVariable
+		TypeBinding elementType = this.elementVariable.type.resolvedType;
+		TypeBinding collectionType = this.collection.resolveType(scope);
+		this.collection.computeConversion(scope, collectionType, collectionType);
+		boolean hasError = elementType == null || collectionType == null;
+
+		if (!hasError) {
+			if (collectionType.isArrayType()) { // for(E e : E[])
+				this.kind = ARRAY;
+				this.collectionElementType = ((ArrayBinding) collectionType).elementsType();
+				if (!collectionElementType.isCompatibleWith(elementType)
+						&& !scope.isBoxingCompatibleWith(collectionElementType, elementType)) {
+					scope.problemReporter().notCompatibleTypesErrorInForeach(collection, collectionElementType, elementType);
+				}
+				// in case we need to do a conversion
+				int compileTimeTypeID = collectionElementType.id;
+				if (elementType.isBaseType()) {
+					if (!collectionElementType.isBaseType()) {
+						compileTimeTypeID = scope.environment().computeBoxingType(collectionElementType).id;
+						this.elementVariableImplicitWidening = UNBOXING;
+						if (elementType.isBaseType()) {
+							this.elementVariableImplicitWidening |= (elementType.id << 4) + compileTimeTypeID;
+							scope.problemReporter().autoboxing(collection, collectionElementType, elementType);
+						}
+					} else {
+						this.elementVariableImplicitWidening = (elementType.id << 4) + compileTimeTypeID;
+					}
+				} else {
+					if (collectionElementType.isBaseType()) {
+						int boxedID = scope.environment().computeBoxingType(collectionElementType).id;
+						this.elementVariableImplicitWidening = BOXING | (compileTimeTypeID << 4) | compileTimeTypeID; // use primitive type in implicit conversion
+						compileTimeTypeID = boxedID;
+						scope.problemReporter().autoboxing(collection, collectionElementType, elementType);
+					}
+				}
+			} else if (collectionType instanceof ReferenceBinding) {
+			    ReferenceBinding iterableType = ((ReferenceBinding)collectionType).findSuperTypeErasingTo(T_JavaLangIterable, false /*Iterable is not a class*/);
+			    if (iterableType != null) {
+				    if (iterableType.isParameterizedType()) { // for(E e : Iterable<E>)
+					    ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding)iterableType;
+						if (parameterizedType.arguments.length == 1) { // per construction can only be one
+							this.kind = GENERIC_ITERABLE;
+							this.collectionElementType = parameterizedType.arguments[0]; 
+							if (!collectionElementType.isCompatibleWith(elementType)
+									&& !scope.isBoxingCompatibleWith(collectionElementType, elementType)) {
+								scope.problemReporter().notCompatibleTypesErrorInForeach(collection, collectionElementType, elementType);
+							}
+							int compileTimeTypeID = collectionElementType.id;
+							// no conversion needed as only for reference types
+							if (elementType.isBaseType()) {
+								if (!collectionElementType.isBaseType()) {
+									compileTimeTypeID = scope.environment().computeBoxingType(collectionElementType).id;
+									this.elementVariableImplicitWidening = UNBOXING;
+									if (elementType.isBaseType()) {
+										this.elementVariableImplicitWidening |= (elementType.id << 4) + compileTimeTypeID;
+									}
+								} else {
+									this.elementVariableImplicitWidening = (elementType.id << 4) + compileTimeTypeID;
+								}
+							} else {
+								if (collectionElementType.isBaseType()) {
+									int boxedID = scope.environment().computeBoxingType(collectionElementType).id;
+									this.elementVariableImplicitWidening = BOXING | (compileTimeTypeID << 4) | compileTimeTypeID; // use primitive type in implicit conversion
+									compileTimeTypeID = boxedID;
+								}
+							}
+						}
+				    } else if (iterableType.isGenericType()) { // for (T t : Iterable<T>) - in case used inside Iterable itself
+						if (iterableType.typeVariables().length == 1) {
+							this.kind = GENERIC_ITERABLE;
+							this.collectionElementType = iterableType.typeVariables()[0]; 
+							if (!collectionElementType.isCompatibleWith(elementType)
+									&& !scope.isBoxingCompatibleWith(collectionElementType, elementType)) {
+								scope.problemReporter().notCompatibleTypesErrorInForeach(collection, collectionElementType, elementType);
+							}
+							int compileTimeTypeID = collectionElementType.id;
+							// no conversion needed as only for reference types
+							if (elementType.isBaseType()) {
+								if (!collectionElementType.isBaseType()) {
+									compileTimeTypeID = scope.environment().computeBoxingType(collectionElementType).id;
+									this.elementVariableImplicitWidening = UNBOXING;
+									if (elementType.isBaseType()) {
+										this.elementVariableImplicitWidening |= (elementType.id << 4) + compileTimeTypeID;
+									}
+								} else {
+									this.elementVariableImplicitWidening = (elementType.id << 4) + compileTimeTypeID;
+								}
+							} else {
+								if (collectionElementType.isBaseType()) {
+									int boxedID = scope.environment().computeBoxingType(collectionElementType).id;
+									this.elementVariableImplicitWidening = BOXING | (compileTimeTypeID << 4) | compileTimeTypeID; // use primitive type in implicit conversion
+									compileTimeTypeID = boxedID;
+								}
+							}
+						}
+					} else if (iterableType.isRawType()) { // for(Object o : Iterable)
+						this.kind = RAW_ITERABLE;
+						this.collectionElementType = scope.getJavaLangObject();
+						if (!collectionElementType.isCompatibleWith(elementType)
+								&& !scope.isBoxingCompatibleWith(collectionElementType, elementType)) {
+							scope.problemReporter().notCompatibleTypesErrorInForeach(collection, collectionElementType, elementType);
+						}
+						// no conversion needed as only for reference types
+					}			    
+			    }
+			}
+			switch(this.kind) {
+				case ARRAY :
+					// allocate #index secret variable (of type int)
+					this.indexVariable = new LocalVariableBinding(SecretIndexVariableName, IntBinding, AccDefault, false);
+					scope.addLocalVariable(this.indexVariable);
+					this.indexVariable.setConstant(NotAConstant); // not inlinable
+					
+					// allocate #max secret variable
+					this.maxVariable = new LocalVariableBinding(SecretMaxVariableName, IntBinding, AccDefault, false);
+					scope.addLocalVariable(this.maxVariable);
+					this.maxVariable.setConstant(NotAConstant); // not inlinable
+					// add #array secret variable (of collection type)
+					this.collectionVariable = new LocalVariableBinding(SecretCollectionVariableName, collectionType, AccDefault, false);
+					scope.addLocalVariable(this.collectionVariable);
+					this.collectionVariable.setConstant(NotAConstant); // not inlinable
+					break;
+				case RAW_ITERABLE :
+				case GENERIC_ITERABLE :
+					// allocate #index secret variable (of type Iterator)
+					this.indexVariable = new LocalVariableBinding(SecretIndexVariableName, scope.getJavaUtilIterator(), AccDefault, false);
+					scope.addLocalVariable(this.indexVariable);
+					this.indexVariable.setConstant(NotAConstant); // not inlinable
+					break;
+				default :
+					scope.problemReporter().invalidTypeForCollection(collection);
+			}
+		}
+		if (action != null) {
+			action.resolve(scope);
+		}
+	}
+	
+	public void traverse(
+		ASTVisitor visitor,
+		BlockScope blockScope) {
+
+		if (visitor.visit(this, blockScope)) {
+			this.elementVariable.traverse(visitor, scope);
+			this.collection.traverse(visitor, scope);
+			if (action != null) {
+				action.traverse(visitor, scope);
+			}
+		}
+		visitor.endVisit(this, blockScope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
index a262104..223a9ed 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
@@ -71,6 +71,11 @@
 		if (isConditionOptimizedFalse) {
 			thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE); 
 		}
+		FlowInfo elseFlowInfo = flowInfo.initsWhenFalse().copy();
+		if (isConditionOptimizedTrue) {
+			elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE); 
+		}
+		this.condition.checkNullComparison(currentScope, flowContext, flowInfo, thenFlowInfo, elseFlowInfo);
 		if (this.thenStatement != null) {
 			// Save info for code gen
 			thenInitStateIndex =
@@ -84,10 +89,6 @@
 		this.thenExit =  !thenFlowInfo.isReachable();
 
 		// process the ELSE part
-		FlowInfo elseFlowInfo = flowInfo.initsWhenFalse().copy();
-		if (isConditionOptimizedTrue) {
-			elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE); 
-		}
 		if (this.elseStatement != null) {
 		    // signal else clause unnecessarily nested, tolerate else-if code pattern
 		    if (thenFlowInfo == FlowInfo.DEAD_END 
@@ -152,9 +153,7 @@
 				true);
 			// May loose some local variable initializations : affecting the local variable attributes
 			if (thenInitStateIndex != -1) {
-				codeStream.removeNotDefinitelyAssignedVariables(
-					currentScope,
-					thenInitStateIndex);
+				codeStream.removeNotDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
 				codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
 			}
 			// generate then statement
@@ -221,7 +220,7 @@
 	public void resolve(BlockScope scope) {
 
 		TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
-		condition.implicitWidening(type, type);
+		condition.computeConversion(scope, type, type);
 		if (thenStatement != null)
 			thenStatement.resolve(scope);
 		if (elseStatement != null)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ImplicitDocTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ImplicitDocTypeReference.java
index 9dda67e..546e57c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ImplicitDocTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ImplicitDocTypeReference.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.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
 import org.eclipse.jdt.internal.compiler.lookup.Scope;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
@@ -34,7 +35,7 @@
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope)
 	 */
-	public TypeBinding getTypeBinding(Scope scope) {
+	protected TypeBinding getTypeBinding(Scope scope) {
 		this.constant = NotAConstant;
 		return this.resolvedType = scope.enclosingSourceType();
 	}
@@ -52,6 +53,12 @@
 		return true;
 	}
 	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public void traverse(ASTVisitor visitor, BlockScope classScope) {
+		// Do nothing
+	}
+	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
 	 */
 	public void traverse(ASTVisitor visitor, ClassScope classScope) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ImportReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ImportReference.java
index 4623b2d..fca4408 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ImportReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ImportReference.java
@@ -23,6 +23,7 @@
 	public int declarationSourceEnd;
 	public boolean used;
 	public int modifiers; // 1.5 addition for static imports
+	public Annotation[] annotations;
 
 	public ImportReference(
 			char[][] tokens,
@@ -37,6 +38,10 @@
 		this.sourceStart = (int) (sourcePositions[0] >>> 32);
 		this.modifiers = modifiers;
 	}
+	
+	public boolean isStatic() {
+		return (this.modifiers & AccStatic) != 0;
+	}
 
 	/**
 	 * @return char[][]
@@ -67,6 +72,11 @@
 	public void traverse(ASTVisitor visitor, CompilationUnitScope scope) {
 
 		visitor.visit(this, scope);
+		if (this.annotations != null) {
+			int annotationsLength = this.annotations.length;
+			for (int i = 0; i < annotationsLength; i++)
+				this.annotations[i].traverse(visitor, scope);
+		}
 		visitor.endVisit(this, scope);
 	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Initializer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Initializer.java
index ff53718..987149f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Initializer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Initializer.java
@@ -57,16 +57,18 @@
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 
-	public boolean isField() {
-
-		return false;
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
+	 */
+	public int getKind() {
+		return INITIALIZER;
 	}
-
+	
 	public boolean isStatic() {
 
 		return (modifiers & AccStatic) != 0;
 	}
-
+	
 	public void parseStatements(
 		Parser parser,
 		TypeDeclaration typeDeclaration,
@@ -80,7 +82,9 @@
 
 		if (modifiers != 0) {
 			printIndent(indent, output);
-			printModifiers(modifiers, output).append("{\n"); //$NON-NLS-1$
+			printModifiers(modifiers, output);
+			if (this.annotations != null) printAnnotations(this.annotations, output);
+			output.append("{\n"); //$NON-NLS-1$
 			block.printBody(indent, output);
 			printIndent(indent, output).append('}'); 
 			return output;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
index feacdaf..5a47db8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
@@ -10,7 +10,6 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
@@ -38,139 +37,13 @@
 		FlowContext flowContext,
 		FlowInfo flowInfo) {
 
-		return expression
+		flowInfo = expression
 			.analyseCode(currentScope, flowContext, flowInfo)
 			.unconditionalInits();
+		expression.checkNullStatus(currentScope, flowContext, flowInfo, FlowInfo.NON_NULL);
+		return flowInfo;
 	}
-	/**
-	 * Returns false if the instanceof unnecessary
-	 */
-	public final boolean checkCastTypesCompatibility(
-		BlockScope scope,
-		TypeBinding castType,
-		TypeBinding expressionType) {
-	
-		//A more complete version of this method is provided on
-		//CastExpression (it deals with constant and need runtime checkcast)
 
-		if (castType == expressionType) return false;
-		
-		//by grammatical construction, the base type check is not necessary
-
-		if (castType == null || expressionType == null) return true;
-	
-		//-----------cast to something which is NOT a base type--------------------------	
-		if (expressionType == NullBinding) {
-			//	if (castType.isArrayType()){ // 26903 - need checkcast when casting null to array type
-			//		needRuntimeCheckcast = true;
-			//	}
-			return false; //null is compatible with every thing
-		}
-		if (expressionType.isBaseType()) {
-			scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
-			return true;
-		}
-	
-		if (expressionType.isArrayType()) {
-			if (castType == expressionType) return false; // identity conversion
-	
-			if (castType.isArrayType()) {
-				//------- (castType.isArray) expressionType.isArray -----------
-				TypeBinding exprElementType = ((ArrayBinding) expressionType).elementsType(scope);
-				if (exprElementType.isBaseType()) {
-					// <---stop the recursion------- 
-					if (((ArrayBinding) castType).elementsType(scope) != exprElementType)
-						scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
-					return true;
-				}
-				// recursively on the elements...
-				return checkCastTypesCompatibility(
-					scope,
-					((ArrayBinding) castType).elementsType(scope),
-					exprElementType);
-			} else if (
-				castType.isClass()) {
-				//------(castType.isClass) expressionType.isArray ---------------	
-				if (castType.id == T_Object) {
-					return false;
-				}
-			} else { //------- (castType.isInterface) expressionType.isArray -----------
-				if (castType.id == T_JavaLangCloneable || castType.id == T_JavaIoSerializable) {
-					return true;
-				}
-			}
-			scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
-			return true;
-		}
-	
-		if (expressionType.isClass()) {
-			if (castType.isArrayType()) {
-				// ---- (castType.isArray) expressionType.isClass -------
-				if (expressionType.id == T_Object) { // potential runtime error
-					return true;
-				}
-			} else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isClass ------
-				if (expressionType.isCompatibleWith(castType)){ // no runtime error
-					return false;
-				}
-				if (castType.isCompatibleWith(expressionType)) {
-					// potential runtime  error
-					return true;
-				}
-			} else { // ----- (castType.isInterface) expressionType.isClass -------  
-				if (expressionType.isCompatibleWith(castType)) 
-					return false;
-				if (!((ReferenceBinding) expressionType).isFinal()) {
-				    // a subclass may implement the interface ==> no check at compile time
-					return true;
-				}
-				// no subclass for expressionType, thus compile-time check is valid
-			}
-			scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
-			return true;
-		}
-	
-		//	if (expressionType.isInterface()) { cannot be anything else
-		if (castType.isArrayType()) {
-			// ----- (castType.isArray) expressionType.isInterface ------
-			if (!(expressionType.id == T_JavaLangCloneable
-					|| expressionType.id == T_JavaIoSerializable)) {// potential runtime error
-				scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
-			}
-			return true;
-		} else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isInterface --------
-			if (castType.id == T_Object) { // no runtime error
-				return false;
-			}
-			if (((ReferenceBinding) castType).isFinal()) {
-				// no subclass for castType, thus compile-time check is valid
-				if (!castType.isCompatibleWith(expressionType)) {
-					// potential runtime error
-					scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
-					return true;
-				}
-			}
-		} else { // ----- (castType.isInterface) expressionType.isInterface -------
-			if (expressionType.isCompatibleWith(castType)) { 
-				return false;
-			}
-			if (!castType.isCompatibleWith(expressionType)) {
-				MethodBinding[] castTypeMethods = ((ReferenceBinding) castType).methods();
-				MethodBinding[] expressionTypeMethods =
-					((ReferenceBinding) expressionType).methods();
-				int exprMethodsLength = expressionTypeMethods.length;
-				for (int i = 0, castMethodsLength = castTypeMethods.length; i < castMethodsLength; i++)
-					for (int j = 0; j < exprMethodsLength; j++) {
-						if ((castTypeMethods[i].returnType != expressionTypeMethods[j].returnType)
-								&& CharOperation.equals(castTypeMethods[i].selector, expressionTypeMethods[j].selector)
-								&& castTypeMethods[i].areParametersEqual(expressionTypeMethods[j])) {
-							scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
-						}
-					}
-			}
-		}
-		return true;
-	}
 	/**
 	 * Code generation for instanceOfExpression
 	 *
@@ -186,8 +59,11 @@
 		int pc = codeStream.position;
 		expression.generateCode(currentScope, codeStream, true);
 		codeStream.instance_of(type.resolvedType);
-		if (!valueRequired)
+		if (valueRequired) {
+			codeStream.generateImplicitConversion(implicitConversion);
+		} else {
 			codeStream.pop();
+		}
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 
@@ -196,22 +72,33 @@
 		expression.printExpression(indent, output).append(" instanceof "); //$NON-NLS-1$
 		return type.print(0, output);
 	}
-	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#reportIllegalCast(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
+	 */
+	public void reportIllegalCast(Scope scope, TypeBinding castType, TypeBinding expressionType) {
+		scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
+	}
 	public TypeBinding resolveType(BlockScope scope) {
 
 		constant = NotAConstant;
 		TypeBinding expressionType = expression.resolveType(scope);
-		TypeBinding checkType = type.resolveType(scope);
-		if (expressionType == null || checkType == null)
+		TypeBinding checkedType = type.resolveType(scope, true /* check bounds*/);
+		if (expressionType == null || checkedType == null)
 			return null;
 
-		boolean necessary = checkCastTypesCompatibility(scope, checkType, expressionType);
-		if (!necessary) {
-			scope.problemReporter().unnecessaryInstanceof(this, checkType);
+		if (checkedType.isTypeVariable() || checkedType.isBoundParameterizedType() || checkedType.isGenericType()) {
+			scope.problemReporter().illegalInstanceOfGenericType(checkedType, this);
+		} else {
+			checkCastTypesCompatibility(scope, checkedType, expressionType, null);
 		}
 		return this.resolvedType = BooleanBinding;
 	}
-
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#tagAsUnnecessaryCast(Scope,TypeBinding)
+	 */
+	public void tagAsUnnecessaryCast(Scope scope, TypeBinding castType) {
+		scope.problemReporter().unnecessaryInstanceof(this, castType);
+	}
 	public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 		if (visitor.visit(this, scope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
index 46a2172..0e7821e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
@@ -56,7 +56,7 @@
 		if (length == 1) {	constant = Constant.fromValue(0); return ;}
 		final int shift,radix;
 		int j ;
-		if ( (source[1] == 'x') | (source[1] == 'X') )
+		if ( (source[1] == 'x') || (source[1] == 'X') )
 		{	shift = 4 ; j = 2; radix = 16;}
 		else
 		{	shift = 3 ; j = 1; radix = 8;}
@@ -94,11 +94,9 @@
  */ 
 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
 	int pc = codeStream.position;
-	if (valueRequired)
-		if ((implicitConversion >> 4) == T_int)
-			codeStream.generateInlinedValue(value);
-		else
-			codeStream.generateConstant(constant, implicitConversion);
+	if (valueRequired) {
+		codeStream.generateConstant(constant, implicitConversion);
+	}
 	codeStream.recordPositionsFrom(pc, this.sourceStart);
 }
 public TypeBinding literalType(BlockScope scope) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
index f683964..03cdba4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
@@ -11,17 +11,20 @@
 package org.eclipse.jdt.internal.compiler.ast;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser;
 
 /**
  * Node representing a structured Javadoc comment
  */
 public class Javadoc extends ASTNode {
 
-	public JavadocSingleNameReference[] parameters; // @param
-	public TypeReference[] thrownExceptions; // @throws, @exception
+	public JavadocSingleNameReference[] paramReferences; // @param
+	public JavadocSingleTypeReference[] paramTypeParameters; // @param
+	public TypeReference[] exceptionReferences; // @throws, @exception
 	public JavadocReturnStatement returnStatement; // @return
-	public Expression[] references; // @see
+	public Expression[] seeReferences; // @see
 	public boolean inherited = false;
 	// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51600
 	// Store param references for tag with invalid syntax
@@ -37,25 +40,32 @@
 	 */
 	public StringBuffer print(int indent, StringBuffer output) {
 		printIndent(indent, output).append("/**\n"); //$NON-NLS-1$
-		if (this.parameters != null) {
-			for (int i = 0, length = this.parameters.length; i < length; i++) {
+		if (this.paramReferences != null) {
+			for (int i = 0, length = this.paramReferences.length; i < length; i++) {
 				printIndent(indent + 1, output).append(" * @param "); //$NON-NLS-1$		
-				this.parameters[i].print(indent, output).append('\n');
+				this.paramReferences[i].print(indent, output).append('\n');
+			}
+		}
+		if (this.paramTypeParameters != null) {
+			for (int i = 0, length = this.paramTypeParameters.length; i < length; i++) {
+				printIndent(indent + 1, output).append(" * @param <"); //$NON-NLS-1$		
+				this.paramTypeParameters[i].print(indent, output).append(">\n"); //$NON-NLS-1$
 			}
 		}
 		if (this.returnStatement != null) {
-			printIndent(indent + 1, output).append(" * @return\n"); //$NON-NLS-1$		
+			printIndent(indent + 1, output).append(" * @"); //$NON-NLS-1$
+			this.returnStatement.print(indent, output).append('\n');
 		}
-		if (this.thrownExceptions != null) {
-			for (int i = 0, length = this.thrownExceptions.length; i < length; i++) {
+		if (this.exceptionReferences != null) {
+			for (int i = 0, length = this.exceptionReferences.length; i < length; i++) {
 				printIndent(indent + 1, output).append(" * @throws "); //$NON-NLS-1$		
-				this.thrownExceptions[i].print(indent, output).append('\n');
+				this.exceptionReferences[i].print(indent, output).append('\n');
 			}
 		}
-		if (this.references != null) {
-			for (int i = 0, length = this.references.length; i < length; i++) {
+		if (this.seeReferences != null) {
+			for (int i = 0, length = this.seeReferences.length; i < length; i++) {
 				printIndent(indent + 1, output).append(" * @see"); //$NON-NLS-1$		
-				this.references[i].print(indent, output).append('\n');
+				this.seeReferences[i].print(indent, output).append('\n');
 			}
 		}
 		printIndent(indent, output).append(" */\n"); //$NON-NLS-1$
@@ -66,14 +76,14 @@
 	 * Resolve type javadoc while a class scope
 	 */
 	public void resolve(ClassScope classScope) {
-		
 
 		// @param tags
-		int paramTagsSize = this.parameters == null ? 0 : this.parameters.length;
+		int paramTagsSize = this.paramReferences == null ? 0 : this.paramReferences.length;
 		for (int i = 0; i < paramTagsSize; i++) {
-			JavadocSingleNameReference param = this.parameters[i];
+			JavadocSingleNameReference param = this.paramReferences[i];
 			classScope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd);
 		}
+		resolveTypeParameterTags(classScope, true);
 
 		// @return tags
 		if (this.returnStatement != null) {
@@ -81,9 +91,9 @@
 		}
 
 		// @throws/@exception tags
-		int throwsTagsLength = this.thrownExceptions == null ? 0 : this.thrownExceptions.length;
+		int throwsTagsLength = this.exceptionReferences == null ? 0 : this.exceptionReferences.length;
 		for (int i = 0; i < throwsTagsLength; i++) {
-			TypeReference typeRef = this.thrownExceptions[i];
+			TypeReference typeRef = this.exceptionReferences[i];
 			int start, end;
 			if (typeRef instanceof JavadocSingleTypeReference) {
 				JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) typeRef;
@@ -101,27 +111,9 @@
 		}
 
 		// @see tags
-		int seeTagsLength = this.references == null ? 0 : this.references.length;
+		int seeTagsLength = this.seeReferences == null ? 0 : this.seeReferences.length;
 		for (int i = 0; i < seeTagsLength; i++) {
-			
-			// Resolve reference
-			this.references[i].resolveType(classScope);
-
-			// Some unbound field reference might be changed to message send
-			// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51911
-			if (this.references[i] instanceof JavadocFieldReference) {
-				JavadocFieldReference fieldRef = (JavadocFieldReference) this.references[i];
-				if (fieldRef.receiverType != null && fieldRef.binding == null) { // binding was reset in case of valid method reference
-					// TODO (frederic) post 3.0 - avoid new instanciation of Compiler AST node
-					JavadocMessageSend msgSend = new JavadocMessageSend(fieldRef.token, fieldRef.nameSourcePosition);
-					msgSend.receiver = fieldRef.receiver;
-					msgSend.receiverType = fieldRef.receiverType;
-					msgSend.qualifyingType = fieldRef.receiverType;
-					msgSend.superAccess = classScope.enclosingSourceType().isCompatibleWith(msgSend.receiverType);
-					msgSend.binding = classScope.findMethod((ReferenceBinding)msgSend.receiverType, msgSend.selector, new TypeBinding[0], msgSend);
-					this.references[i] = msgSend;
-				}
-			}
+			resolveReference(this.seeReferences[i], classScope);
 		}
 	}
 	
@@ -132,40 +124,24 @@
 		
 		// get method declaration
 		AbstractMethodDeclaration methDecl = methScope.referenceMethod();
-		boolean overriding = methDecl == null ? false : (methDecl.binding.modifiers & (AccImplementing+AccOverriding)) != 0;
+		boolean overriding = methDecl == null ? false : (methDecl.binding.modifiers & (AccImplementing | AccOverriding)) != 0;
 
 		// @see tags
-		int seeTagsLength = this.references == null ? 0 : this.references.length;
+		int seeTagsLength = this.seeReferences == null ? 0 : this.seeReferences.length;
 		boolean superRef = false;
 		for (int i = 0; i < seeTagsLength; i++) {
 			
 			// Resolve reference
-			this.references[i].resolveType(methScope);
+			resolveReference(this.seeReferences[i], methScope);
 			
-			// Some unbound field reference might be changed to message send
-			// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51911
-			if (this.references[i] instanceof JavadocFieldReference) {
-				JavadocFieldReference fieldRef = (JavadocFieldReference) this.references[i];
-				if (fieldRef.receiverType != null && fieldRef.binding == null) { // binding was reset in case of valid method reference
-					// TODO (frederic) post 3.0 - avoid new instanciation of Compiler AST node
-					JavadocMessageSend msgSend = new JavadocMessageSend(fieldRef.token, fieldRef.nameSourcePosition);
-					msgSend.receiver = fieldRef.receiver;
-					msgSend.receiverType = fieldRef.receiverType;
-					msgSend.qualifyingType = fieldRef.receiverType;
-					msgSend.superAccess = methScope.enclosingSourceType().isCompatibleWith(msgSend.receiverType);
-					msgSend.binding = methScope.findMethod((ReferenceBinding)msgSend.receiverType, msgSend.selector, new TypeBinding[0], msgSend);
-					this.references[i] = msgSend;
-				}
-			}
-
 			// see whether we can have a super reference
 			try {
 				if (methDecl != null && (methDecl.isConstructor() || overriding) && !superRef) {
-					if (this.references[i] instanceof JavadocMessageSend) {
-						JavadocMessageSend messageSend = (JavadocMessageSend) this.references[i];
+					if (this.seeReferences[i] instanceof JavadocMessageSend) {
+						JavadocMessageSend messageSend = (JavadocMessageSend) this.seeReferences[i];
 						// if binding is valid then look if we have a reference to an overriden method/constructor
 						if (messageSend.binding != null && messageSend.binding.isValidBinding()) {
-							if (methDecl.binding.declaringClass.isCompatibleWith(messageSend.receiverType) &&
+							if (methDecl.binding.declaringClass.isCompatibleWith(messageSend.actualReceiverType) &&
 								CharOperation.equals(messageSend.selector, methDecl.selector) &&
 								(messageSend.binding.returnType == methDecl.binding.returnType)) {
 								if (messageSend.arguments == null && methDecl.arguments == null) {
@@ -177,8 +153,8 @@
 							}
 						}
 					}
-					else if (this.references[i] instanceof JavadocAllocationExpression) {
-						JavadocAllocationExpression allocationExpr = (JavadocAllocationExpression) this.references[i];
+					else if (this.seeReferences[i] instanceof JavadocAllocationExpression) {
+						JavadocAllocationExpression allocationExpr = (JavadocAllocationExpression) this.seeReferences[i];
 						// if binding is valid then look if we have a reference to an overriden method/constructor
 						if (allocationExpr.binding != null && allocationExpr.binding.isValidBinding()) {
 							if (methDecl.binding.declaringClass.isCompatibleWith(allocationExpr.resolvedType)) {
@@ -203,11 +179,12 @@
 
 		// @param tags
 		resolveParamTags(methScope, reportMissing);
+		resolveTypeParameterTags(methScope, reportMissing);
 
 		// @return tags
 		if (this.returnStatement == null) {
 			if (reportMissing && methDecl != null) {
-				if (!methDecl.isConstructor() && !methDecl.isClinit()) {
+				if (methDecl.isMethod()) {
 					MethodDeclaration meth = (MethodDeclaration) methDecl;
 					if (meth.binding.returnType != VoidBinding) {
 						// method with return should have @return tag
@@ -229,17 +206,78 @@
 		}
 	}
 	
+	private void resolveReference(Expression reference, Scope scope) {
+
+		// Perform resolve
+		switch (scope.kind) {
+			case Scope.METHOD_SCOPE:
+				reference.resolveType((MethodScope)scope);
+			break;
+			case Scope.CLASS_SCOPE:
+				reference.resolveType((ClassScope)scope);
+			break;
+		}
+
+		// Verify field references
+		boolean verifyValues = scope.environment().options.sourceLevel >= ClassFileConstants.JDK1_5;
+		if (reference instanceof JavadocFieldReference) {
+			JavadocFieldReference fieldRef = (JavadocFieldReference) reference;
+			int modifiers = fieldRef.binding==null ? -1 : fieldRef.binding.modifiers;
+			
+			// Verify if this is a method reference
+			// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51911
+			if (fieldRef.methodBinding != null) {
+				// cannot refer to method for @value tag
+				if (fieldRef.tagValue == AbstractCommentParser.TAG_VALUE_VALUE) {
+					scope.problemReporter().javadocInvalidValueReference(fieldRef.sourceStart, fieldRef.sourceEnd, modifiers);
+				}
+				else if (fieldRef.receiverType != null) {
+					fieldRef.superAccess = scope.enclosingSourceType().isCompatibleWith(fieldRef.receiverType);
+					fieldRef.methodBinding = scope.findMethod((ReferenceBinding)fieldRef.receiverType, fieldRef.token, new TypeBinding[0], fieldRef);
+				}
+			}
+
+			// Verify whether field ref should be static or not (for @value tags)
+			else if (verifyValues && fieldRef.binding != null && fieldRef.binding.isValidBinding()) {
+				if (fieldRef.tagValue == AbstractCommentParser.TAG_VALUE_VALUE && !fieldRef.binding.isStatic()) {
+					scope.problemReporter().javadocInvalidValueReference(fieldRef.sourceStart, fieldRef.sourceEnd, modifiers);
+				}
+			}
+		}
+
+		// If not 1.5 level, verification is finished
+		if (!verifyValues)  return;
+
+		// Verify that message reference are not used for @value tags
+		else if (reference instanceof JavadocMessageSend) {
+			JavadocMessageSend msgSend = (JavadocMessageSend) reference;
+			int modifiers = msgSend.binding==null ? -1 : msgSend.binding.modifiers;
+			if (msgSend.tagValue == AbstractCommentParser.TAG_VALUE_VALUE) { // cannot refer to method for @value tag
+				scope.problemReporter().javadocInvalidValueReference(msgSend.sourceStart, msgSend.sourceEnd, modifiers);
+			}
+		}
+
+		// Verify that constructorreference are not used for @value tags
+		else if (reference instanceof JavadocAllocationExpression) {
+			JavadocAllocationExpression alloc = (JavadocAllocationExpression) reference;
+			int modifiers = alloc.binding==null ? -1 : alloc.binding.modifiers;
+			if (alloc.tagValue == AbstractCommentParser.TAG_VALUE_VALUE) { // cannot refer to method for @value tag
+				scope.problemReporter().javadocInvalidValueReference(alloc.sourceStart, alloc.sourceEnd, modifiers);
+			}
+		}
+	}
+
 	/*
 	 * Resolve @param tags while method scope
 	 */
 	private void resolveParamTags(MethodScope methScope, boolean reportMissing) {
 		AbstractMethodDeclaration md = methScope.referenceMethod();
-		int paramTagsSize = this.parameters == null ? 0 : this.parameters.length;
+		int paramTagsSize = this.paramReferences == null ? 0 : this.paramReferences.length;
 
 		// If no referenced method (field initializer for example) then report a problem for each param tag
 		if (md == null) {
 			for (int i = 0; i < paramTagsSize; i++) {
-				JavadocSingleNameReference param = this.parameters[i];
+				JavadocSingleNameReference param = this.paramReferences[i];
 				methScope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd);
 			}
 			return;
@@ -251,7 +289,7 @@
 			if (reportMissing) {
 				for (int i = 0; i < argumentsSize; i++) {
 					Argument arg = md.arguments[i];
-					methScope.problemReporter().javadocMissingParamTag(arg, md.binding.modifiers);
+					methScope.problemReporter().javadocMissingParamTag(arg.name, arg.sourceStart, arg.sourceEnd, md.binding.modifiers);
 				}
 			}
 		} else {
@@ -260,14 +298,14 @@
 
 			// Scan all @param tags
 			for (int i = 0; i < paramTagsSize; i++) {
-				JavadocSingleNameReference param = this.parameters[i];
+				JavadocSingleNameReference param = this.paramReferences[i];
 				param.resolve(methScope);
 				if (param.binding != null && param.binding.isValidBinding()) {
 					// Verify duplicated tags
 					boolean found = false;
 					for (int j = 0; j < maxBindings && !found; j++) {
 						if (bindings[j] == param.binding) {
-							methScope.problemReporter().javadocDuplicatedParamTag(param, md.binding.modifiers);
+							methScope.problemReporter().javadocDuplicatedParamTag(param.token, param.sourceStart, param.sourceEnd, md.binding.modifiers);
 							found = true;
 						}
 					}
@@ -289,7 +327,103 @@
 						}
 					}
 					if (!found) {
-						methScope.problemReporter().javadocMissingParamTag(arg, md.binding.modifiers);
+						methScope.problemReporter().javadocMissingParamTag(arg.name, arg.sourceStart, arg.sourceEnd, md.binding.modifiers);
+					}
+				}
+			}
+		}
+	}
+
+	/*
+	 * Resolve @param tags for type parameters
+	 */
+	private void resolveTypeParameterTags(Scope scope, boolean reportMissing) {
+		int paramTypeParamLength = this.paramTypeParameters == null ? 0 : this.paramTypeParameters.length;
+
+		// Get declaration infos
+		TypeDeclaration typeDeclaration = null;
+		AbstractMethodDeclaration methodDeclaration = null;
+		TypeVariableBinding[] typeVariables = null;
+		int modifiers = -1;
+		switch (scope.kind) {
+			case Scope.METHOD_SCOPE:
+				methodDeclaration = ((MethodScope)scope).referenceMethod();
+				// If no referenced method (field initializer for example) then report a problem for each param tag
+				if (methodDeclaration == null) {
+					for (int i = 0; i < paramTypeParamLength; i++) {
+						JavadocSingleNameReference param = this.paramReferences[i];
+						scope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd);
+					}
+					return;
+				}
+				typeVariables = methodDeclaration.binding.typeVariables;
+				modifiers = methodDeclaration.binding.modifiers;
+				break;
+			case Scope.CLASS_SCOPE:
+				typeDeclaration = ((ClassScope) scope).referenceContext;
+				typeVariables = typeDeclaration.binding.typeVariables;
+				modifiers = typeDeclaration.binding.modifiers;
+				break;
+		}
+
+		// If no type variables then report a problem for each param type parameter tag
+		if (typeVariables == null || typeVariables.length == 0) {
+			for (int i = 0; i < paramTypeParamLength; i++) {
+				JavadocSingleTypeReference param = this.paramTypeParameters[i];
+				scope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd);
+			}
+			return;
+		}
+		
+		// If no param tags then report a problem for each declaration type parameter
+		TypeParameter[] parameters = typeDeclaration==null ? methodDeclaration.typeParameters() : typeDeclaration.typeParameters;
+		int typeParametersLength = parameters == null ? 0 : parameters.length;
+		if (paramTypeParamLength == 0) {
+			if (reportMissing) {
+				for (int i = 0, l=parameters.length; i<l; i++) {
+					scope.problemReporter().javadocMissingParamTag(parameters[i].name, parameters[i].sourceStart, parameters[i].sourceEnd, modifiers);
+				}
+			}
+		// Otherwise verify that all param tags match type parameters
+		} else if (typeVariables.length == typeParametersLength) {
+			TypeVariableBinding[] bindings = new TypeVariableBinding[paramTypeParamLength];
+			int maxBindings = 0;
+
+			// Scan all @param tags
+			for (int i = 0; i < paramTypeParamLength; i++) {
+				JavadocSingleTypeReference param = this.paramTypeParameters[i];
+				TypeBinding paramBindind = param.internalResolveType(scope);
+				if (paramBindind != null && paramBindind.isValidBinding()) {
+					if (paramBindind.isTypeVariable()) {
+						// Verify duplicated tags
+						boolean duplicate = false;
+						for (int j = 0; j < maxBindings && !duplicate; j++) {
+							if (bindings[j] == param.resolvedType) {
+								scope.problemReporter().javadocDuplicatedParamTag(param.token, param.sourceStart, param.sourceEnd, modifiers);
+								duplicate = true;
+							}
+						}
+						if (!duplicate) {
+							bindings[maxBindings++] = (TypeVariableBinding) param.resolvedType;
+						}
+					} else {
+						scope.problemReporter().javadocUndeclaredParamTagName(param.token, param.sourceStart, param.sourceEnd, modifiers);
+					}
+				}
+			}
+
+			// Look for undocumented type parameters
+			if (reportMissing) {
+				for (int i = 0; i < typeParametersLength; i++) {
+					TypeParameter parameter = parameters[i];
+					boolean found = false;
+					for (int j = 0; j < maxBindings && !found; j++) {
+						if (parameter.binding == bindings[j]) {
+							found = true;
+						}
+					}
+					if (!found) {
+						scope.problemReporter().javadocMissingParamTag(parameter.name, parameter.sourceStart, parameter.sourceEnd, modifiers);
 					}
 				}
 			}
@@ -301,12 +435,12 @@
 	 */
 	private void resolveThrowsTags(MethodScope methScope, boolean reportMissing) {
 		AbstractMethodDeclaration md = methScope.referenceMethod();
-		int throwsTagsLength = this.thrownExceptions == null ? 0 : this.thrownExceptions.length;
+		int throwsTagsLength = this.exceptionReferences == null ? 0 : this.exceptionReferences.length;
 
 		// If no referenced method (field initializer for example) then report a problem for each throws tag
 		if (md == null) {
 			for (int i = 0; i < throwsTagsLength; i++) {
-				TypeReference typeRef = this.thrownExceptions[i];
+				TypeReference typeRef = this.exceptionReferences[i];
 				int start = typeRef.sourceStart;
 				int end = typeRef.sourceEnd;
 				if (typeRef instanceof JavadocQualifiedTypeReference) {
@@ -343,7 +477,7 @@
 
 			// Scan all @throws tags
 			for (int i = 0; i < throwsTagsLength; i++) {
-				TypeReference typeRef = this.thrownExceptions[i];
+				TypeReference typeRef = this.exceptionReferences[i];
 				typeRef.resolve(methScope);
 				TypeBinding typeBinding = typeRef.resolvedType;
 
@@ -404,10 +538,12 @@
 	 * Search node with a given staring position in javadoc objects arrays.
 	 */
 	public ASTNode getNodeStartingAt(int start) {
+		int length = 0;
 		// parameters array
-		if (this.parameters != null) {
-			for (int i=0; i<this.parameters.length; i++) {
-				JavadocSingleNameReference param = this.parameters[i];
+		if (this.paramReferences != null) {
+			length = this.paramReferences.length;
+			for (int i=0; i<length; i++) {
+				JavadocSingleNameReference param = this.paramReferences[i];
 				if (param.sourceStart==start) {
 					return param;
 				}
@@ -415,34 +551,47 @@
 		}
 		// array of invalid syntax tags parameters
 		if (this.invalidParameters != null) {
-			for (int i=0; i<this.invalidParameters.length; i++) {
+			length = this.invalidParameters.length;
+			for (int i=0; i<length; i++) {
 				JavadocSingleNameReference param = this.invalidParameters[i];
 				if (param.sourceStart==start) {
 					return param;
 				}
 			}
 		}
+		// type parameters array
+		if (this.paramTypeParameters != null) {
+			length = this.paramTypeParameters.length;
+			for (int i=0; i<length; i++) {
+				JavadocSingleTypeReference param = this.paramTypeParameters[i];
+				if (param.sourceStart==start) {
+					return param;
+				}
+			}
+		}
 		// thrown exception array
-		if (this.thrownExceptions != null) {
-			for (int i=0; i<this.thrownExceptions.length; i++) {
-				TypeReference typeRef = this.thrownExceptions[i];
+		if (this.exceptionReferences != null) {
+			length = this.exceptionReferences.length;
+			for (int i=0; i<length; i++) {
+				TypeReference typeRef = this.exceptionReferences[i];
 				if (typeRef.sourceStart==start) {
 					return typeRef;
 				}
 			}
 		}
 		// references array
-		if (this.references != null) {
-			for (int i=0; i<this.references.length; i++) {
-				org.eclipse.jdt.internal.compiler.ast.Expression expression = this.references[i];
+		if (this.seeReferences != null) {
+			length = this.seeReferences.length;
+			for (int i=0; i<length; i++) {
+				org.eclipse.jdt.internal.compiler.ast.Expression expression = this.seeReferences[i];
 				if (expression.sourceStart==start) {
 					return expression;
 				} else if (expression instanceof JavadocAllocationExpression) {
-					JavadocAllocationExpression allocationExpr = (JavadocAllocationExpression) this.references[i];
+					JavadocAllocationExpression allocationExpr = (JavadocAllocationExpression) this.seeReferences[i];
 					// if binding is valid then look at arguments
 					if (allocationExpr.binding != null && allocationExpr.binding.isValidBinding()) {
 						if (allocationExpr.arguments != null) {
-							for (int j=0; j<allocationExpr.arguments.length; j++) {
+							for (int j=0, l=allocationExpr.arguments.length; j<l; j++) {
 								if (allocationExpr.arguments[j].sourceStart == start) {
 									return allocationExpr.arguments[j];
 								}
@@ -450,11 +599,11 @@
 						}
 					}
 				} else if (expression instanceof JavadocMessageSend) {
-					JavadocMessageSend messageSend = (JavadocMessageSend) this.references[i];
+					JavadocMessageSend messageSend = (JavadocMessageSend) this.seeReferences[i];
 					// if binding is valid then look at arguments
 					if (messageSend.binding != null && messageSend.binding.isValidBinding()) {
 						if (messageSend.arguments != null) {
-							for (int j=0; j<messageSend.arguments.length; j++) {
+							for (int j=0, l=messageSend.arguments.length; j<l; j++) {
 								if (messageSend.arguments[j].sourceStart == start) {
 									return messageSend.arguments[j];
 								}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java
index 6c7ff1f..032ebd2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java
@@ -17,6 +17,7 @@
 public class JavadocAllocationExpression extends AllocationExpression {
 
 	public int tagSourceStart, tagSourceEnd;
+	public int tagValue;
 	public boolean superAccess = false;
 	
 	public JavadocAllocationExpression(long pos) {
@@ -37,7 +38,7 @@
 		} else if (scope.kind == Scope.CLASS_SCOPE) {
 			this.resolvedType = this.type.resolveType((ClassScope)scope);
 		} else {
-			this.resolvedType = this.type.resolveType((BlockScope)scope);
+			this.resolvedType = this.type.resolveType((BlockScope)scope, true /* check bounds*/);
 		}
 
 		// buffering the arguments' types
@@ -85,7 +86,7 @@
 		if (isMethodUseDeprecated(this.binding, scope)) {
 			scope.problemReporter().javadocDeprecatedMethod(this.binding, this, scope.getDeclarationModifiers());
 		}
-
+		// TODO (frederic) add support for unsafe type operation warning
 		return allocationType;
 	}
 	
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.java
index 57be26e..d55372a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.java
@@ -35,27 +35,23 @@
 	 */
 	private TypeBinding internalResolveType(Scope scope) {
 		this.constant = NotAConstant;
-		if (this.resolvedType != null) { // is a shared type reference which was already resolved
-			if (!this.resolvedType.isValidBinding()) {
-				return null; // already reported error
-			}
-		}
-		else {
-			if (this.argument != null) {
-				TypeReference typeRef = this.argument.type;
-				if (typeRef != null) {
-					this.resolvedType = typeRef.getTypeBinding(scope);
-					typeRef.resolvedType = this.resolvedType;
-					if (!this.resolvedType.isValidBinding()) {
-						scope.problemReporter().javadocInvalidType(typeRef, this.resolvedType, scope.getDeclarationModifiers());
-						return null;
-					}
-					if (isTypeUseDeprecated(this.resolvedType, scope)) {
-						scope.problemReporter().javadocDeprecatedType(this.resolvedType, typeRef, scope.getDeclarationModifiers());
-						return null;
-					}
-					return this.resolvedType;
+		if (this.resolvedType != null) // is a shared type reference which was already resolved
+			return this.resolvedType.isValidBinding() ? this.resolvedType : null; // already reported error
+
+		if (this.argument != null) {
+			TypeReference typeRef = this.argument.type;
+			if (typeRef != null) {
+				this.resolvedType = typeRef.getTypeBinding(scope);
+				typeRef.resolvedType = this.resolvedType;
+				if (!this.resolvedType.isValidBinding()) {
+					scope.problemReporter().javadocInvalidType(typeRef, this.resolvedType, scope.getDeclarationModifiers());
+					return null;
 				}
+				if (isTypeUseDeprecated(this.resolvedType, scope)) {
+					scope.problemReporter().javadocDeprecatedType(this.resolvedType, typeRef, scope.getDeclarationModifiers());
+					return null;
+				}
+				return this.resolvedType = scope.convertToRawType(this.resolvedType);
 			}
 		}
 		return null;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArrayQualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArrayQualifiedTypeReference.java
index 86b4d0e..e2c44c4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArrayQualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArrayQualifiedTypeReference.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
 import org.eclipse.jdt.internal.compiler.lookup.Scope;
 
 
@@ -39,4 +40,9 @@
 		visitor.visit(this, scope);
 		visitor.endVisit(this, scope);
 	}
+	
+	public void traverse(ASTVisitor visitor, ClassScope scope) {
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArraySingleTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArraySingleTypeReference.java
index 8395065..67cde84 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArraySingleTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArraySingleTypeReference.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
 import org.eclipse.jdt.internal.compiler.lookup.Scope;
 
 
@@ -37,4 +38,9 @@
 		visitor.visit(this, scope);
 		visitor.endVisit(this, scope);
 	}
+
+	public void traverse(ASTVisitor visitor, ClassScope scope) {
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java
index 04f1016..9277647 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java
@@ -16,11 +16,23 @@
 public class JavadocFieldReference extends FieldReference {
 
 	public int tagSourceStart, tagSourceEnd;
+	public int tagValue;
+	public MethodBinding methodBinding;
+	public boolean superAccess = false;
 
 	public JavadocFieldReference(char[] source, long pos) {
 		super(source, pos);
 		this.bits |= InsideJavadoc;
 	}
+	
+	/*
+	public Binding getBinding() {
+		if (this.methodBinding != null) {
+			return this.methodBinding;
+		}
+		return this.binding;
+	}
+	*/
 
 	/*
 	 * Resolves type on a Block or Class scope.
@@ -57,18 +69,19 @@
 		if (!fieldBinding.isValidBinding() || !(fieldBinding instanceof FieldBinding)) {
 			if (this.receiverType instanceof ReferenceBinding) {
 				ReferenceBinding refBinding = (ReferenceBinding) this.receiverType;
-				MethodBinding[] bindings = refBinding.getMethods(this.token);
-				if (bindings == null) {
+				MethodBinding[] methodBindings = refBinding.getMethods(this.token);
+				if (methodBindings == null) {
 					scope.problemReporter().javadocInvalidField(this.sourceStart, this.sourceEnd, fieldBinding, this.receiverType, scope.getDeclarationModifiers());
 				} else {
-					switch (bindings.length) {
+					switch (methodBindings.length) {
 						case 0:
 							scope.problemReporter().javadocInvalidField(this.sourceStart, this.sourceEnd, fieldBinding, this.receiverType, scope.getDeclarationModifiers());
 							break;
 						case 1:
-							this.binding = null;
+							this.methodBinding = methodBindings[0];
 							break;
 						default:
+							this.methodBinding = methodBindings[0];
 							scope.problemReporter().javadocAmbiguousMethodReference(this.sourceStart, this.sourceEnd, fieldBinding, scope.getDeclarationModifiers());
 							break;
 					}
@@ -88,7 +101,7 @@
 	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#isSuperAccess()
 	 */
 	public boolean isSuperAccess() {
-		return false;
+		return this.superAccess;
 	}
 
 	public StringBuffer printExpression(int indent, StringBuffer output) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java
index ec69136..3d10d73 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java
@@ -17,6 +17,7 @@
 public class JavadocMessageSend extends MessageSend {
 
 	public int tagSourceStart, tagSourceEnd;
+	public int tagValue;
 	public boolean superAccess = false;
 
 	public JavadocMessageSend(char[] name, long pos) {
@@ -39,11 +40,11 @@
 		// Base type promotion
 		this.constant = NotAConstant;
 		if (this.receiver == null) {
-			this.receiverType = scope.enclosingSourceType();
+			this.actualReceiverType = scope.enclosingSourceType();
 		} else if (scope.kind == Scope.CLASS_SCOPE) {
-			this.receiverType = this.receiver.resolveType((ClassScope) scope);
+			this.actualReceiverType = this.receiver.resolveType((ClassScope) scope);
 		} else {
-			this.receiverType = this.receiver.resolveType((BlockScope) scope);
+			this.actualReceiverType = this.receiver.resolveType((BlockScope) scope);
 		}
 
 		// will check for null after args are resolved
@@ -69,20 +70,19 @@
 		}
 
 		// check receiver type
-		if (this.receiverType == null) {
+		if (this.actualReceiverType == null) {
 			return null;
 		}
-		this.qualifyingType = this.receiverType;
-		this.superAccess = scope.enclosingSourceType().isCompatibleWith(this.receiverType);
+		this.superAccess = scope.enclosingSourceType().isCompatibleWith(this.actualReceiverType);
 
 		// base type cannot receive any message
-		if (this.receiverType.isBaseType()) {
-			scope.problemReporter().javadocErrorNoMethodFor(this, this.receiverType, argumentTypes, scope.getDeclarationModifiers());
+		if (this.actualReceiverType.isBaseType()) {
+			scope.problemReporter().javadocErrorNoMethodFor(this, this.actualReceiverType, argumentTypes, scope.getDeclarationModifiers());
 			return null;
 		}
 		this.binding = (this.receiver != null && this.receiver.isThis())
 			? scope.getImplicitMethod(this.selector, argumentTypes, this)
-			: scope.getMethod(this.receiverType, this.selector, argumentTypes, this);
+			: scope.getMethod(this.actualReceiverType, this.selector, argumentTypes, this);
 		if (!this.binding.isValidBinding()) {
 			// implicit lookup may discover issues due to static/constructor contexts. javadoc must be resilient
 			switch (this.binding.problemId()) {
@@ -97,10 +97,10 @@
 		}
 		if (!this.binding.isValidBinding()) {
 			if (this.binding.declaringClass == null) {
-				if (this.receiverType instanceof ReferenceBinding) {
-					this.binding.declaringClass = (ReferenceBinding) this.receiverType;
+				if (this.actualReceiverType instanceof ReferenceBinding) {
+					this.binding.declaringClass = (ReferenceBinding) this.actualReceiverType;
 				} else { 
-					scope.problemReporter().javadocErrorNoMethodFor(this, this.receiverType, argumentTypes, scope.getDeclarationModifiers());
+					scope.problemReporter().javadocErrorNoMethodFor(this, this.actualReceiverType, argumentTypes, scope.getDeclarationModifiers());
 					return null;
 				}
 			}
@@ -108,7 +108,7 @@
 			// record the closest match, for clients who may still need hint about possible method match
 			if (this.binding instanceof ProblemMethodBinding){
 				MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch;
-				if (closestMatch != null) this.codegenBinding = this.binding = closestMatch;
+				if (closestMatch != null) this.binding = closestMatch;
 			}
 			return this.resolvedType = this.binding == null ? null : this.binding.returnType;
 		}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java
index 388f8ef..5daff1e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java
@@ -47,40 +47,41 @@
 		visitor.visit(this, scope);
 		visitor.endVisit(this, scope);
 	}
+	public void traverse(ASTVisitor visitor, ClassScope scope) {
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
 
 	/*
-	 * 
+	 *
 	 */
-	private TypeBinding internalResolveType(Scope scope) {
+	private TypeBinding internalResolveType(Scope scope, boolean checkBounds) {
 		// handle the error here
 		this.constant = NotAConstant;
-		if (this.resolvedType != null) { // is a shared type reference which was already resolved
-			if (!this.resolvedType.isValidBinding())
-				return null; // already reported error
-		} else {
-			this.resolvedType = getTypeBinding(scope);
-			if (!this.resolvedType.isValidBinding()) {
-				Binding binding = scope.getTypeOrPackage(this.tokens);
-				if (binding instanceof PackageBinding) {
-					this.packageBinding = (PackageBinding) binding;
-				} else {
-					reportInvalidType(scope);
-				}
-				return null;
+		if (this.resolvedType != null) // is a shared type reference which was already resolved
+			return this.resolvedType.isValidBinding() ? this.resolvedType : null; // already reported error
+
+		this.resolvedType = getTypeBinding(scope);
+		if (!this.resolvedType.isValidBinding()) {
+			Binding binding = scope.getTypeOrPackage(this.tokens);
+			if (binding instanceof PackageBinding) {
+				this.packageBinding = (PackageBinding) binding;
+			} else {
+				reportInvalidType(scope);
 			}
-			if (isTypeUseDeprecated(this.resolvedType, scope)) {
-				reportDeprecatedType(scope);
-			}
+			return null;
 		}
-		return this.resolvedType;
+		if (isTypeUseDeprecated(this.resolvedType, scope))
+			reportDeprecatedType(scope);
+		return this.resolvedType = scope.convertToRawType(this.resolvedType);
 	}
 
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveType(org.eclipse.jdt.internal.compiler.lookup.BlockScope)
 	 * We need to override to handle package references
 	 */
-	public TypeBinding resolveType(BlockScope blockScope) {
-		return internalResolveType(blockScope);
+	public TypeBinding resolveType(BlockScope blockScope, boolean checkBounds) {
+		return internalResolveType(blockScope, checkBounds);
 	}
 
 	/* (non-Javadoc)
@@ -88,6 +89,6 @@
 	 * We need to override to handle package references
 	 */
 	public TypeBinding resolveType(ClassScope classScope) {
-		return internalResolveType(classScope);
+		return internalResolveType(classScope, false);
 	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocReturnStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocReturnStatement.java
index 8a53e1b..d541e00 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocReturnStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocReturnStatement.java
@@ -16,6 +16,7 @@
 
 public class JavadocReturnStatement extends ReturnStatement {
 	public char[] description;
+	public boolean empty = true;
 
 	public JavadocReturnStatement(int s, int e, char[] descr) {
 		super(null, s, e);
@@ -23,9 +24,12 @@
 		this.bits |= InsideJavadoc;
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.ast.Statement#resolve(org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
 	public void resolve(BlockScope scope) {
 		MethodScope methodScope = scope.methodScope();
-		MethodBinding methodBinding;
+		MethodBinding methodBinding = null;
 		TypeBinding methodType =
 			(methodScope.referenceContext instanceof AbstractMethodDeclaration)
 				? ((methodBinding = ((AbstractMethodDeclaration) methodScope.referenceContext).binding) == null 
@@ -34,10 +38,22 @@
 				: VoidBinding;
 		if (methodType == null || methodType == VoidBinding) {
 			scope.problemReporter().javadocUnexpectedTag(this.sourceStart, this.sourceEnd);
+		} else if (this.empty) {
+			scope.problemReporter().javadocEmptyReturnTag(this.sourceStart, this.sourceEnd);
 		}
 	}
 
 	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.ast.Statement#printStatement(int, java.lang.StringBuffer)
+	 */
+	public StringBuffer printStatement(int tab, StringBuffer output) {
+		printIndent(tab, output).append("return"); //$NON-NLS-1$
+		if (description != null )
+			output.append(' ').append(description);
+		return output;
+	}
+
+	/* (non-Javadoc)
 	 * Redefine to capture javadoc specific signatures
 	 * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
 	 */
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.java
index 5661217..4bfe4c6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.java
@@ -17,8 +17,10 @@
 
 	public int tagSourceStart, tagSourceEnd;
 
-	public JavadocSingleNameReference(char[] name, int startPosition, int endPosition) {
-		super(name, (((long) startPosition) << 32) + endPosition);
+	public JavadocSingleNameReference(char[] source, long pos, int tagStart, int tagEnd) {
+		super(source, pos);
+		this.tagSourceStart = tagStart;
+		this.tagSourceEnd = tagEnd;
 		this.bits |= InsideJavadoc;
 	}
 
@@ -39,10 +41,10 @@
 		if (warn) {
 			try {
 				MethodScope methScope = (MethodScope) scope;
-				scope.problemReporter().javadocInvalidParamName(this, methScope.referenceMethod().modifiers);
+				scope.problemReporter().javadocUndeclaredParamTagName(this.token, this.sourceStart, this.sourceEnd, methScope.referenceMethod().modifiers);
 			}
 			catch (Exception e) {
-				scope.problemReporter().javadocInvalidParamName(this, -1);
+				scope.problemReporter().javadocUndeclaredParamTagName(this.token, this.sourceStart, this.sourceEnd, -1);
 			}
 		}
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java
index 541f099..44c3c3c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java
@@ -46,40 +46,39 @@
 		visitor.visit(this, scope);
 		visitor.endVisit(this, scope);
 	}
+	
+	public void traverse(ASTVisitor visitor, ClassScope scope) {
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
 
-	/*
-	 * 
-	 */
-	private TypeBinding internalResolveType(Scope scope) {
+	TypeBinding internalResolveType(Scope scope) {
 		// handle the error here
 		this.constant = NotAConstant;
-		if (this.resolvedType != null) { // is a shared type reference which was already resolved
-			if (!this.resolvedType.isValidBinding())
-				return null; // already reported error
-		} else {
-			this.resolvedType = getTypeBinding(scope);
-			if (!this.resolvedType.isValidBinding()) {
-				char[][] tokens = { this.token };
-				Binding binding = scope.getTypeOrPackage(tokens);
-				if (binding instanceof PackageBinding) {
-					this.packageBinding = (PackageBinding) binding;
-				} else {
-					reportInvalidType(scope);
-				}
-				return null;
+		if (this.resolvedType != null)// is a shared type reference which was already resolved
+			return this.resolvedType.isValidBinding() ? this.resolvedType : null; // already reported error
+
+		this.resolvedType = getTypeBinding(scope);
+		if (!this.resolvedType.isValidBinding()) {
+			char[][] tokens = { this.token };
+			Binding binding = scope.getTypeOrPackage(tokens);
+			if (binding instanceof PackageBinding) {
+				this.packageBinding = (PackageBinding) binding;
+			} else {
+				reportInvalidType(scope);
 			}
-			if (isTypeUseDeprecated(this.resolvedType, scope)) {
-				reportDeprecatedType(scope);
-			}
+			return null;
 		}
-		return this.resolvedType;
+		if (isTypeUseDeprecated(this.resolvedType, scope))
+			reportDeprecatedType(scope);
+		return this.resolvedType = scope.convertToRawType(this.resolvedType);
 	}
 
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveType(org.eclipse.jdt.internal.compiler.lookup.BlockScope)
 	 * We need to override to handle package references
 	 */
-	public TypeBinding resolveType(BlockScope blockScope) {
+	public TypeBinding resolveType(BlockScope blockScope, boolean checkBounds) {
 		return internalResolveType(blockScope);
 	}
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
index 353fc00..57fee6e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
@@ -40,21 +40,24 @@
 		if (flowInfo.isReachable()) {
 			bits |= IsLocalDeclarationReachableMASK; // only set if actually reached
 		}
-		if (initialization == null) 
+		if (this.initialization == null) 
 			return flowInfo;
 			
+		int nullStatus = this.initialization.nullStatus(flowInfo);
 		flowInfo =
-			initialization
+			this.initialization
 				.analyseCode(currentScope, flowContext, flowInfo)
 				.unconditionalInits();
-
-		// final int i = (i = 0);
-		// no need to complain since (i = 0) part will get the blame
-		//if (binding.isFinal() && flowInfo.isPotentiallyAssigned(binding)) {
-		//	currentScope.problemReporter().duplicateInitializationOfFinalLocal(binding, this);
-		//}
-				
+		
 		flowInfo.markAsDefinitelyAssigned(binding);
+		switch(nullStatus) {
+			case FlowInfo.NULL :
+				flowInfo.markAsDefinitelyNull(this.binding);
+				break;
+			case FlowInfo.NON_NULL :
+				flowInfo.markAsDefinitelyNonNull(this.binding);
+				break;
+		}
 		return flowInfo;
 	}
 
@@ -131,25 +134,31 @@
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
+	 */
+	public int getKind() {
+		return LOCAL_VARIABLE;
+	}
+	
 	public void resolve(BlockScope scope) {
 
 		// create a binding and add it to the scope
-		TypeBinding typeBinding = type.resolveType(scope);
+		TypeBinding variableType = type.resolveType(scope, true /* check bounds*/);
 
 		checkModifiers();
-
-		if (typeBinding != null) {
-			if (typeBinding == VoidBinding) {
+		if (variableType != null) {
+			if (variableType == VoidBinding) {
 				scope.problemReporter().variableTypeCannotBeVoid(this);
 				return;
 			}
-			if (typeBinding.isArrayType() && ((ArrayBinding) typeBinding).leafComponentType == VoidBinding) {
+			if (variableType.isArrayType() && ((ArrayBinding) variableType).leafComponentType == VoidBinding) {
 				scope.problemReporter().variableTypeCannotBeVoidArray(this);
 				return;
 			}
 		}
 		
-		Binding existingVariable = scope.getBinding(name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
+		Binding existingVariable = scope.getBinding(name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
 		boolean shouldInsertInScope = true;
 		if (existingVariable != null && existingVariable.isValidBinding()){
 			if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) {
@@ -164,14 +173,16 @@
 			if ((modifiers & AccFinal)!= 0 && this.initialization == null) {
 				modifiers |= AccBlankFinal;
 			}
-			binding = new LocalVariableBinding(this, typeBinding, modifiers, false);
+			this.binding = new LocalVariableBinding(this, variableType, modifiers, false);
 			scope.addLocalVariable(binding);
-			binding.constant = NotAConstant;
+			this.binding.setConstant(NotAConstant);
 			// allow to recursivelly target the binding....
 			// the correct constant is harmed if correctly computed at the end of this method
+			
+			resolveAnnotations(scope, this.annotations, this.binding);
 		}
 
-		if (typeBinding == null) {
+		if (variableType == null) {
 			if (initialization != null)
 				initialization.resolveType(scope); // want to report all possible errors
 			return;
@@ -180,20 +191,34 @@
 		// store the constant for final locals 	
 		if (initialization != null) {
 			if (initialization instanceof ArrayInitializer) {
-				TypeBinding initializationType = initialization.resolveTypeExpecting(scope, typeBinding);
+				TypeBinding initializationType = initialization.resolveTypeExpecting(scope, variableType);
 				if (initializationType != null) {
 					((ArrayInitializer) initialization).binding = (ArrayBinding) initializationType;
-					initialization.implicitWidening(typeBinding, initializationType);
+					initialization.computeConversion(scope, variableType, initializationType);
 				}
 			} else {
-				TypeBinding initializationType = initialization.resolveType(scope);
+			    this.initialization.setExpectedType(variableType);
+				TypeBinding initializationType = this.initialization.resolveType(scope);
 				if (initializationType != null) {
-					if (initialization.isConstantValueOfTypeAssignableToType(initializationType, typeBinding)
-						|| (typeBinding.isBaseType() && BaseTypeBinding.isWidening(typeBinding.id, initializationType.id))
-						|| initializationType.isCompatibleWith(typeBinding))
-						initialization.implicitWidening(typeBinding, initializationType);
-					else
-						scope.problemReporter().typeMismatchError(initializationType, typeBinding, this);
+					if (variableType != initializationType) // must call before computeConversion() and typeMismatchError()
+						scope.compilationUnitScope().recordTypeConversion(variableType, initializationType);
+					if (initialization.isConstantValueOfTypeAssignableToType(initializationType, variableType)
+						|| (variableType.isBaseType() && BaseTypeBinding.isWidening(variableType.id, initializationType.id))
+						|| initializationType.isCompatibleWith(variableType)) {
+						this.initialization.computeConversion(scope, variableType, initializationType);
+						if (initializationType.needsUncheckedConversion(variableType)) {
+						    scope.problemReporter().unsafeRawConversion(this.initialization, initializationType, variableType);
+						}						
+					} else if (scope.environment().options.sourceLevel >= JDK1_5 // autoboxing
+									&& (scope.isBoxingCompatibleWith(initializationType, variableType) 
+											|| (initializationType.isBaseType()  // narrowing then boxing ?
+													&& initializationType != null 
+													&& !variableType.isBaseType()
+													&& initialization.isConstantValueOfTypeAssignableToType(initializationType, scope.environment().computeBoxingType(variableType))))) {
+						this.initialization.computeConversion(scope, variableType, initializationType);
+					} else {
+						scope.problemReporter().typeMismatchError(initializationType, variableType, this);
+					}
 				}
 			}
 
@@ -201,10 +226,10 @@
 			// (the optimization of the constant propagation will be done later on)
 			// cast from constant actual type to variable type
 			if (binding != null) {
-				binding.constant =
+				binding.setConstant(
 					binding.isFinal()
-						? initialization.constant.castTo((typeBinding.id << 4) + initialization.constant.typeID())
-						: NotAConstant;
+						? initialization.constant.castTo((variableType.id << 4) + initialization.constant.typeID())
+						: NotAConstant);
 			}
 		}
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java
index 70294b5..6da299b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java
@@ -38,7 +38,7 @@
 	{	if (length == 1) { 	constant = Constant.fromValue(0L);	return;	}
 		final int shift,radix;
 		int j ;
-		if ( (source[1] == 'x') | (source[1] == 'X') )
+		if ( (source[1] == 'x') || (source[1] == 'X') )
 		{	shift = 4 ; j = 2; radix = 16;}
 		else
 		{	shift = 3 ; j = 1; radix = 8;}
@@ -85,11 +85,9 @@
  */ 
 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
 	int pc = codeStream.position;
-	if (valueRequired)
-		if ((implicitConversion >> 4) == T_long)
-			codeStream.generateInlinedValue(value);
-		else
-			codeStream.generateConstant(constant, implicitConversion);
+	if (valueRequired) {
+		codeStream.generateConstant(constant, implicitConversion);
+	}
 	codeStream.recordPositionsFrom(pc, this.sourceStart);
 }
 public TypeBinding literalType(BlockScope scope) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MarkerAnnotation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MarkerAnnotation.java
new file mode 100644
index 0000000..65f1bd5
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MarkerAnnotation.java
@@ -0,0 +1,35 @@
+/*
+ * Created on 2004-03-11
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class MarkerAnnotation extends Annotation {
+	
+	public MarkerAnnotation(TypeReference type, int sourceStart) {
+		this.type = type;
+		this.sourceStart = sourceStart;
+		this.sourceEnd = type.sourceEnd;
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.Annotation#memberValuePairs()
+	 */
+	public MemberValuePair[] memberValuePairs() {
+		return NoValuePairs;
+	}
+	
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
+	public void traverse(ASTVisitor visitor, CompilationUnitScope scope) {
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java
new file mode 100644
index 0000000..04d0ee8
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+/**
+ * MemberValuePair node
+ */
+public class MemberValuePair extends ASTNode {
+	
+	public char[] name;
+	public Expression value;
+	public MethodBinding binding;
+	
+	public MemberValuePair(char[] token, int sourceStart, int sourceEnd, Expression value) {
+		this.name = token;
+		this.sourceStart = sourceStart;
+		this.sourceEnd = sourceEnd;
+		this.value = value;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#print(int, java.lang.StringBuffer)
+	 */
+	public StringBuffer print(int indent, StringBuffer output) {
+		output
+			.append(name)
+			.append(" = "); //$NON-NLS-1$
+		value.print(indent, output);
+		return output;
+	}
+	
+	public void resolveTypeExpecting(BlockScope scope, TypeBinding requiredType) {
+		
+		if (requiredType == null) 
+			return;
+		if (this.value == null) 
+			return;
+
+		this.value.setExpectedType(requiredType); // needed in case of generic method invocation
+		if (this.value instanceof ArrayInitializer) {
+			ArrayInitializer initializer = (ArrayInitializer) this.value;
+			if ((initializer.resolveTypeExpecting(scope, this.binding.returnType)) != null) {
+				this.value.resolvedType = initializer.binding = (ArrayBinding) this.binding.returnType;
+			}			
+		} else {
+			this.value.resolveType(scope);
+		}
+		TypeBinding valueType = this.value.resolvedType;
+		if (valueType == null)
+			return;
+
+		TypeBinding leafType = requiredType.leafComponentType();
+		if (!((this.value.isConstantValueOfTypeAssignableToType(valueType, requiredType)
+				|| (requiredType.isBaseType() && BaseTypeBinding.isWidening(requiredType.id, valueType.id)))
+				|| valueType.isCompatibleWith(requiredType))) {
+
+			if (!(requiredType.isArrayType() 
+					&& requiredType.dimensions() == 1 
+					&& (this.value.isConstantValueOfTypeAssignableToType(valueType, leafType)
+							|| (leafType.isBaseType() && BaseTypeBinding.isWidening(leafType.id, valueType.id)))
+							|| valueType.isCompatibleWith(leafType))) {
+				
+				scope.problemReporter().typeMismatchError(valueType, requiredType, this.value);
+				return; // may allow to proceed to find more errors at once
+			}
+		} else {
+			scope.compilationUnitScope().recordTypeConversion(requiredType.leafComponentType(), valueType.leafComponentType());
+			this.value.computeConversion(scope, requiredType, valueType);				
+		}
+		
+		// annotation methods can only return base types, String, Class, enum type, annotation types and arrays of these
+		checkAnnotationMethodType: {
+			switch (leafType.erasure().id) {
+				case T_byte :
+				case T_short :
+				case T_char :
+				case T_int :
+				case T_long :
+				case T_float :
+				case T_double :
+				case T_boolean :
+				case T_JavaLangString :
+					if (this.value instanceof ArrayInitializer) {
+						ArrayInitializer initializer = (ArrayInitializer) this.value;
+						final Expression[] expressions = initializer.expressions;
+						if (expressions != null) {
+							for (int i =0, max = expressions.length; i < max; i++) {
+								if (expressions[i].constant == NotAConstant) {
+									scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, expressions[i]);
+								}
+							}
+						}
+					} else if (this.value.constant == NotAConstant) {
+						scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, this.value);
+					}
+					break checkAnnotationMethodType;
+				case T_JavaLangClass :
+					if (this.value instanceof ArrayInitializer) {
+						ArrayInitializer initializer = (ArrayInitializer) this.value;
+						final Expression[] expressions = initializer.expressions;
+						if (expressions != null) {
+							for (int i =0, max = expressions.length; i < max; i++) {
+								if (!(expressions[i] instanceof ClassLiteralAccess)) {
+									scope.problemReporter().annotationValueMustBeClassLiteral(this.binding.declaringClass, this.name, expressions[i]);
+								}
+							}
+						}
+					} else if (!(this.value instanceof ClassLiteralAccess)) {
+						scope.problemReporter().annotationValueMustBeClassLiteral(this.binding.declaringClass, this.name, this.value);
+					}
+					break checkAnnotationMethodType;
+			}
+			if (leafType.isEnum()) {
+				break checkAnnotationMethodType;
+			}
+			if (leafType.isAnnotationType()) {
+				break checkAnnotationMethodType;
+			}
+		}
+	}
+	
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		if (visitor.visit(this, scope)) {
+			if (this.value != null) {
+				this.value.traverse(visitor, scope);
+			}
+		}
+		visitor.endVisit(this, scope);
+	}
+	public void traverse(ASTVisitor visitor, CompilationUnitScope scope) {
+		if (visitor.visit(this, scope)) {
+			if (this.value != null) {
+				this.value.traverse(visitor, scope);
+			}
+		}
+		visitor.endVisit(this, scope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
index a9a2e9d..05b78da 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
@@ -11,6 +11,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -18,20 +19,28 @@
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class MessageSend extends Expression implements InvocationSite {
+    
 	public Expression receiver ;
 	public char[] selector ;
 	public Expression[] arguments ;
-	public MethodBinding binding, codegenBinding;
+	public MethodBinding binding;							// exact binding resulting from lookup
+	protected MethodBinding codegenBinding;		// actual binding used for code generation (if no synthetic accessor)
+	MethodBinding syntheticAccessor;						// synthetic accessor for inner-emulation
+	public TypeBinding expectedType;					// for generic method invocation (return type inference)
 
 	public long nameSourcePosition ; //(start<<32)+end
 
-	MethodBinding syntheticAccessor;
-
-	public TypeBinding receiverType, qualifyingType;
+	public TypeBinding actualReceiverType;
+	public TypeBinding valueCast; // extra reference type cast to perform on method returned value
+	public TypeReference[] typeArguments;
+	public TypeBinding[] genericTypeArguments;
 	
 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
 
-	flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo, !binding.isStatic()).unconditionalInits();
+	boolean nonStatic = !binding.isStatic();
+	flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits();
+	if (nonStatic) receiver.checkNullStatus(currentScope, flowContext, flowInfo, FlowInfo.NON_NULL);
+
 	if (arguments != null) {
 		int length = arguments.length;
 		for (int i = 0; i < length; i++) {
@@ -46,7 +55,31 @@
 	manageSyntheticAccessIfNecessary(currentScope, flowInfo);	
 	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()) {
+		MethodBinding originalBinding = this.binding.original();
+		if (originalBinding != this.binding) {
+		    // extra cast needed if method return type has type variable
+		    if ((originalBinding.returnType.tagBits & TagBits.HasTypeVariable) != 0 && runtimeTimeType.id != T_JavaLangObject) {
+		        this.valueCast = originalBinding.returnType.genericCast(scope.boxing(runtimeTimeType)); // runtimeType could be base type in boxing case
+		    }
+		} 	else if (this.actualReceiverType.isArrayType() 
+						&& runtimeTimeType.id != T_JavaLangObject
+						&& this.binding.parameters == NoParameters 
+						&& scope.environment().options.complianceLevel >= JDK1_5 
+						&& CharOperation.equals(this.binding.selector, CLONE)) {
+					// from 1.5 compliant mode on, array#clone() resolves to array type, but codegen to #clone()Object - thus require extra inserted cast
+			this.valueCast = runtimeTimeType;			
+		}
+	}
+	super.computeConversion(scope, runtimeTimeType, compileTimeType);
+}
 /**
  * MessageSend code generation
  *
@@ -59,7 +92,7 @@
 	int pc = codeStream.position;
 
 	// generate receiver/enclosing instance access
-	boolean isStatic = codegenBinding.isStatic();
+	boolean isStatic = this.codegenBinding.isStatic();
 	// outer access ?
 	if (!isStatic && ((bits & DepthMASK) != 0) && receiver.isImplicitThis()){
 		// outer method can be reached through emulation if implicit access
@@ -70,23 +103,19 @@
 		receiver.generateCode(currentScope, codeStream, !isStatic);
 	}
 	// generate arguments
-	if (arguments != null){
-		for (int i = 0, max = arguments.length; i < max; i++){
-			arguments[i].generateCode(currentScope, codeStream, true);
-		}
-	}
+	generateArguments(binding, arguments, currentScope, codeStream);
 	// actual message invocation
 	if (syntheticAccessor == null){
 		if (isStatic){
-			codeStream.invokestatic(codegenBinding);
+			codeStream.invokestatic(this.codegenBinding);
 		} else {
-			if( (receiver.isSuper()) || codegenBinding.isPrivate()){
-				codeStream.invokespecial(codegenBinding);
+			if( (receiver.isSuper()) || this.codegenBinding.isPrivate()){
+				codeStream.invokespecial(this.codegenBinding);
 			} else {
-				if (codegenBinding.declaringClass.isInterface()){
-					codeStream.invokeinterface(codegenBinding);
+				if ((this.codegenBinding.declaringClass.modifiers & AccInterface) != 0) { // interface or annotation type
+					codeStream.invokeinterface(this.codegenBinding);
 				} else {
-					codeStream.invokevirtual(codegenBinding);
+					codeStream.invokevirtual(this.codegenBinding);
 				}
 			}
 		}
@@ -96,6 +125,8 @@
 	// operation on the returned value
 	if (valueRequired){
 		// implicit conversion if necessary
+		if (this.valueCast != null) 
+			codeStream.checkcast(this.valueCast);
 		codeStream.generateImplicitConversion(implicitConversion);
 	} else {
 		// pop return value if any
@@ -112,6 +143,12 @@
 	}
 	codeStream.recordPositionsFrom(pc, (int)(this.nameSourcePosition >>> 32)); // highlight selector
 }
+/**
+ * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+ */
+public TypeBinding[] genericTypeArguments() {
+	return this.genericTypeArguments;
+}
 public boolean isSuperAccess() {	
 	return receiver.isSuper();
 }
@@ -121,13 +158,16 @@
 public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo){
 
 	if (!flowInfo.isReachable()) return;
-	if (binding.isPrivate()){
+
+	// if method from parameterized type got found, use the original method at codegen time
+	this.codegenBinding = this.binding.original();
+	if (this.binding.isPrivate()){
 
 		// depth is set for both implicit and explicit access (see MethodBinding#canBeSeenBy)		
-		if (currentScope.enclosingSourceType() != binding.declaringClass){
+		if (currentScope.enclosingSourceType() != this.codegenBinding.declaringClass){
 		
-			syntheticAccessor = ((SourceTypeBinding)binding.declaringClass).addSyntheticMethod(binding, isSuperAccess());
-			currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
+			syntheticAccessor = ((SourceTypeBinding)this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isSuperAccess());
+			currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this);
 			return;
 		}
 
@@ -135,44 +175,60 @@
 
 		// qualified super need emulation always
 		SourceTypeBinding destinationType = (SourceTypeBinding)(((QualifiedSuperReference)receiver).currentCompatibleType);
-		syntheticAccessor = destinationType.addSyntheticMethod(binding, isSuperAccess());
-		currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
+		syntheticAccessor = destinationType.addSyntheticMethod(this.codegenBinding, isSuperAccess());
+		currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this);
 		return;
 
 	} else if (binding.isProtected()){
 
 		SourceTypeBinding enclosingSourceType;
 		if (((bits & DepthMASK) != 0) 
-				&& binding.declaringClass.getPackage() 
+				&& this.codegenBinding.declaringClass.getPackage() 
 					!= (enclosingSourceType = currentScope.enclosingSourceType()).getPackage()){
 
 			SourceTypeBinding currentCompatibleType = (SourceTypeBinding)enclosingSourceType.enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
-			syntheticAccessor = currentCompatibleType.addSyntheticMethod(binding, isSuperAccess());
-			currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
+			syntheticAccessor = currentCompatibleType.addSyntheticMethod(this.codegenBinding, isSuperAccess());
+			currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this);
 			return;
 		}
 	}
+	
 	// if the binding declaring class is not visible, need special action
 	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
 	// NOTE: from target 1.2 on, method's declaring class is touched if any different from receiver type
 	// and not from Object or implicit static method call.	
-	if (binding.declaringClass != this.qualifyingType
-		&& !this.qualifyingType.isArrayType()
+	if (this.binding.declaringClass != this.actualReceiverType
+		&& !this.actualReceiverType.isArrayType()
 		&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
-				&& (!receiver.isImplicitThis() || !binding.isStatic())
-				&& binding.declaringClass.id != T_Object) // no change for Object methods
-			|| !binding.declaringClass.canBeSeenBy(currentScope))) {
+				&& (!receiver.isImplicitThis() || !this.codegenBinding.isStatic())
+				&& this.binding.declaringClass.id != T_JavaLangObject) // no change for Object methods
+			|| !this.binding.declaringClass.canBeSeenBy(currentScope))) {
 
-		this.codegenBinding = currentScope.enclosingSourceType().getUpdatedMethodBinding(binding, (ReferenceBinding) this.qualifyingType);
+		this.codegenBinding = currentScope.enclosingSourceType().getUpdatedMethodBinding(
+		        										this.codegenBinding, (ReferenceBinding) this.actualReceiverType.erasure());
 
 		// Post 1.4.0 target, array clone() invocations are qualified with array type 
 		// This is handled in array type #clone method binding resolution (see Scope and UpdatedMethodBinding)
 	}
 }
 
+public int nullStatus(FlowInfo flowInfo) {
+	return FlowInfo.UNKNOWN;
+}
+	
 public StringBuffer printExpression(int indent, StringBuffer output){
 	
 	if (!receiver.isImplicitThis()) receiver.printExpression(0, output).append('.');
+	if (this.typeArguments != null) {
+		output.append('<');//$NON-NLS-1$
+		int max = typeArguments.length - 1;
+		for (int j = 0; j < max; j++) {
+			typeArguments[j].print(0, output);
+			output.append(", ");//$NON-NLS-1$
+		}
+		typeArguments[max].print(0, output);
+		output.append('>');
+	}
 	output.append(selector).append('(') ; //$NON-NLS-1$
 	if (arguments != null) {
 		for (int i = 0; i < arguments.length ; i ++) {	
@@ -188,18 +244,32 @@
 	// Base type promotion
 
 	constant = NotAConstant;
-	boolean receiverCast = false, argumentsCast = false; 
+	boolean receiverCast = false, argsContainCast = false; 
 	if (this.receiver instanceof CastExpression) {
 		this.receiver.bits |= IgnoreNeedForCastCheckMASK; // will check later on
 		receiverCast = true;
 	}
-	this.qualifyingType = this.receiverType = receiver.resolveType(scope); 
-	if (receiverCast && this.receiverType != null) {
+	this.actualReceiverType = receiver.resolveType(scope); 
+	if (receiverCast && this.actualReceiverType != null) {
 		 // due to change of declaring class with receiver type, only identity cast should be notified
-		if (((CastExpression)this.receiver).expression.resolvedType == this.receiverType) { 
-					scope.problemReporter().unnecessaryCast((CastExpression)this.receiver);		
+		if (((CastExpression)this.receiver).expression.resolvedType == this.actualReceiverType) { 
+			scope.problemReporter().unnecessaryCast((CastExpression)this.receiver);		
 		}
 	}
+	// resolve type arguments (for generic constructor call)
+	if (this.typeArguments != null) {
+		int length = this.typeArguments.length;
+		boolean argHasError = false; // typeChecks all arguments
+		this.genericTypeArguments = new TypeBinding[length];
+		for (int i = 0; i < length; i++) {
+			if ((this.genericTypeArguments[i] = this.typeArguments[i].resolveType(scope, true /* check bounds*/)) == null) {
+				argHasError = true;
+			}
+		}
+		if (argHasError) {
+			return null;
+		}
+	}	
 	// will check for null after args are resolved
 	TypeBinding[] argumentTypes = NoParameters;
 	if (arguments != null) {
@@ -210,75 +280,92 @@
 			Expression argument = arguments[i];
 			if (argument instanceof CastExpression) {
 				argument.bits |= IgnoreNeedForCastCheckMASK; // will check later on
-				argumentsCast = true;
+				argsContainCast = true;
 			}
 			if ((argumentTypes[i] = argument.resolveType(scope)) == null){
 				argHasError = true;
 			}
 		}
 		if (argHasError) {
-			if(receiverType instanceof ReferenceBinding) {
+			if(actualReceiverType instanceof ReferenceBinding) {
 				// record any selector match, for clients who may still need hint about possible method match
-				this.codegenBinding = this.binding = scope.findMethod((ReferenceBinding)receiverType, selector, new TypeBinding[]{}, this);
+				this.binding = scope.findMethod((ReferenceBinding)actualReceiverType, selector, new TypeBinding[]{}, this);
 			}			
 			return null;
 		}
 	}
-	if (this.receiverType == null)
-		return null;
-
-	// base type cannot receive any message
-	if (this.receiverType.isBaseType()) {
-		scope.problemReporter().errorNoMethodFor(this, this.receiverType, argumentTypes);
+	if (this.actualReceiverType == null) {
 		return null;
 	}
-	this.codegenBinding = this.binding = 
+	// base type cannot receive any message
+	if (this.actualReceiverType.isBaseType()) {
+		scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
+		return null;
+	}
+	this.binding = 
 		receiver.isImplicitThis()
 			? scope.getImplicitMethod(selector, argumentTypes, this)
-			: scope.getMethod(this.receiverType, selector, argumentTypes, this); 
+			: scope.getMethod(this.actualReceiverType, selector, argumentTypes, this); 
 	if (!binding.isValidBinding()) {
 		if (binding.declaringClass == null) {
-			if (this.receiverType instanceof ReferenceBinding) {
-				binding.declaringClass = (ReferenceBinding) this.receiverType;
+			if (this.actualReceiverType instanceof ReferenceBinding) {
+				binding.declaringClass = (ReferenceBinding) this.actualReceiverType;
 			} else { 
-				scope.problemReporter().errorNoMethodFor(this, this.receiverType, argumentTypes);
+				scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
 				return null;
 			}
 		}
 		scope.problemReporter().invalidMethod(this, binding);
-		// record the closest match, for clients who may still need hint about possible method match
-		if (binding instanceof ProblemMethodBinding){
-			MethodBinding closestMatch = ((ProblemMethodBinding)binding).closestMatch;
-			if (closestMatch != null) this.codegenBinding = this.binding = closestMatch;
+		MethodBinding closestMatch = ((ProblemMethodBinding)binding).closestMatch;
+		switch (this.binding.problemId()) {
+			case ProblemReasons.Ambiguous :
+			case ProblemReasons.NotVisible :
+			case ProblemReasons.NonStaticReferenceInConstructorInvocation :
+			case ProblemReasons.NonStaticReferenceInStaticContext :
+			case ProblemReasons.ReceiverTypeNotVisible :
+			case ProblemReasons.ParameterBoundMismatch :
+				// only steal returnType in cases listed above
+				if (closestMatch != null) this.resolvedType = closestMatch.returnType;
+			default :
 		}
-		return this.resolvedType = this.binding == null ? null : this.binding.returnType;
+		// record the closest match, for clients who may still need hint about possible method match
+		if (closestMatch != null) {
+			this.binding = closestMatch;
+			if (closestMatch.isPrivate() && !scope.isDefinedInMethod(closestMatch)) {
+				// ignore cases where method is used from within inside itself (e.g. direct recursions)
+				closestMatch.original().modifiers |= AccPrivateUsed;
+			}
+		}
+		return this.resolvedType;
 	}
 	if (!binding.isStatic()) {
 		// the "receiver" must not be a type, in other words, a NameReference that the TC has bound to a Type
 		if (receiver instanceof NameReference 
-				&& (((NameReference) receiver).bits & BindingIds.TYPE) != 0) {
+				&& (((NameReference) receiver).bits & Binding.TYPE) != 0) {
 			scope.problemReporter().mustUseAStaticMethod(this, binding);
+		} else {
+			// compute generic cast if necessary
+			TypeBinding expectedReceiverType = this.actualReceiverType.erasure().isCompatibleWith(this.binding.declaringClass.erasure())
+				? this.actualReceiverType
+				: this.binding.declaringClass;
+			receiver.computeConversion(scope, expectedReceiverType, actualReceiverType);
+			if (expectedReceiverType != this.actualReceiverType) this.actualReceiverType = expectedReceiverType;
 		}
 	} else {
 		// static message invoked through receiver? legal but unoptimal (optional warning).
 		if (!(receiver.isImplicitThis()
 				|| receiver.isSuper()
 				|| (receiver instanceof NameReference 
-					&& (((NameReference) receiver).bits & BindingIds.TYPE) != 0))) {
+					&& (((NameReference) receiver).bits & Binding.TYPE) != 0))) {
 			scope.problemReporter().nonStaticAccessToStaticMethod(this, binding);
 		}
-		if (!receiver.isImplicitThis() && binding.declaringClass != receiverType) {
+		if (!receiver.isImplicitThis() && binding.declaringClass != actualReceiverType) {
 			scope.problemReporter().indirectAccessToStaticMethod(this, binding);
 		}		
 	}
-	if (arguments != null) {
-		for (int i = 0; i < arguments.length; i++) {
-			arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
-		}
-		if (argumentsCast) {
-			CastExpression.checkNeedForArgumentCasts(scope, this.receiver, receiverType, binding, this.arguments, argumentTypes, this);
-		}
-	}
+	if (this.arguments != null) 
+		checkInvocationArguments(scope, this.receiver, actualReceiverType, binding, this.arguments, argumentTypes, argsContainCast, this);
+
 	//-------message send that are known to fail at compile time-----------
 	if (binding.isAbstract()) {
 		if (receiver.isSuper()) {
@@ -289,11 +376,28 @@
 	if (isMethodUseDeprecated(binding, scope))
 		scope.problemReporter().deprecatedMethod(binding, this);
 
-	return this.resolvedType = binding.returnType;
+	// from 1.5 compliance on, array#clone() returns the array type (but binding still shows Object)
+	if (actualReceiverType.isArrayType() 
+			&& this.binding.parameters == NoParameters 
+			&& scope.environment().options.complianceLevel >= JDK1_5 
+			&& CharOperation.equals(this.binding.selector, CLONE)) {
+		this.resolvedType = actualReceiverType;
+	} else {
+		this.resolvedType = this.binding.returnType;
+	}
+	return this.resolvedType;
 }
+
 public void setActualReceiverType(ReferenceBinding receiverType) {
-	this.qualifyingType = receiverType;
+	this.actualReceiverType = receiverType;
 }
+/**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#setExpectedType(org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
+ */
+public void setExpectedType(TypeBinding expectedType) {
+    this.expectedType = expectedType;
+}
+
 public void setDepth(int depth) {
 	bits &= ~DepthMASK; // flush previous depth if any
 	if (depth > 0) {
@@ -307,6 +411,11 @@
 public void traverse(ASTVisitor visitor, BlockScope blockScope) {
 	if (visitor.visit(this, blockScope)) {
 		receiver.traverse(visitor, blockScope);
+		if (this.typeArguments != null) {
+			for (int i = 0, typeArgumentsLength = this.typeArguments.length; i < typeArgumentsLength; i++) {
+				this.typeArguments[i].traverse(visitor, blockScope);
+			}		
+		}
 		if (arguments != null) {
 			int argumentsLength = arguments.length;
 			for (int i = 0; i < argumentsLength; i++)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
index b738665..c9de4c6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
@@ -13,6 +13,7 @@
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.flow.ExceptionHandlingFlowContext;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
@@ -23,7 +24,8 @@
 public class MethodDeclaration extends AbstractMethodDeclaration {
 	
 	public TypeReference returnType;
-
+	public TypeParameter[] typeParameters;
+	
 	/**
 	 * MethodDeclaration constructor comment.
 	 */
@@ -49,10 +51,14 @@
 				}
 			}
 				
+			// skip enum implicit methods
+			if (binding.declaringClass.isEnum() && (this.selector == TypeConstants.VALUES || this.selector == TypeConstants.VALUEOF))
+				return;
+
 			// may be in a non necessary <clinit> for innerclass with static final constant fields
 			if (binding.isAbstract() || binding.isNative())
 				return;
-
+			
 			ExceptionHandlingFlowContext methodContext =
 				new ExceptionHandlingFlowContext(
 					initializationContext,
@@ -61,6 +67,12 @@
 					scope,
 					FlowInfo.DEAD_END);
 
+			// tag parameters as being set
+			if (this.arguments != null) {
+				for (int i = 0, count = this.arguments.length; i < count; i++) {
+					flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
+				}
+			}
 			// propagate to statements
 			if (statements != null) {
 				boolean didAlreadyComplain = false;
@@ -89,6 +101,11 @@
 		}
 	}
 
+	public boolean isMethod() {
+
+		return true;
+	}
+
 	public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
 
 		//fill up the method body with statement
@@ -110,29 +127,35 @@
 			this.returnType.resolvedType = this.binding.returnType;
 			// record the return type binding
 		}
-		// look if the name of the method is correct
-		if (binding != null && isTypeUseDeprecated(binding.returnType, scope))
-			scope.problemReporter().deprecatedType(binding.returnType, returnType);
-
 		// check if method with constructor name
 		if (CharOperation.equals(scope.enclosingSourceType().sourceName, selector)) {
 			scope.problemReporter().methodWithConstructorName(this);
 		}
 		
+		// check @Override annotation
+		if (this.binding != null 
+				&& (this.binding.tagBits & TagBits.AnnotationOverride) != 0
+				&& (this.binding.modifiers & AccOverriding) == 0) {
+			scope.problemReporter().methodMustOverride(this);
+		}
+				
 		// by grammatical construction, interface methods are always abstract
-		if (!scope.enclosingSourceType().isInterface()){
-
-			// if a method has an semicolon body and is not declared as abstract==>error
-			// native methods may have a semicolon body 
-			if ((modifiers & AccSemicolonBody) != 0) {
-				if ((modifiers & AccNative) == 0)
-					if ((modifiers & AccAbstract) == 0)
-						scope.problemReporter().methodNeedBody(this);
-			} else {
-				// the method HAS a body --> abstract native modifiers are forbiden
-				if (((modifiers & AccNative) != 0) || ((modifiers & AccAbstract) != 0))
-					scope.problemReporter().methodNeedingNoBody(this);
-			}
+		switch (scope.referenceType().kind()) {
+			case IGenericType.ENUM_DECL :
+				if (this.selector == TypeConstants.VALUES) break;
+				if (this.selector == TypeConstants.VALUEOF) break;
+			case IGenericType.CLASS_DECL :
+				// if a method has an semicolon body and is not declared as abstract==>error
+				// native methods may have a semicolon body 
+				if ((modifiers & AccSemicolonBody) != 0) {
+					if ((modifiers & AccNative) == 0)
+						if ((modifiers & AccAbstract) == 0)
+							scope.problemReporter().methodNeedBody(this);
+				} else {
+					// the method HAS a body --> abstract native modifiers are forbiden
+					if (((modifiers & AccNative) != 0) || ((modifiers & AccAbstract) != 0))
+						scope.problemReporter().methodNeedingNoBody(this);
+				}
 		}
 		super.resolveStatements(); 
 	}
@@ -142,6 +165,17 @@
 		ClassScope classScope) {
 
 		if (visitor.visit(this, classScope)) {
+			if (this.annotations != null) {
+				int annotationsLength = this.annotations.length;
+				for (int i = 0; i < annotationsLength; i++)
+					this.annotations[i].traverse(visitor, scope);
+			}
+			if (this.typeParameters != null) {
+				int typeParametersLength = this.typeParameters.length;
+				for (int i = 0; i < typeParametersLength; i++) {
+					this.typeParameters[i].traverse(visitor, scope);
+				}
+			}			
 			if (returnType != null)
 				returnType.traverse(visitor, scope);
 			if (arguments != null) {
@@ -162,4 +196,7 @@
 		}
 		visitor.endVisit(this, classScope);
 	}
+	public TypeParameter[] typeParameters() {
+	    return this.typeParameters;
+	}		
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java
index 98a3f30..c48432f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java
@@ -12,11 +12,10 @@
 
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
-public abstract class NameReference extends Reference implements InvocationSite, BindingIds {
+public abstract class NameReference extends Reference implements InvocationSite {
 
 	public Binding binding, codegenBinding; //may be aTypeBinding-aFieldBinding-aLocalVariableBinding
 	
-	public TypeBinding receiverType;		// raw receiver type
 	public TypeBinding actualReceiverType;	// modified receiver type - actual one according to namelookup
 
 	//the error printing
@@ -28,7 +27,7 @@
 	//no changeClass in java.
 public NameReference() {
 	super();
-	bits |= TYPE | VARIABLE; // restrictiveFlag
+	bits |= Binding.TYPE | Binding.VARIABLE; // restrictiveFlag
 	
 }
 public FieldBinding fieldBinding() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NormalAnnotation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NormalAnnotation.java
new file mode 100644
index 0000000..d8a720e
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NormalAnnotation.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/**
+ * Normal annotation node
+ */
+public class NormalAnnotation extends Annotation {
+	
+	public MemberValuePair[] memberValuePairs;
+	
+	public NormalAnnotation(TypeReference type, int sourceStart) {
+		this.type = type;
+		this.sourceStart = sourceStart;
+		this.sourceEnd = type.sourceEnd;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.Annotation#memberValuePairs()
+	 */
+	public MemberValuePair[] memberValuePairs() {
+		return this.memberValuePairs == null ? NoValuePairs : this.memberValuePairs;
+	}
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+		super.printExpression(indent, output);
+		output.append('(');
+		if (this.memberValuePairs != null) {
+			for (int i = 0, max = this.memberValuePairs.length; i < max; i++) {
+				if (i > 0) {
+					output.append(',');
+				}
+				this.memberValuePairs[i].print(indent, output);
+			}
+		}
+		output.append(')');
+		return output;
+	}
+	
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		if (visitor.visit(this, scope)) {
+			if (this.memberValuePairs != null) {
+				int memberValuePairsLength = this.memberValuePairs.length;
+				for (int i = 0; i < memberValuePairsLength; i++)
+					this.memberValuePairs[i].traverse(visitor, scope);
+			}
+		}
+		visitor.endVisit(this, scope);
+	}
+	public void traverse(ASTVisitor visitor, CompilationUnitScope scope) {
+		if (visitor.visit(this, scope)) {
+			if (this.memberValuePairs != null) {
+				int memberValuePairsLength = this.memberValuePairs.length;
+				for (int i = 0; i < memberValuePairsLength; i++)
+					this.memberValuePairs[i].traverse(visitor, scope);
+			}
+		}
+		visitor.endVisit(this, scope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
index d79b252..ea507f3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
@@ -12,6 +12,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.lookup.*;
 
 public class NullLiteral extends MagicLiteral {
@@ -37,14 +38,20 @@
 	 */ 
 	public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
 		int pc = codeStream.position;
-		if (valueRequired)
+		if (valueRequired) {
 			codeStream.aconst_null();
+			codeStream.generateImplicitConversion(this.implicitConversion);
+		}
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 	public TypeBinding literalType(BlockScope scope) {
 		return NullBinding;
 	}
 
+	public int nullStatus(FlowInfo flowInfo) {
+		return FlowInfo.NULL;
+	}
+	
 	/**
 	 * 
 	 */
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java
index 4574e0b..7ea85eb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java
@@ -10,6 +10,8 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+
 public abstract class OperatorExpression extends Expression implements OperatorIds {
 
 	public static int[][] OperatorSignatures = new int[NumberOfTables][];
@@ -66,10 +68,10 @@
 					case T_float	: return "100.0f"; //$NON-NLS-1$
 					case T_int		: return "1"; //$NON-NLS-1$
 					case T_long		: return "7L"; //$NON-NLS-1$
-					case T_String	: return "\"hello-world\""; //$NON-NLS-1$
+					case T_JavaLangString	: return "\"hello-world\""; //$NON-NLS-1$
 					case T_null		: return "null"; //$NON-NLS-1$
 					case T_short	: return "((short) 5)"; //$NON-NLS-1$
-					case T_Object	: return "null";} //$NON-NLS-1$
+					case T_JavaLangObject	: return "null";} //$NON-NLS-1$
 				return "";} //$NON-NLS-1$
 	
 			public  final String type(int code){
@@ -81,10 +83,10 @@
 					case T_float	: return "f"; //$NON-NLS-1$
 					case T_int		: return "i"; //$NON-NLS-1$
 					case T_long		: return "l"; //$NON-NLS-1$
-					case T_String	: return "str"; //$NON-NLS-1$
+					case T_JavaLangString	: return "str"; //$NON-NLS-1$
 					case T_null		: return "null"; //$NON-NLS-1$
 					case T_short	: return "s"; //$NON-NLS-1$
-					case T_Object	: return "obj";} //$NON-NLS-1$
+					case T_JavaLangObject	: return "obj";} //$NON-NLS-1$
 				return "xxx";} //$NON-NLS-1$
 			
 			public  final String operator(int operator){
@@ -122,7 +124,7 @@
 			"\t\t//method automatically generated by\n"+ //$NON-NLS-1$
 			"\t\t//org.eclipse.jdt.internal.compiler.ast.OperatorExpression.generateTableTestCase();\n"+ //$NON-NLS-1$
 		
-			"\t\tString str0;\t String str\t= "+decode.constant(T_String)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+			"\t\tString str0;\t String str\t= "+decode.constant(T_JavaLangString)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
 			"\t\tint i0;\t int i\t= "+decode.constant(T_int)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
 			"\t\tboolean z0;\t boolean z\t= "+decode.constant(T_boolean)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
 			"\t\tchar c0; \t char  c\t= "+decode.constant(T_char)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
@@ -131,7 +133,7 @@
 			"\t\tbyte b0; \t byte b\t= "+decode.constant(T_byte)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
 			"\t\tshort s0; \t short s\t= "+decode.constant(T_short)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
 			"\t\tlong l0; \t long l\t= "+decode.constant(T_long)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
-			"\t\tObject obj0; \t Object obj\t= "+decode.constant(T_Object)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+			"\t\tObject obj0; \t Object obj\t= "+decode.constant(T_JavaLangObject)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
 			"\n"; //$NON-NLS-1$
 	
 		int error = 0;		
@@ -150,8 +152,8 @@
 	
 				{	s += "\t\t"+decode.type(result)+"0"+" = "+decode.type(left); //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-2$
 					s += " "+decode.operator(operator)+" "+decode.type(right)+";\n"; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
-					String begin = result == T_String ? "\t\tif (! " : "\t\tif ( "; //$NON-NLS-2$ //$NON-NLS-1$
-					String test = result == T_String ? ".equals(" : " != ("; //$NON-NLS-2$ //$NON-NLS-1$
+					String begin = result == T_JavaLangString ? "\t\tif (! " : "\t\tif ( "; //$NON-NLS-2$ //$NON-NLS-1$
+					String test = result == T_JavaLangString ? ".equals(" : " != ("; //$NON-NLS-2$ //$NON-NLS-1$
 					s += begin	+decode.type(result)+"0"+test //$NON-NLS-1$
 								+decode.constant(left)+" " //$NON-NLS-1$
 								+decode.operator(operator)+" " //$NON-NLS-1$
@@ -167,7 +169,7 @@
 
 	public static final int[] get_AND(){
 	
-		//the code is an int
+		//the code is an int, only 20 bits are used, see below.
 		// (cast)  left   Op (cast)  rigth --> result
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
@@ -649,34 +651,34 @@
 		//	table[(T_String<<4)+T_long] 		= T_undefined; 
 		//	table[(T_String<<4)+T_short] 		= T_undefined;
 		//	table[(T_String<<4)+T_void] 		= T_undefined;
-		table[(T_String<<4)+T_String] 		= /*String2Object                 String2Object*/
-											  (T_Object<<16)+(T_String<<12)+(T_Object<<8)+(T_String<<4)+T_boolean;
-		table[(T_String<<4)+T_Object] 		= /*String2Object                 Object2Object*/
-											  (T_Object<<16)+(T_String<<12)+(T_Object<<8)+(T_Object<<4)+T_boolean;
+		table[(T_JavaLangString<<4)+T_JavaLangString] 		= /*String2Object                 String2Object*/
+											  (T_JavaLangObject<<16)+(T_JavaLangString<<12)+(T_JavaLangObject<<8)+(T_JavaLangString<<4)+T_boolean;
+		table[(T_JavaLangString<<4)+T_JavaLangObject] 		= /*String2Object                 Object2Object*/
+											  (T_JavaLangObject<<16)+(T_JavaLangString<<12)+(T_JavaLangObject<<8)+(T_JavaLangObject<<4)+T_boolean;
 		//	table[(T_String<<4)+T_double] 		= T_undefined;
 		//	table[(T_String<<4)+T_float] 		= T_undefined; 
 		//	table[(T_String<<4)+T_boolean] 		= T_undefined;
 		//	table[(T_String<<4)+T_char] 		= T_undefined;
 		//	table[(T_String<<4)+T_int] 			= T_undefined;
-		table[(T_String<<4)+T_null] 		= /*Object2String                null2Object */
-											  (T_Object<<16)+(T_String<<12)+(T_Object<<8)+(T_null<<4)+T_boolean;
+		table[(T_JavaLangString<<4)+T_null] 		= /*Object2String                null2Object */
+											  (T_JavaLangObject<<16)+(T_JavaLangString<<12)+(T_JavaLangObject<<8)+(T_null<<4)+T_boolean;
 	
 		//	table[(T_Object<<4)+T_undefined] 	= T_undefined;
 		//	table[(T_Object<<4)+T_byte] 		= T_undefined;
 		//	table[(T_Object<<4)+T_long] 		= T_undefined;
 		//	table[(T_Object<<4)+T_short]		= T_undefined;
 		//	table[(T_Object<<4)+T_void] 		= T_undefined;
-		table[(T_Object<<4)+T_String] 		= /*Object2Object                 String2Object*/
-											  (T_Object<<16)+(T_Object<<12)+(T_Object<<8)+(T_String<<4)+T_boolean;
-		table[(T_Object<<4)+T_Object] 		= /*Object2Object                 Object2Object*/
-											  (T_Object<<16)+(T_Object<<12)+(T_Object<<8)+(T_Object<<4)+T_boolean;
+		table[(T_JavaLangObject<<4)+T_JavaLangString] 		= /*Object2Object                 String2Object*/
+											  (T_JavaLangObject<<16)+(T_JavaLangObject<<12)+(T_JavaLangObject<<8)+(T_JavaLangString<<4)+T_boolean;
+		table[(T_JavaLangObject<<4)+T_JavaLangObject] 		= /*Object2Object                 Object2Object*/
+											  (T_JavaLangObject<<16)+(T_JavaLangObject<<12)+(T_JavaLangObject<<8)+(T_JavaLangObject<<4)+T_boolean;
 		//	table[(T_Object<<4)+T_double] 		= T_undefined;
 		//	table[(T_Object<<4)+T_float] 		= T_undefined;
 		//	table[(T_Object<<4)+T_boolean]		= T_undefined;
 		//	table[(T_Object<<4)+T_char] 		= T_undefined;
 		//	table[(T_Object<<4)+T_int] 			= T_undefined;
-		table[(T_Object<<4)+T_null] 		= /*Object2Object                 null2Object*/
-											  (T_Object<<16)+(T_Object<<12)+(T_Object<<8)+(T_null<<4)+T_boolean;
+		table[(T_JavaLangObject<<4)+T_null] 		= /*Object2Object                 null2Object*/
+											  (T_JavaLangObject<<16)+(T_JavaLangObject<<12)+(T_JavaLangObject<<8)+(T_null<<4)+T_boolean;
 	
 		//	table[(T_double<<4)+T_undefined] 	= T_undefined;
 		table[(T_double<<4)+T_byte] 		= (Double2Double<<12)+(Byte2Double<<4)+T_boolean;
@@ -753,17 +755,17 @@
 		//	table[(T_null<<4)+T_long] 			= T_undefined;
 		//	table[(T_null<<4)+T_short] 			= T_undefined;
 		//	table[(T_null<<4)+T_void] 			= T_undefined;
-		table[(T_null<<4)+T_String] 		= /*null2Object                 String2Object*/
-											  (T_Object<<16)+(T_null<<12)+(T_Object<<8)+(T_String<<4)+T_boolean;
-		table[(T_null<<4)+T_Object] 		= /*null2Object                 Object2Object*/
-											  (T_Object<<16)+(T_null<<12)+(T_Object<<8)+(T_Object<<4)+T_boolean; 
+		table[(T_null<<4)+T_JavaLangString] 		= /*null2Object                 String2Object*/
+											  (T_JavaLangObject<<16)+(T_null<<12)+(T_JavaLangObject<<8)+(T_JavaLangString<<4)+T_boolean;
+		table[(T_null<<4)+T_JavaLangObject] 		= /*null2Object                 Object2Object*/
+											  (T_JavaLangObject<<16)+(T_null<<12)+(T_JavaLangObject<<8)+(T_JavaLangObject<<4)+T_boolean; 
 		//	table[(T_null<<4)+T_double] 		= T_undefined;
 		//	table[(T_null<<4)+T_float] 			= T_undefined;
 		//	table[(T_null<<4)+T_boolean] 		= T_undefined;
 		//	table[(T_null<<4)+T_char] 			= T_undefined;
 		//	table[(T_null<<4)+T_int] 			= T_undefined;
 		table[(T_null<<4)+T_null] 			= /*null2Object                 null2Object*/
-											  (T_Object<<16)+(T_null<<12)+(T_Object<<8)+(T_null<<4)+T_boolean;
+											  (T_JavaLangObject<<16)+(T_null<<12)+(T_JavaLangObject<<8)+(T_null<<4)+T_boolean;
 		return table;
 	}
 
@@ -1200,30 +1202,30 @@
 		table = (int[]) get_PLUS().clone();
 
 		// customization	
-		table[(T_String<<4)+T_byte] 		= T_undefined;
-		table[(T_String<<4)+T_long] 		= T_undefined;
-		table[(T_String<<4)+T_short] 		= T_undefined;
-		table[(T_String<<4)+T_void] 		= T_undefined;
-		table[(T_String<<4)+T_String] 		= T_undefined;
-		table[(T_String<<4)+T_Object] 		= T_undefined;
-		table[(T_String<<4)+T_double] 		= T_undefined;
-		table[(T_String<<4)+T_float] 		= T_undefined;
-		table[(T_String<<4)+T_boolean] 		= T_undefined;
-		table[(T_String<<4)+T_char] 		= T_undefined;
-		table[(T_String<<4)+T_int] 			= T_undefined;
-		table[(T_String<<4)+T_null] 		= T_undefined;
+		table[(T_JavaLangString<<4)+T_byte] 		= T_undefined;
+		table[(T_JavaLangString<<4)+T_long] 		= T_undefined;
+		table[(T_JavaLangString<<4)+T_short] 		= T_undefined;
+		table[(T_JavaLangString<<4)+T_void] 		= T_undefined;
+		table[(T_JavaLangString<<4)+T_JavaLangString] 		= T_undefined;
+		table[(T_JavaLangString<<4)+T_JavaLangObject] 		= T_undefined;
+		table[(T_JavaLangString<<4)+T_double] 		= T_undefined;
+		table[(T_JavaLangString<<4)+T_float] 		= T_undefined;
+		table[(T_JavaLangString<<4)+T_boolean] 		= T_undefined;
+		table[(T_JavaLangString<<4)+T_char] 		= T_undefined;
+		table[(T_JavaLangString<<4)+T_int] 			= T_undefined;
+		table[(T_JavaLangString<<4)+T_null] 		= T_undefined;
 		
-		table[(T_byte<<4)	+T_String] 		= T_undefined;
-		table[(T_long<<4)	+T_String] 		= T_undefined;
-		table[(T_short<<4)	+T_String] 		= T_undefined;
-		table[(T_void<<4)	+T_String] 		= T_undefined;
-		table[(T_Object<<4)	+T_String] 		= T_undefined;
-		table[(T_double<<4)	+T_String] 		= T_undefined;
-		table[(T_float<<4)	+T_String] 		= T_undefined;
-		table[(T_boolean<<4)+T_String] 		= T_undefined;
-		table[(T_char<<4)	+T_String] 		= T_undefined;
-		table[(T_int<<4)	+T_String] 		= T_undefined;
-		table[(T_null<<4)	+T_String] 		= T_undefined;
+		table[(T_byte<<4)	+T_JavaLangString] 		= T_undefined;
+		table[(T_long<<4)	+T_JavaLangString] 		= T_undefined;
+		table[(T_short<<4)	+T_JavaLangString] 		= T_undefined;
+		table[(T_void<<4)	+T_JavaLangString] 		= T_undefined;
+		table[(T_JavaLangObject<<4)	+T_JavaLangString] 		= T_undefined;
+		table[(T_double<<4)	+T_JavaLangString] 		= T_undefined;
+		table[(T_float<<4)	+T_JavaLangString] 		= T_undefined;
+		table[(T_boolean<<4)+T_JavaLangString] 		= T_undefined;
+		table[(T_char<<4)	+T_JavaLangString] 		= T_undefined;
+		table[(T_int<<4)	+T_JavaLangString] 		= T_undefined;
+		table[(T_null<<4)	+T_JavaLangString] 		= T_undefined;
 		
 		table[(T_null<<4)	+T_null] 		= T_undefined;
 	
@@ -1292,7 +1294,7 @@
 		table[(T_byte<<4)+T_long] 		= (Byte2Long<<12)+(Long2Long<<4)+T_long;
 		table[(T_byte<<4)+T_short] 		= (Byte2Int<<12)+(Short2Int<<4)+T_int;
 		//	table[(T_byte<<4)+T_void] 		= T_undefined;
-		table[(T_byte<<4)+T_String] 	= (Byte2Byte<<12)+(String2String<<4)+T_String;
+		table[(T_byte<<4)+T_JavaLangString] 	= (Byte2Byte<<12)+(String2String<<4)+T_JavaLangString;
 		//	table[(T_byte<<4)+T_Object] 	= T_undefined;
 		table[(T_byte<<4)+T_double] 	= (Byte2Double<<12)+(Double2Double<<4)+T_double;
 		table[(T_byte<<4)+T_float] 		= (Byte2Float<<12)+(Float2Float<<4)+T_float;
@@ -1306,7 +1308,7 @@
 		table[(T_long<<4)+T_long] 		= (Long2Long<<12)+(Long2Long<<4)+T_long;
 		table[(T_long<<4)+T_short] 		= (Long2Long<<12)+(Short2Long<<4)+T_long;
 		//	table[(T_long<<4)+T_void] 		= T_undefined;
-		table[(T_long<<4)+T_String] 	= (Long2Long<<12)+(String2String<<4)+T_String;
+		table[(T_long<<4)+T_JavaLangString] 	= (Long2Long<<12)+(String2String<<4)+T_JavaLangString;
 		//	table[(T_long<<4)+T_Object] 	= T_undefined;
 		table[(T_long<<4)+T_double] 	= (Long2Double<<12)+(Double2Double<<4)+T_double;
 		table[(T_long<<4)+T_float] 		= (Long2Float<<12)+(Float2Float<<4)+T_float;
@@ -1320,7 +1322,7 @@
 		table[(T_short<<4)+T_long] 			= (Short2Long<<12)+(Long2Long<<4)+T_long;
 		table[(T_short<<4)+T_short] 		= (Short2Int<<12)+(Short2Int<<4)+T_int;
 		//	table[(T_short<<4)+T_void] 			= T_undefined;
-		table[(T_short<<4)+T_String] 		= (Short2Short<<12)+(String2String<<4)+T_String;
+		table[(T_short<<4)+T_JavaLangString] 		= (Short2Short<<12)+(String2String<<4)+T_JavaLangString;
 		//	table[(T_short<<4)+T_Object] 		= T_undefined;
 		table[(T_short<<4)+T_double] 		= (Short2Double<<12)+(Double2Double<<4)+T_double;
 		table[(T_short<<4)+T_float] 		= (Short2Float<<12)+(Float2Float<<4)+T_float;
@@ -1344,25 +1346,25 @@
 		//	table[(T_void<<4)+T_null] 		= T_undefined;
 		
 		//	table[(T_String<<4)+T_undefined] 	= T_undefined; 
-		table[(T_String<<4)+T_byte] 		= (String2String<<12)+(Byte2Byte<<4)+T_String;
-		table[(T_String<<4)+T_long] 		= (String2String<<12)+(Long2Long<<4)+T_String; 
-		table[(T_String<<4)+T_short] 		= (String2String<<12)+(Short2Short<<4)+T_String;
+		table[(T_JavaLangString<<4)+T_byte] 		= (String2String<<12)+(Byte2Byte<<4)+T_JavaLangString;
+		table[(T_JavaLangString<<4)+T_long] 		= (String2String<<12)+(Long2Long<<4)+T_JavaLangString; 
+		table[(T_JavaLangString<<4)+T_short] 		= (String2String<<12)+(Short2Short<<4)+T_JavaLangString;
 		//	table[(T_String<<4)+T_void] 		= T_undefined;
-		table[(T_String<<4)+T_String] 		= (String2String<<12)+(String2String<<4)+T_String;
-		table[(T_String<<4)+T_Object] 		= (String2String<<12)+(Object2Object<<4)+T_String;
-		table[(T_String<<4)+T_double] 		= (String2String<<12)+(Double2Double<<4)+T_String;
-		table[(T_String<<4)+T_float] 		= (String2String<<12)+(Float2Float<<4)+T_String; 
-		table[(T_String<<4)+T_boolean] 		= (String2String<<12)+(Boolean2Boolean<<4)+T_String;
-		table[(T_String<<4)+T_char] 		= (String2String<<12)+(Char2Char<<4)+T_String;
-		table[(T_String<<4)+T_int] 			= (String2String<<12)+(Int2Int<<4)+T_String;
-		table[(T_String<<4)+T_null] 		= (String2String<<12)+(T_null<<8)+(T_null<<4)+T_String;
+		table[(T_JavaLangString<<4)+T_JavaLangString] 		= (String2String<<12)+(String2String<<4)+T_JavaLangString;
+		table[(T_JavaLangString<<4)+T_JavaLangObject] 		= (String2String<<12)+(Object2Object<<4)+T_JavaLangString;
+		table[(T_JavaLangString<<4)+T_double] 		= (String2String<<12)+(Double2Double<<4)+T_JavaLangString;
+		table[(T_JavaLangString<<4)+T_float] 		= (String2String<<12)+(Float2Float<<4)+T_JavaLangString; 
+		table[(T_JavaLangString<<4)+T_boolean] 		= (String2String<<12)+(Boolean2Boolean<<4)+T_JavaLangString;
+		table[(T_JavaLangString<<4)+T_char] 		= (String2String<<12)+(Char2Char<<4)+T_JavaLangString;
+		table[(T_JavaLangString<<4)+T_int] 			= (String2String<<12)+(Int2Int<<4)+T_JavaLangString;
+		table[(T_JavaLangString<<4)+T_null] 		= (String2String<<12)+(T_null<<8)+(T_null<<4)+T_JavaLangString;
 	
 		//	table[(T_Object<<4)+T_undefined] 	= T_undefined;
 		//	table[(T_Object<<4)+T_byte] 		= T_undefined;
 		//	table[(T_Object<<4)+T_long] 		= T_undefined;
 		//	table[(T_Object<<4)+T_short]		= T_undefined;
 		//	table[(T_Object<<4)+T_void] 		= T_undefined;
-		table[(T_Object<<4)+T_String] 		= (Object2Object<<12)+(String2String<<4)+T_String;
+		table[(T_JavaLangObject<<4)+T_JavaLangString] 		= (Object2Object<<12)+(String2String<<4)+T_JavaLangString;
 		//	table[(T_Object<<4)+T_Object] 		= T_undefined;
 		//	table[(T_Object<<4)+T_double] 		= T_undefined;
 		//	table[(T_Object<<4)+T_float] 		= T_undefined;
@@ -1376,7 +1378,7 @@
 		table[(T_double<<4)+T_long] 		= (Double2Double<<12)+(Long2Double<<4)+T_double;
 		table[(T_double<<4)+T_short] 		= (Double2Double<<12)+(Short2Double<<4)+T_double; 
 		//	table[(T_double<<4)+T_void] 		= T_undefined;
-		table[(T_double<<4)+T_String] 		= (Double2Double<<12)+(String2String<<4)+T_String;
+		table[(T_double<<4)+T_JavaLangString] 		= (Double2Double<<12)+(String2String<<4)+T_JavaLangString;
 		//	table[(T_double<<4)+T_Object] 		= T_undefined;
 		table[(T_double<<4)+T_double] 		= (Double2Double<<12)+(Double2Double<<4)+T_double;
 		table[(T_double<<4)+T_float] 		= (Double2Double<<12)+(Float2Double<<4)+T_double; 
@@ -1390,7 +1392,7 @@
 		table[(T_float<<4)+T_long] 			= (Float2Float<<12)+(Long2Float<<4)+T_float;
 		table[(T_float<<4)+T_short] 		= (Float2Float<<12)+(Short2Float<<4)+T_float;
 		//	table[(T_float<<4)+T_void] 			= T_undefined;
-		table[(T_float<<4)+T_String] 		= (Float2Float<<12)+(String2String<<4)+T_String;
+		table[(T_float<<4)+T_JavaLangString] 		= (Float2Float<<12)+(String2String<<4)+T_JavaLangString;
 		//	table[(T_float<<4)+T_Object] 		= T_undefined;
 		table[(T_float<<4)+T_double] 		= (Float2Double<<12)+(Double2Double<<4)+T_double;
 		table[(T_float<<4)+T_float] 		= (Float2Float<<12)+(Float2Float<<4)+T_float;
@@ -1404,7 +1406,7 @@
 		//	table[(T_boolean<<4)+T_long] 			= T_undefined;
 		//	table[(T_boolean<<4)+T_short] 			= T_undefined;
 		//	table[(T_boolean<<4)+T_void] 			= T_undefined;
-		table[(T_boolean<<4)+T_String] 			= (Boolean2Boolean<<12)+(String2String<<4)+T_String;
+		table[(T_boolean<<4)+T_JavaLangString] 			= (Boolean2Boolean<<12)+(String2String<<4)+T_JavaLangString;
 		//	table[(T_boolean<<4)+T_Object] 			= T_undefined;
 		//	table[(T_boolean<<4)+T_double] 			= T_undefined;
 		//	table[(T_boolean<<4)+T_float] 			= T_undefined;
@@ -1418,7 +1420,7 @@
 		table[(T_char<<4)+T_long] 			= (Char2Long<<12)+(Long2Long<<4)+T_long;
 		table[(T_char<<4)+T_short] 			= (Char2Int<<12)+(Short2Int<<4)+T_int;
 		//	table[(T_char<<4)+T_void] 			= T_undefined;
-		table[(T_char<<4)+T_String] 		= (Char2Char<<12)+(String2String<<4)+T_String;
+		table[(T_char<<4)+T_JavaLangString] 		= (Char2Char<<12)+(String2String<<4)+T_JavaLangString;
 		//	table[(T_char<<4)+T_Object] 		= T_undefined;
 		table[(T_char<<4)+T_double] 		= (Char2Double<<12)+(Double2Double<<4)+T_double;
 		table[(T_char<<4)+T_float] 			= (Char2Float<<12)+(Float2Float<<4)+T_float;
@@ -1432,7 +1434,7 @@
 		table[(T_int<<4)+T_long] 		= (Int2Long<<12)+(Long2Long<<4)+T_long;
 		table[(T_int<<4)+T_short] 		= (Int2Int<<12)+(Short2Int<<4)+T_int;
 		//	table[(T_int<<4)+T_void] 		= T_undefined;
-		table[(T_int<<4)+T_String] 		= (Int2Int<<12)+(String2String<<4)+T_String;
+		table[(T_int<<4)+T_JavaLangString] 		= (Int2Int<<12)+(String2String<<4)+T_JavaLangString;
 		//	table[(T_int<<4)+T_Object] 		= T_undefined;
 		table[(T_int<<4)+T_double] 		= (Int2Double<<12)+(Double2Double<<4)+T_double;
 		table[(T_int<<4)+T_float] 		= (Int2Float<<12)+(Float2Float<<4)+T_float;
@@ -1446,7 +1448,7 @@
 		//	table[(T_null<<4)+T_long] 			= T_undefined;
 		//	table[(T_null<<4)+T_short] 			= T_undefined;
 		//	table[(T_null<<4)+T_void] 			= T_undefined;
-		table[(T_null<<4)+T_String] 		= (T_null<<16)+(T_null<<12)+(String2String<<4)+T_String;
+		table[(T_null<<4)+T_JavaLangString] 		= (T_null<<16)+(T_null<<12)+(String2String<<4)+T_JavaLangString;
 		//	table[(T_null<<4)+T_Object] 		= T_undefined;
 		//	table[(T_null<<4)+T_double] 		= T_undefined;
 		//	table[(T_null<<4)+T_float] 			= T_undefined;
@@ -1554,6 +1556,10 @@
 		return "unknown operator"; //$NON-NLS-1$
 	}
 
+	public int nullStatus(FlowInfo flowInfo) {
+		return FlowInfo.UNKNOWN;
+	}
+	
 	public StringBuffer printExpression(int indent, StringBuffer output){
 
 		output.append('(');
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java
new file mode 100644
index 0000000..eed5a1f
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java
@@ -0,0 +1,300 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/**
+ * Syntactic representation of a reference to a generic type.
+ * Note that it might also have a dimension.
+ */
+public class ParameterizedQualifiedTypeReference extends ArrayQualifiedTypeReference {
+
+	public TypeReference[][] typeArguments;
+	private boolean didResolve = false;
+
+	/**
+	 * @param tokens
+	 * @param dim
+	 * @param positions
+	 */
+	public ParameterizedQualifiedTypeReference(char[][] tokens, TypeReference[][] typeArguments, int dim, long[] positions) {
+	    
+		super(tokens, dim, positions);
+		this.typeArguments = typeArguments;
+	}
+	public void checkBounds(Scope scope) {
+		if (this.resolvedType == null) return;
+
+		checkBounds(
+			(ReferenceBinding) this.resolvedType.leafComponentType(),
+			scope,
+			this.typeArguments.length - 1);
+	}
+	public void checkBounds(ReferenceBinding type, Scope scope, int index) {
+		if (type.enclosingType() != null)
+			checkBounds(type.enclosingType(), scope, index - 1);
+
+		if (type.isParameterizedType()) {
+			ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) type;
+			ReferenceBinding currentType = parameterizedType.type;
+			TypeVariableBinding[] typeVariables = currentType.typeVariables();
+			TypeBinding[] argTypes = parameterizedType.arguments;
+			if (argTypes != null && typeVariables != null) { // argTypes may be null in error cases
+				for (int i = 0, argLength = typeVariables.length; i < argLength; i++)
+				    if (!typeVariables[i].boundCheck(parameterizedType, argTypes[i]))
+						scope.problemReporter().typeMismatchError(argTypes[i], typeVariables[i], currentType, this.typeArguments[index][i]);
+			}
+		}
+	}
+	public TypeReference copyDims(int dim){
+		//return a type reference copy of me with some dimensions
+		//warning : the new type ref has a null binding
+		this.dimensions = dim;
+		return this;
+	}	
+	
+	/**
+	 * @return char[][]
+	 */
+	public char [][] getParameterizedTypeName(){
+		int length = this.tokens.length;
+		char[][] qParamName = new char[length][];
+		for (int i = 0; i < length; i++) {
+			TypeReference[] arguments = this.typeArguments[i];
+			if (arguments == null) {
+				qParamName[i] = this.tokens[i];
+			} else {
+				StringBuffer buffer = new StringBuffer(5);
+				buffer.append(this.tokens[i]);
+				buffer.append('<');
+				for (int j = 0, argLength =arguments.length; j < argLength; j++) {
+					if (j > 0) buffer.append(',');
+					buffer.append(CharOperation.concatWith(arguments[j].getParameterizedTypeName(), '.'));
+				}
+				buffer.append('>');
+				int nameLength = buffer.length();
+				qParamName[i] = new char[nameLength];
+				buffer.getChars(0, nameLength, qParamName[i], 0);		
+			}
+		}
+		int dim = this.dimensions;
+		if (dim > 0) {
+			char[] dimChars = new char[dim*2];
+			for (int i = 0; i < dim; i++) {
+				int index = i*2;
+				dimChars[index] = '[';
+				dimChars[index+1] = ']';
+			}
+			qParamName[length-1] = CharOperation.concat(qParamName[length-1], dimChars);
+		}
+		return qParamName;
+	}	
+	
+	/* (non-Javadoc)
+     * @see org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope)
+     */
+    protected TypeBinding getTypeBinding(Scope scope) {
+        return null; // not supported here - combined with resolveType(...)
+    }
+    
+    /*
+     * No need to check for reference to raw type per construction
+     */
+	private TypeBinding internalResolveType(Scope scope, boolean checkBounds) {
+
+		// handle the error here
+		this.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
+			return this.resolvedType;
+		} 
+	    this.didResolve = true;
+	    Binding binding = scope.getPackage(this.tokens);
+	    if (binding != null && !binding.isValidBinding()) {
+	    	this.resolvedType = (ReferenceBinding) binding;
+			reportInvalidType(scope);
+			return null;
+		}
+
+	    PackageBinding packageBinding = binding == null ? null : (PackageBinding) binding;
+	    boolean isClassScope = scope.kind == Scope.CLASS_SCOPE;
+		boolean typeIsConsistent = true;
+		ReferenceBinding qualifiedType = null;
+	    for (int i = packageBinding == null ? 0 : packageBinding.compoundName.length, max = this.tokens.length; i < max; i++) {
+			findNextTypeBinding(i, scope, packageBinding);
+			if (!(this.resolvedType.isValidBinding())) {
+				reportInvalidType(scope);
+				return null;
+			}
+			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 (typeIsConsistent && currentType.isStatic() && qualifiedType != null && (qualifiedType.isParameterizedType() || qualifiedType.isGenericType())) {
+				scope.problemReporter().staticMemberOfParameterizedType(this, scope.createParameterizedType((ReferenceBinding)currentType.erasure(), null, qualifiedType));
+				typeIsConsistent = false;
+			}			
+			// check generic and arity
+		    TypeReference[] args = this.typeArguments[i];
+		    if (args != null) {
+				int argLength = args.length;
+				TypeBinding[] argTypes = new TypeBinding[argLength];
+				boolean argHasError = false;
+				for (int j = 0; j < argLength; j++) {
+				    TypeReference arg = args[j];
+				    TypeBinding argType = isClassScope
+						? arg.resolveTypeArgument((ClassScope) scope, currentType, j)
+						: arg.resolveTypeArgument((BlockScope) scope, currentType, j);
+					if (argType == null) {
+						argHasError = true;
+					} else {
+						argTypes[j] = argType;
+					}			    
+				}
+				if (argHasError) return null;
+// TODO (philippe)	if ((this.bits & ASTNode.IsSuperType) != 0)
+				if (isClassScope)
+					if (((ClassScope) scope).detectHierarchyCycle(currentType, this, argTypes))
+						return null;
+
+			    TypeVariableBinding[] typeVariables = currentType.typeVariables();
+				if (typeVariables == NoTypeVariables) { // check generic
+					scope.problemReporter().nonGenericTypeCannotBeParameterized(this, currentType, argTypes);
+					return null;
+				} else if (argLength != typeVariables.length) { // check arity
+					scope.problemReporter().incorrectArityForParameterizedType(this, currentType, argTypes);
+					return null;
+				}
+				// check parameterizing non-static member type of raw type
+				if (typeIsConsistent && !currentType.isStatic() && qualifiedType != null && qualifiedType.isRawType()) {
+					scope.problemReporter().rawMemberTypeCannotBeParameterized(
+							this, scope.environment().createRawType((ReferenceBinding)currentType.erasure(), qualifiedType), argTypes);
+					typeIsConsistent = false;				
+				}
+				ParameterizedTypeBinding parameterizedType = scope.createParameterizedType((ReferenceBinding)currentType.erasure(), argTypes, qualifiedType);
+				// check argument type compatibility
+				if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method resolution
+					for (int j = 0; j < argLength; j++)
+					    if (!typeVariables[j].boundCheck(parameterizedType, argTypes[j]))
+							scope.problemReporter().typeMismatchError(argTypes[j], typeVariables[j], currentType, args[j]);
+				qualifiedType = parameterizedType;
+		    } else {
+// TODO (philippe)	if ((this.bits & ASTNode.IsSuperType) != 0)
+				if (isClassScope)
+					if (((ClassScope) scope).detectHierarchyCycle(currentType, this, null))
+						return null;
+				if (currentType.isGenericType()) {
+	   			    if (typeIsConsistent && qualifiedType != null && qualifiedType.isParameterizedType()) {
+						scope.problemReporter().parameterizedMemberTypeMissingArguments(this, scope.createParameterizedType((ReferenceBinding)currentType.erasure(), null, qualifiedType));
+						typeIsConsistent = false;
+					}
+	   			    qualifiedType = scope.environment().createRawType(currentType, qualifiedType); // raw type
+				} else {
+					qualifiedType = (qualifiedType != null && qualifiedType.isParameterizedType())
+													? scope.createParameterizedType((ReferenceBinding)currentType.erasure(), null, qualifiedType)
+													: currentType;
+				}
+			}
+		}
+		this.resolvedType = qualifiedType;
+		if (isTypeUseDeprecated(this.resolvedType, scope))
+			reportDeprecatedType(scope);
+		// array type ?
+		if (this.dimensions > 0) {
+			if (dimensions > 255)
+				scope.problemReporter().tooManyDimensions(this);
+			this.resolvedType = scope.createArrayType(this.resolvedType, dimensions);
+		}
+		return this.resolvedType;
+	}
+	
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+		int length = tokens.length;
+		for (int i = 0; i < length - 1; i++) {
+			output.append(tokens[i]);
+			TypeReference[] typeArgument = typeArguments[i];
+			if (typeArgument != null) {
+				output.append('<');//$NON-NLS-1$
+				int max = typeArgument.length - 1;
+				for (int j = 0; j < max; j++) {
+					typeArgument[j].print(0, output);
+					output.append(", ");//$NON-NLS-1$
+				}
+				typeArgument[max].print(0, output);
+				output.append('>');
+			}
+			output.append('.');
+		}
+		output.append(tokens[length - 1]);
+		TypeReference[] typeArgument = typeArguments[length - 1];
+		if (typeArgument != null) {
+			output.append('<');//$NON-NLS-1$
+			int max = typeArgument.length - 1;
+			for (int j = 0; j < max; j++) {
+				typeArgument[j].print(0, output);
+				output.append(", ");//$NON-NLS-1$
+			}
+			typeArgument[max].print(0, output);
+			output.append('>');
+		}
+		if ((this.bits & IsVarArgs) != 0) {
+			for (int i= 0 ; i < dimensions - 1; i++) {
+				output.append("[]"); //$NON-NLS-1$
+			}
+			output.append("..."); //$NON-NLS-1$
+		} else {
+			for (int i= 0 ; i < dimensions; i++) {
+				output.append("[]"); //$NON-NLS-1$
+			}
+		}
+		return output;
+	}	
+	
+	public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
+	    return internalResolveType(scope, checkBounds);
+	}	
+	public TypeBinding resolveType(ClassScope scope) {
+	    return internalResolveType(scope, false);
+	}
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		if (visitor.visit(this, scope)) {
+			for (int i = 0, max = this.typeArguments.length; i < max; i++) {
+				if (this.typeArguments[i] != null) {
+					for (int j = 0, max2 = this.typeArguments[i].length; j < max2; j++) {
+						this.typeArguments[i][j].traverse(visitor, scope);
+					}
+				}
+			}
+		}
+		visitor.endVisit(this, scope);
+	}
+	
+	public void traverse(ASTVisitor visitor, ClassScope scope) {
+		if (visitor.visit(this, scope)) {
+			for (int i = 0, max = this.typeArguments.length; i < max; i++) {
+				if (this.typeArguments[i] != null) {
+					for (int j = 0, max2 = this.typeArguments[i].length; j < max2; j++) {
+						this.typeArguments[i][j].traverse(visitor, scope);
+					}
+				}
+			}
+		}
+		visitor.endVisit(this, scope);
+	}
+
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
new file mode 100644
index 0000000..8c4494f
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
@@ -0,0 +1,232 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/**
+ * Syntactic representation of a reference to a generic type.
+ * Note that it might also have a dimension.
+ */
+public class ParameterizedSingleTypeReference extends ArrayTypeReference {
+
+	public TypeReference[] typeArguments;
+	private boolean didResolve = false;
+	
+	public ParameterizedSingleTypeReference(char[] name, TypeReference[] typeArguments, int dim, long pos){
+		super(name, dim, pos);
+		this.originalSourceEnd = this.sourceEnd;
+		this.typeArguments = typeArguments;
+	}
+	public void checkBounds(Scope scope) {
+		if (this.resolvedType == null) return;
+
+		if (this.resolvedType.leafComponentType() instanceof ParameterizedTypeBinding) {
+			ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) this.resolvedType.leafComponentType();
+			ReferenceBinding currentType = parameterizedType.type;
+			TypeVariableBinding[] typeVariables = currentType.typeVariables();
+			TypeBinding[] argTypes = parameterizedType.arguments;
+			if (argTypes != null && typeVariables != null) { // may be null in error cases
+				for (int i = 0, argLength = typeVariables.length; i < argLength; i++)
+					if (!typeVariables[i].boundCheck(parameterizedType, argTypes[i]))
+						scope.problemReporter().typeMismatchError(argTypes[i], typeVariables[i], currentType, this.typeArguments[i]);
+			}
+		}
+	}
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#copyDims(int)
+	 */
+	public TypeReference copyDims(int dim) {
+		this.dimensions = dim;
+		return this;
+	}
+
+	/**
+	 * @return char[][]
+	 */
+	public char [][] getParameterizedTypeName(){
+		StringBuffer buffer = new StringBuffer(5);
+		buffer.append(this.token).append('<');
+		for (int i = 0, length = this.typeArguments.length; i < length; i++) {
+			if (i > 0) buffer.append(',');
+			buffer.append(CharOperation.concatWith(this.typeArguments[i].getParameterizedTypeName(), '.'));
+		}
+		buffer.append('>');
+		int nameLength = buffer.length();
+		char[] name = new char[nameLength];
+		buffer.getChars(0, nameLength, name, 0);
+		int dim = this.dimensions;
+		if (dim > 0) {
+			char[] dimChars = new char[dim*2];
+			for (int i = 0; i < dim; i++) {
+				int index = i*2;
+				dimChars[index] = '[';
+				dimChars[index+1] = ']';
+			}
+			name = CharOperation.concat(name, dimChars);
+		}		
+		return new char[][]{ name };
+	}	
+	/**
+     * @see org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope)
+     */
+    protected TypeBinding getTypeBinding(Scope scope) {
+        return null; // not supported here - combined with resolveType(...)
+    }	
+
+    /*
+     * No need to check for reference to raw type per construction
+     */
+	private TypeBinding internalResolveType(Scope scope, ReferenceBinding enclosingType, boolean checkBounds) {
+
+		// handle the error here
+		this.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
+			return this.resolvedType;
+		} 
+	    this.didResolve = true;
+		if (enclosingType == null) {
+			this.resolvedType = scope.getType(token);
+			if (!(this.resolvedType.isValidBinding())) {
+				reportInvalidType(scope);
+				return null;
+			}
+			enclosingType = this.resolvedType.enclosingType(); // if member type
+			if (enclosingType != null) {
+				ReferenceBinding currentType = (ReferenceBinding) this.resolvedType;
+				if (currentType.isStatic() && (enclosingType.isGenericType() || enclosingType.isParameterizedType())) {
+					enclosingType = scope.environment().createRawType((ReferenceBinding)enclosingType.erasure(), enclosingType.enclosingType());
+				}
+			}
+		} else { // resolving member type (relatively to enclosingType)
+			this.resolvedType = scope.getMemberType(token, (ReferenceBinding)enclosingType.erasure());		    
+			if (!this.resolvedType.isValidBinding()) {
+				scope.problemReporter().invalidEnclosingType(this, this.resolvedType, enclosingType);
+				return null;
+			}
+			if (isTypeUseDeprecated(this.resolvedType, scope))
+				scope.problemReporter().deprecatedType(this.resolvedType, this);
+		}
+
+		// check generic and arity
+	    boolean isClassScope = scope.kind == Scope.CLASS_SCOPE;
+		ReferenceBinding currentType = (ReferenceBinding) this.resolvedType;
+		int argLength = this.typeArguments.length;
+		TypeBinding[] argTypes = new TypeBinding[argLength];
+		boolean argHasError = false;
+		for (int i = 0; i < argLength; i++) {
+		    TypeReference typeArgument = this.typeArguments[i];
+		    TypeBinding argType = isClassScope
+				? typeArgument.resolveTypeArgument((ClassScope) scope, currentType, i)
+				: typeArgument.resolveTypeArgument((BlockScope) scope, currentType, i);
+		     if (argType == null) {
+		         argHasError = true;
+		     } else {
+			    argTypes[i] = argType;
+		     }
+		}
+		if (argHasError) return null;
+// TODO (philippe)	if ((this.bits & ASTNode.IsSuperType) != 0)
+		if (isClassScope)
+			if (((ClassScope) scope).detectHierarchyCycle(currentType, this, argTypes))
+				return null;
+
+		TypeVariableBinding[] typeVariables = currentType.typeVariables();
+		if (typeVariables == NoTypeVariables) { // check generic
+			scope.problemReporter().nonGenericTypeCannotBeParameterized(this, currentType, argTypes);
+			return null;
+		} else if (argLength != typeVariables.length) { // check arity
+			scope.problemReporter().incorrectArityForParameterizedType(this, currentType, argTypes);
+			return null;
+		}
+		// if generic type X<T> is referred to as parameterized X<T>, then answer itself
+		checkGeneric: {
+		    for (int i = 0; i < argLength; i++)
+				if (typeVariables[i] != argTypes[i])
+				    break checkGeneric;
+			return currentType;
+		}
+		ParameterizedTypeBinding parameterizedType = scope.createParameterizedType((ReferenceBinding)currentType.erasure(), argTypes, enclosingType);
+		// check argument type compatibility
+		if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method resolution
+			for (int i = 0; i < argLength; i++)
+			    if (!typeVariables[i].boundCheck(parameterizedType, argTypes[i]))
+					scope.problemReporter().typeMismatchError(argTypes[i], typeVariables[i], currentType, this.typeArguments[i]);
+
+		this.resolvedType = parameterizedType;
+		if (isTypeUseDeprecated(this.resolvedType, scope))
+			reportDeprecatedType(scope);
+		// array type ?
+		if (this.dimensions > 0) {
+			if (dimensions > 255)
+				scope.problemReporter().tooManyDimensions(this);
+			this.resolvedType = scope.createArrayType(parameterizedType, dimensions);
+		}
+		return this.resolvedType;
+	}	
+	
+	public StringBuffer printExpression(int indent, StringBuffer output){
+		output.append(token);
+		output.append("<"); //$NON-NLS-1$
+		int max = typeArguments.length - 1;
+		for (int i= 0; i < max; i++) {
+			typeArguments[i].print(0, output);
+			output.append(", ");//$NON-NLS-1$
+		}
+		typeArguments[max].print(0, output);
+		output.append(">"); //$NON-NLS-1$
+		if ((this.bits & IsVarArgs) != 0) {
+			for (int i= 0 ; i < dimensions - 1; i++) {
+				output.append("[]"); //$NON-NLS-1$
+			}
+			output.append("..."); //$NON-NLS-1$
+		} else {
+			for (int i= 0 ; i < dimensions; i++) {
+				output.append("[]"); //$NON-NLS-1$
+			}
+		}
+		return output;
+	}
+	
+	public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
+	    return internalResolveType(scope, null, checkBounds);
+	}	
+
+	public TypeBinding resolveType(ClassScope scope) {
+	    return internalResolveType(scope, null, false /*no bounds check in classScope*/);
+	}	
+	
+	public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
+	    return internalResolveType(scope, enclosingType, true/*check bounds*/);
+	}
+	
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		if (visitor.visit(this, scope)) {
+			for (int i = 0, max = this.typeArguments.length; i < max; i++) {
+				this.typeArguments[i].traverse(visitor, scope);
+			}
+		}
+		visitor.endVisit(this, scope);
+	}
+	
+	public void traverse(ASTVisitor visitor, ClassScope scope) {
+		if (visitor.visit(this, scope)) {
+			for (int i = 0, max = this.typeArguments.length; i < max; i++) {
+				this.typeArguments[i].traverse(visitor, scope);
+			}
+		}
+		visitor.endVisit(this, scope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
index f236168..289eca2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
@@ -16,7 +16,10 @@
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 /**
- * Variation on allocation, where can be specified an enclosing instance and an anonymous type
+ * Variation on allocation, where can optionally be specified any of:
+ * - leading enclosing instance
+ * - trailing anonymous type
+ * - generic type arguments for generic constructor invocation
  */
 public class QualifiedAllocationExpression extends AllocationExpression {
 	
@@ -31,6 +34,7 @@
 
 	public QualifiedAllocationExpression(TypeDeclaration anonymousType) {
 		this.anonymousType = anonymousType;
+		anonymousType.allocation = this;
 	}
 
 	public FlowInfo analyseCode(
@@ -44,8 +48,9 @@
 		}
 		
 		// check captured variables are initialized in current context (26134)
+		ReferenceBinding allocatedType = this.superTypeBinding == null ? this.binding.declaringClass : this.superTypeBinding;
 		checkCapturedLocalInitializationIfNecessary(
-			this.superTypeBinding == null ? this.binding.declaringClass : this.superTypeBinding, 
+			(ReferenceBinding) allocatedType.erasure(),
 			currentScope, 
 			flowInfo);
 		
@@ -87,14 +92,19 @@
 		boolean valueRequired) {
 
 		int pc = codeStream.position;
-		ReferenceBinding allocatedType = binding.declaringClass;
+		ReferenceBinding allocatedType = this.codegenBinding.declaringClass;
 		codeStream.new_(allocatedType);
 		if (valueRequired) {
 			codeStream.dup();
 		}
 		// better highlight for allocation: display the type individually
-		codeStream.recordPositionsFrom(pc, type.sourceStart);
-
+		if (this.type != null) { // null for enum constant body
+			codeStream.recordPositionsFrom(pc, this.type.sourceStart);
+		} else {
+			// push enum constant name and ordinal
+			codeStream.ldc(String.valueOf(enumConstant.name));
+			codeStream.generateInlinedValue(enumConstant.binding.id);
+		}
 		// handling innerclass instance allocation - enclosing instance arguments
 		if (allocatedType.isNestedType()) {
 			codeStream.generateSyntheticEnclosingInstanceValues(
@@ -104,11 +114,7 @@
 				this);
 		}
 		// generate the arguments for constructor
-		if (arguments != null) {
-			for (int i = 0, count = arguments.length; i < count; i++) {
-				arguments[i].generateCode(currentScope, codeStream, true);
-			}
-		}
+		generateArguments(binding, arguments, currentScope, codeStream);
 		// handling innerclass instance allocation - outer local arguments
 		if (allocatedType.isNestedType()) {
 			codeStream.generateSyntheticOuterArgumentValues(
@@ -119,17 +125,18 @@
 		
 		// invoke constructor
 		if (syntheticAccessor == null) {
-			codeStream.invokespecial(binding);
+			codeStream.invokespecial(this.codegenBinding);
 		} else {
 			// synthetic accessor got some extra arguments appended to its signature, which need values
 			for (int i = 0,
-				max = syntheticAccessor.parameters.length - binding.parameters.length;
+				max = syntheticAccessor.parameters.length - this.codegenBinding.parameters.length;
 				i < max;
 				i++) {
 				codeStream.aconst_null();
 			}
 			codeStream.invokespecial(syntheticAccessor);
 		}
+		codeStream.generateImplicitConversion(this.implicitConversion);
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 
 		if (anonymousType != null) {
@@ -153,17 +160,17 @@
 	public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 
 		if (!flowInfo.isReachable()) return;
-		ReferenceBinding allocatedType;
+		ReferenceBinding allocatedTypeErasure = (ReferenceBinding) binding.declaringClass.erasure();
 
 		// perform some emulation work in case there is some and we are inside a local type only
-		if ((allocatedType = binding.declaringClass).isNestedType()
+		if (allocatedTypeErasure.isNestedType()
 			&& currentScope.enclosingSourceType().isLocalType()) {
 
-			if (allocatedType.isLocalType()) {
-				((LocalTypeBinding) allocatedType).addInnerEmulationDependent(currentScope, enclosingInstance != null);
+			if (allocatedTypeErasure.isLocalType()) {
+				((LocalTypeBinding) allocatedTypeErasure).addInnerEmulationDependent(currentScope, enclosingInstance != null);
 			} else {
 				// locally propagate, since we already now the desired shape for sure
-				currentScope.propagateInnerEmulation(allocatedType, enclosingInstance != null);
+				currentScope.propagateInnerEmulation(allocatedTypeErasure, enclosingInstance != null);
 			}
 		}
 	}
@@ -182,17 +189,14 @@
 	public TypeBinding resolveType(BlockScope scope) {
 
 		// added for code assist...cannot occur with 'normal' code
-		if (anonymousType == null && enclosingInstance == null) {
+		if (this.anonymousType == null && this.enclosingInstance == null) {
 			return super.resolveType(scope);
 		}
 
 		// Propagate the type checking to the arguments, and checks if the constructor is defined.
 		// ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
 		// ClassInstanceCreationExpression ::= Name '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
-		// ==> by construction, when there is an enclosing instance the typename may NOT be qualified
-		// ==> therefore by construction the type is always a SingleTypeReferenceType instead of being either 
-		// sometime a SingleTypeReference and sometime a QualifedTypeReference
-
+		
 		constant = NotAConstant;
 		TypeBinding enclosingInstanceType = null;
 		TypeBinding receiverType = null;
@@ -212,22 +216,42 @@
 					enclosingInstanceType,
 					enclosingInstance);
 				hasError = true;
+			} else if (type instanceof QualifiedTypeReference) {
+				scope.problemReporter().illegalUsageOfQualifiedTypeReference((QualifiedTypeReference)type);
+				hasError = true;
 			} else {
 				receiverType = ((SingleTypeReference) type).resolveTypeEnclosing(scope, (ReferenceBinding) enclosingInstanceType);
 				if (receiverType != null && enclosingInstanceContainsCast) {
-						CastExpression.checkNeedForEnclosingInstanceCast(scope, enclosingInstance, enclosingInstanceType, receiverType);
+					CastExpression.checkNeedForEnclosingInstanceCast(scope, enclosingInstance, enclosingInstanceType, receiverType);
 				}
 			}
 		} else {
-			receiverType = type.resolveType(scope);
+			if (this.type == null) {
+				// initialization of an enum constant
+				receiverType = scope.enclosingSourceType();
+			} else {
+				receiverType = this.type.resolveType(scope, true /* check bounds*/);
+			}			
 		}
 		if (receiverType == null) {
 			hasError = true;
 		} else if (((ReferenceBinding) receiverType).isFinal() && this.anonymousType != null) {
-			scope.problemReporter().anonymousClassCannotExtendFinalClass(type, receiverType);
+			if (!receiverType.isEnum()) {
+				scope.problemReporter().anonymousClassCannotExtendFinalClass(type, receiverType);
+			}
 			hasError = true;
 		}
-
+		// resolve type arguments (for generic constructor call)
+		if (this.typeArguments != null) {
+			int length = this.typeArguments.length;
+			this.genericTypeArguments = new TypeBinding[length];
+			for (int i = 0; i < length; i++) {
+				TypeBinding argType = this.typeArguments[i].resolveType(scope, true /* check bounds*/);
+				if (argType == null) return null; // error already reported
+				this.genericTypeArguments[i] = argType;
+			}
+		}
+		
 		// will check for null after args are resolved
 		TypeBinding[] argumentTypes = NoParameters;
 		if (arguments != null) {
@@ -246,7 +270,6 @@
 		}
 		// limit of fault-tolerance
 		if (hasError) return this.resolvedType = receiverType;
-		
 		if (this.anonymousType == null) {
 			// qualified allocation with no anonymous type
 			ReferenceBinding allocationType = (ReferenceBinding) receiverType;
@@ -258,14 +281,8 @@
 				if (isMethodUseDeprecated(binding, scope)) {
 					scope.problemReporter().deprecatedMethod(this.binding, this);
 				}
-				if (arguments != null) {
-					for (int i = 0; i < arguments.length; i++) {
-						arguments[i].implicitWidening(this.binding.parameters[i], argumentTypes[i]);
-					}
-					if (argsContainCast) {
-						CastExpression.checkNeedForArgumentCasts(scope, null, allocationType, binding, this.arguments, argumentTypes, this);
-					}
-				}
+				if (this.arguments != null)
+					checkInvocationArguments(scope, null, allocationType, binding, this.arguments, argumentTypes, argsContainCast, this);
 			} else {
 				if (this.binding.declaringClass == null) {
 					this.binding.declaringClass = allocationType;
@@ -276,16 +293,21 @@
 
 			// The enclosing instance must be compatible with the innermost enclosing type
 			ReferenceBinding expectedType = this.binding.declaringClass.enclosingType();
-			if (enclosingInstanceType.isCompatibleWith(expectedType)) {
+			if (expectedType != enclosingInstanceType) // must call before computeConversion() and typeMismatchError()
+				scope.compilationUnitScope().recordTypeConversion(expectedType, enclosingInstanceType);
+			if (enclosingInstanceType.isCompatibleWith(expectedType) || scope.isBoxingCompatibleWith(enclosingInstanceType, expectedType)) {
+				enclosingInstance.computeConversion(scope, expectedType, enclosingInstanceType);
 				return receiverType;
 			}
-			scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
-				this.enclosingInstance,
-				enclosingInstanceType,
-				expectedType);
+			scope.problemReporter().typeMismatchError(enclosingInstanceType, expectedType, this.enclosingInstance);
 			return this.resolvedType = receiverType;
 		}
 
+		if (receiverType.isTypeVariable()) {
+			receiverType = new ProblemReferenceBinding(receiverType.sourceName(), (ReferenceBinding)receiverType, ProblemReasons.IllegalSuperTypeVariable);
+			scope.problemReporter().invalidType(this, receiverType);
+			return null;
+		}
 		// anonymous type scenario
 		// an anonymous class inherits from java.lang.Object when declared "after" an interface
 		this.superTypeBinding = receiverType.isInterface() ? scope.getJavaLangObject() : (ReferenceBinding) receiverType;
@@ -293,6 +315,9 @@
 		scope.addAnonymousType(this.anonymousType, (ReferenceBinding) receiverType);
 		this.anonymousType.resolve(scope);		
 		
+		if ((receiverType.tagBits & TagBits.HasDirectWildcard) != 0) {
+			scope.problemReporter().superTypeCannotUseWildcard(anonymousType.binding, this.type, receiverType);
+		}		
 		// find anonymous super constructor
 		MethodBinding inheritedBinding = scope.getConstructor(this.superTypeBinding, argumentTypes, this);
 		if (!inheritedBinding.isValidBinding()) {
@@ -303,27 +328,21 @@
 			return this.resolvedType = anonymousType.binding;
 		}
 		if (enclosingInstance != null) {
-			if (!enclosingInstanceType.isCompatibleWith(inheritedBinding.declaringClass.enclosingType())) {
-				scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
-					enclosingInstance,
-					enclosingInstanceType,
-					inheritedBinding.declaringClass.enclosingType());
+			ReferenceBinding targetEnclosing = inheritedBinding.declaringClass.enclosingType();
+			if (targetEnclosing == null) {
+				scope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, (ReferenceBinding)receiverType);
+				return this.resolvedType = anonymousType.binding;
+			} else if (!enclosingInstanceType.isCompatibleWith(targetEnclosing) && !scope.isBoxingCompatibleWith(enclosingInstanceType, targetEnclosing)) {
+				scope.problemReporter().typeMismatchError(enclosingInstanceType, targetEnclosing, enclosingInstance);
 				return this.resolvedType = anonymousType.binding;
 			}
+			enclosingInstance.computeConversion(scope, targetEnclosing, enclosingInstanceType);
 		}
+		if (this.arguments != null)
+			checkInvocationArguments(scope, null, this.superTypeBinding, inheritedBinding, this.arguments, argumentTypes, argsContainCast, this);
 
-		// this promotion has to be done somewhere: here or inside the constructor of the
-		// anonymous class. We do it here while the constructor of the inner is then easier.
-		if (arguments != null) {
-			for (int i = 0; i < arguments.length; i++) {
-				arguments[i].implicitWidening(inheritedBinding.parameters[i], argumentTypes[i]);
-			}
-			if (argsContainCast) {
-				CastExpression.checkNeedForArgumentCasts(scope, null, this.superTypeBinding, inheritedBinding, this.arguments, argumentTypes, this);
-			}
-		}
 		// Update the anonymous inner class : superclass, interface  
-		binding = anonymousType.createsInternalConstructorWithBinding(inheritedBinding);
+		binding = anonymousType.createDefaultConstructorWithBinding(inheritedBinding);
 		return this.resolvedType = anonymousType.binding; // 1.2 change
 	}
 	
@@ -332,7 +351,13 @@
 		if (visitor.visit(this, scope)) {
 			if (enclosingInstance != null)
 				enclosingInstance.traverse(visitor, scope);
-			type.traverse(visitor, scope);
+			if (this.typeArguments != null) {
+				for (int i = 0, typeArgumentsLength = this.typeArguments.length; i < typeArgumentsLength; i++) {
+					this.typeArguments[i].traverse(visitor, scope);
+				}					
+			}
+			if (this.type != null) // case of enum constant
+				this.type.traverse(visitor, scope);
 			if (arguments != null) {
 				int argumentsLength = arguments.length;
 				for (int i = 0; i < argumentsLength; i++)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
index 8afa15a..154a32b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
@@ -25,9 +25,11 @@
 	public FieldBinding[] otherBindings, otherCodegenBindings;
 	int[] otherDepths;
 	public int indexOfFirstFieldBinding;//points (into tokens) for the first token that corresponds to first FieldBinding
-	SyntheticAccessMethodBinding syntheticWriteAccessor;
-	SyntheticAccessMethodBinding[] syntheticReadAccessors;
-	protected FieldBinding lastFieldBinding;
+	SyntheticMethodBinding syntheticWriteAccessor;
+	SyntheticMethodBinding[] syntheticReadAccessors;
+	public TypeBinding genericCast;
+	public TypeBinding[] otherGenericCasts;
+	
 	public QualifiedNameReference(
 		char[][] sources,
 		long[] positions,
@@ -39,6 +41,7 @@
 		this.sourceStart = sourceStart;
 		this.sourceEnd = sourceEnd;
 	}
+	
 	public FlowInfo analyseAssignment(
 		BlockScope currentScope,
 		FlowContext flowContext,
@@ -49,11 +52,12 @@
 		// determine the rank until which we now we do not need any actual value for the field access
 		int otherBindingsCount = otherBindings == null ? 0 : otherBindings.length;
 		boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic();
+		FieldBinding lastFieldBinding = null;
 		switch (bits & RestrictiveFlagMASK) {
-			case FIELD : // reading a field
+			case Binding.FIELD : // reading a field
 				lastFieldBinding = (FieldBinding) binding;
 				if (needValue) {
-					manageSyntheticReadAccessIfNecessary(currentScope, lastFieldBinding, this.actualReceiverType, 0, flowInfo);
+					manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, this.actualReceiverType, 0, flowInfo);
 				}				// check if final blank field
 				if (lastFieldBinding.isBlankFinal()
 				    && this.otherBindings != null // the last field binding is only assigned
@@ -65,7 +69,7 @@
 					}
 				}
 				break;
-			case LOCAL :
+			case Binding.LOCAL :
 				// first binding is a local variable
 				LocalVariableBinding localBinding;
 				if (!flowInfo
@@ -77,6 +81,7 @@
 				} else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
 					localBinding.useFlag = LocalVariableBinding.FAKE_USED;
 				}
+				this.checkNullStatus(currentScope, flowContext, flowInfo, FlowInfo.NON_NULL);
 		}
 		
 		if (needValue) {
@@ -89,7 +94,7 @@
 				lastFieldBinding = otherBindings[i];
 				needValue = !otherBindings[i+1].isStatic();
 				if (needValue) {
-					manageSyntheticReadAccessIfNecessary(
+					manageSyntheticAccessIfNecessary(
 						currentScope, 
 						lastFieldBinding, 
 						i == 0 
@@ -119,7 +124,7 @@
 			} else {
 				lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
 			}
-			manageSyntheticReadAccessIfNecessary(
+			manageSyntheticAccessIfNecessary(
 				currentScope,
 				lastFieldBinding,
 				lastReceiverType,
@@ -166,7 +171,7 @@
 		} else {
 			lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
 		}
-		manageSyntheticWriteAccessIfNecessary(currentScope, lastFieldBinding, lastReceiverType, flowInfo);
+		manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, lastReceiverType, -1 /*write-access*/, flowInfo);
 
 		return flowInfo;
 	}
@@ -190,9 +195,9 @@
 
 		boolean needValue = otherBindingsCount == 0 ? valueRequired : !this.otherBindings[0].isStatic();
 		switch (bits & RestrictiveFlagMASK) {
-			case FIELD : // reading a field
+			case Binding.FIELD : // reading a field
 				if (needValue) {
-					manageSyntheticReadAccessIfNecessary(currentScope, (FieldBinding) binding, this.actualReceiverType, 0, flowInfo);
+					manageSyntheticAccessIfNecessary(currentScope, (FieldBinding) binding, this.actualReceiverType, 0, flowInfo);
 				}
 				// check if reading a final blank field
 				FieldBinding fieldBinding;
@@ -204,7 +209,7 @@
 					currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
 				}
 				break;
-			case LOCAL : // reading a local variable
+			case Binding.LOCAL : // reading a local variable
 				LocalVariableBinding localBinding;
 				if (!flowInfo
 					.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
@@ -215,6 +220,7 @@
 				} else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
 					localBinding.useFlag = LocalVariableBinding.FAKE_USED;
 				}
+				this.checkNullStatus(currentScope, flowContext, flowInfo, FlowInfo.NON_NULL);
 		}
 		if (needValue) {
 			manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
@@ -224,12 +230,10 @@
 			for (int i = 0; i < otherBindingsCount; i++) {
 				needValue = i < otherBindingsCount-1 ? !otherBindings[i+1].isStatic() : valueRequired;
 				if (needValue) {
-					manageSyntheticReadAccessIfNecessary(
+					manageSyntheticAccessIfNecessary(
 						currentScope, 
 						otherBindings[i], 
-						i == 0 
-							? ((VariableBinding)binding).type
-							: otherBindings[i-1].type,
+						i == 0 	? ((VariableBinding)binding).type : otherBindings[i-1].type,
 						i + 1,
 						flowInfo);
 				}
@@ -252,16 +256,45 @@
 				scope.problemReporter().forwardReference(this, 0, scope.enclosingSourceType());
 		}
 		bits &= ~RestrictiveFlagMASK; // clear bits
-		bits |= FIELD;
+		bits |= Binding.FIELD;
 		return getOtherFieldBindings(scope);
 	}
+	
+	/**
+	 * @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)
+		FieldBinding field = null;
+		int length = this.otherBindings == null ? 0 : this.otherBindings.length;
+		if (length == 0) {
+			if ((this.bits & Binding.FIELD) != 0 && this.binding != null && this.binding.isValidBinding()) {
+				field = (FieldBinding) this.binding;
+			}
+		} else {
+			field  = this.otherBindings[length-1];
+		}
+		if (field != null) {
+			FieldBinding originalBinding = field.original();
+			if (originalBinding != field) {
+			    // extra cast needed if method return type has type variable
+			    if ((originalBinding.type.tagBits & TagBits.HasTypeVariable) != 0 && runtimeTimeType.id != T_JavaLangObject) {
+			    	setGenericCast(length,originalBinding.type.genericCast(scope.boxing(runtimeTimeType))); // runtimeType could be base type in boxing case
+			    }
+			} 	
+		}
+		super.computeConversion(scope, runtimeTimeType, compileTimeType);
+	}
+
 	public void generateAssignment(
 		BlockScope currentScope,
 		CodeStream codeStream,
 		Assignment assignment,
 		boolean valueRequired) {
 			
-		generateReadSequence(currentScope, codeStream);
+		FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
 		assignment.expression.generateCode(currentScope, codeStream, true);
 		fieldStore(codeStream, lastFieldBinding, syntheticWriteAccessor, valueRequired);
 		// equivalent to valuesRequired[maxOtherBindings]
@@ -280,21 +313,21 @@
 				codeStream.generateConstant(constant, implicitConversion);
 			}
 		} else {
-			generateReadSequence(currentScope, codeStream); 
+			FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); 
 			if (valueRequired) {
 				if (lastFieldBinding.declaringClass == null) { // array length
 					codeStream.arraylength();
 					codeStream.generateImplicitConversion(implicitConversion);
 				} else {
-					if (lastFieldBinding.constant != NotAConstant) {
+					if (lastFieldBinding.isConstantValue()) {
 						if (!lastFieldBinding.isStatic()){
 							codeStream.invokeObjectGetClass();
 							codeStream.pop();
 						}
 						// inline the last field constant
-						codeStream.generateConstant(lastFieldBinding.constant, implicitConversion);
+						codeStream.generateConstant(lastFieldBinding.constant(), implicitConversion);
 					} else {
-						SyntheticAccessMethodBinding accessor =
+						SyntheticMethodBinding accessor =
 							syntheticReadAccessors == null
 								? null
 								: syntheticReadAccessors[syntheticReadAccessors.length - 1];
@@ -307,6 +340,8 @@
 						} else {
 							codeStream.invokestatic(accessor);
 						}
+						TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
+						if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast);
 						codeStream.generateImplicitConversion(implicitConversion);
 					}
 				}
@@ -328,8 +363,8 @@
 		int assignmentImplicitConversion,
 		boolean valueRequired) {
 			
-		generateReadSequence(currentScope, codeStream);
-		SyntheticAccessMethodBinding accessor =
+		FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
+		SyntheticMethodBinding accessor =
 			syntheticReadAccessors == null
 				? null
 				: syntheticReadAccessors[syntheticReadAccessors.length - 1];
@@ -350,21 +385,25 @@
 		// the last field access is a write access
 		// perform the actual compound operation
 		int operationTypeID;
-		if ((operationTypeID = implicitConversion >> 4) == T_String) {
-			codeStream.generateStringAppend(currentScope, null, expression);
-		} else {
-			// promote the array reference to the suitable operation type
-			codeStream.generateImplicitConversion(implicitConversion);
-			// generate the increment value (will by itself  be promoted to the operation value)
-			if (expression == IntLiteral.One) { // prefix operation
-				codeStream.generateConstant(expression.constant, implicitConversion);
-			} 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);
+		switch(operationTypeID = (implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
+			case T_JavaLangString :
+			case T_JavaLangObject :
+			case T_undefined :
+				codeStream.generateStringConcatenationAppend(currentScope, null, expression);
+				break;
+			default :
+				// 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);
 		}
 		// actual assignment
 		fieldStore(codeStream, lastFieldBinding, syntheticWriteAccessor, valueRequired);
@@ -375,8 +414,9 @@
 		CodeStream codeStream,
 		CompoundAssignment postIncrement,
 		boolean valueRequired) {
-		generateReadSequence(currentScope, codeStream);
-		SyntheticAccessMethodBinding accessor =
+	    
+		FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
+		SyntheticMethodBinding accessor =
 			syntheticReadAccessors == null
 				? null
 				: syntheticReadAccessors[syntheticReadAccessors.length - 1];
@@ -412,10 +452,11 @@
 				}
 			}
 		}
+		codeStream.generateImplicitConversion(implicitConversion);		
 		codeStream.generateConstant(
 			postIncrement.expression.constant,
 			implicitConversion);
-		codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id);
+		codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
 		codeStream.generateImplicitConversion(
 			postIncrement.assignmentImplicitConversion);
 		fieldStore(codeStream, lastFieldBinding, syntheticWriteAccessor, false);
@@ -424,19 +465,20 @@
 	 * Generate code for all bindings (local and fields) excluding the last one, which may then be generated code
 	 * for a read or write access.
 	 */
-	public void generateReadSequence(
-		BlockScope currentScope,
-		CodeStream codeStream) {
+	public FieldBinding generateReadSequence(BlockScope currentScope, CodeStream codeStream) {
 			
 		// determine the rank until which we now we do not need any actual value for the field access
 		int otherBindingsCount = this.otherCodegenBindings == null ? 0 : otherCodegenBindings.length;
-
 		boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic();
+		FieldBinding lastFieldBinding = null;
+		TypeBinding lastGenericCast = null;
+
 		switch (bits & RestrictiveFlagMASK) {
-			case FIELD :
+			case Binding.FIELD :
 				lastFieldBinding = (FieldBinding) this.codegenBinding;
+				lastGenericCast = this.genericCast;
 				// if first field is actually constant, we can inline it
-				if (lastFieldBinding.constant != NotAConstant) {
+				if (lastFieldBinding.isConstantValue()) {
 					break;
 				}
 				if (needValue && !lastFieldBinding.isStatic()) {
@@ -449,13 +491,12 @@
 					}
 				}
 				break;
-			case LOCAL : // reading the first local variable
-				lastFieldBinding = null;
+			case Binding.LOCAL : // reading the first local variable
 				if (!needValue) break; // no value needed
 				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 				// regular local variable read
-				if (localBinding.constant != NotAConstant) {
-					codeStream.generateConstant(localBinding.constant, 0);
+				if (localBinding.isConstantValue()) {
+					codeStream.generateConstant(localBinding.constant(), 0);
 					// no implicit conversion
 				} else {
 					// outer local?
@@ -468,24 +509,25 @@
 					}
 				}
 		}
-
+						
 		// all intermediate field accesses are read accesses
 		// only the last field binding is a write access
 		if (this.otherCodegenBindings != null) {
 			for (int i = 0; i < otherBindingsCount; i++) {
 				FieldBinding nextField = this.otherCodegenBindings[i];
+				TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i];
 				if (lastFieldBinding != null) {
 					needValue = !nextField.isStatic();
 					if (needValue) {
 						MethodBinding accessor =
 							syntheticReadAccessors == null ? null : syntheticReadAccessors[i]; 
 						if (accessor == null) {
-							if (lastFieldBinding.constant != NotAConstant) {
-								if (this.lastFieldBinding != this.codegenBinding && !this.lastFieldBinding.isStatic()) {
+							if (lastFieldBinding.isConstantValue()) {
+								if (lastFieldBinding != this.codegenBinding && !lastFieldBinding.isStatic()) {
 									codeStream.invokeObjectGetClass(); // perform null check
 									codeStream.pop();
 								}
-								codeStream.generateConstant(lastFieldBinding.constant, 0);
+								codeStream.generateConstant(lastFieldBinding.constant(), 0);
 							} else if (lastFieldBinding.isStatic()) {
 								codeStream.getstatic(lastFieldBinding);
 							} else {
@@ -494,42 +536,75 @@
 						} else {
 							codeStream.invokestatic(accessor);
 						}
+						if (lastGenericCast != null) codeStream.checkcast(lastGenericCast);
 					} else {
-						if (this.codegenBinding != this.lastFieldBinding && !this.lastFieldBinding.isStatic()){
+						if (this.codegenBinding != lastFieldBinding && !lastFieldBinding.isStatic()){
 							codeStream.invokeObjectGetClass(); // perform null check
 							codeStream.pop();
 						}						
 					}
 				}
-				this.lastFieldBinding = nextField;
+				lastFieldBinding = nextField;
+				lastGenericCast = nextGenericCast;
 			}
 		}
+		return lastFieldBinding;
 	}
 	public void generateReceiver(CodeStream codeStream) {
 		codeStream.aload_0();
 	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+	 */
+	public TypeBinding[] genericTypeArguments() {
+		return null;
+	}
+	
+	// get the matching codegenBinding
+	protected FieldBinding getCodegenBinding(int index) {
+	  if (index == 0){
+			return (FieldBinding)this.codegenBinding;
+		} else {
+			return this.otherCodegenBindings[index-1];
+		}
+	}
+
+	// get the matching generic cast
+	protected TypeBinding getGenericCast(int index) {
+	   if (index == 0){
+			return this.genericCast;
+		} else {
+		    if (this.otherGenericCasts == null) return null;
+			return this.otherGenericCasts[index-1];
+		}
+	}
+	
 	public TypeBinding getOtherFieldBindings(BlockScope scope) {
 		// At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid)
 		int length = tokens.length;
-		if ((bits & FIELD) != 0) {
-			FieldBinding fieldBinding = (FieldBinding) binding;
-			if (!fieldBinding.isStatic()) {
+		FieldBinding field;
+		if ((bits & Binding.FIELD) != 0) {
+			field = (FieldBinding) this.binding;
+			if (!field.isStatic()) {
 				//must check for the static status....
 				if (indexOfFirstFieldBinding > 1  //accessing to a field using a type as "receiver" is allowed only with static field
 						 || scope.methodScope().isStatic) { 	// the field is the first token of the qualified reference....
-					scope.problemReporter().staticFieldAccessToNonStaticVariable(this, fieldBinding);
+					scope.problemReporter().staticFieldAccessToNonStaticVariable(this, field);
 					return null;
 				 }
 			} else {
 				// indirect static reference ?
 				if (indexOfFirstFieldBinding > 1 
-						&& fieldBinding.declaringClass != actualReceiverType) {
-					scope.problemReporter().indirectAccessToStaticField(this, fieldBinding);
+						&& field.declaringClass != actualReceiverType) {
+					scope.problemReporter().indirectAccessToStaticField(this, field);
 				}
 			}
 			// only last field is actually a write access if any
-			if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssignedMASK) !=0 && indexOfFirstFieldBinding == length))
-				scope.problemReporter().deprecatedField(fieldBinding, this);
+			if (isFieldUseDeprecated(field, scope, (this.bits & IsStrictlyAssignedMASK) !=0 && indexOfFirstFieldBinding == length))
+				scope.problemReporter().deprecatedField(field, this);
+		} else {
+			field = null;
 		}
 		TypeBinding type = ((VariableBinding) binding).type;
 		int index = indexOfFirstFieldBinding;
@@ -543,10 +618,9 @@
 		otherDepths = new int[otherBindingsLength];
 		
 		// fill the first constant (the one of the binding)
-		this.constant =
-			((bits & FIELD) != 0)
+		this.constant = field != null
 				? FieldReference.getConstantFor((FieldBinding) binding, this, false, scope)
-				: ((VariableBinding) binding).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	
@@ -555,8 +629,18 @@
 			if (type == null)
 				return null; // could not resolve type prior to this point
 
+			// set generic cast of for previous field (if any)
+			if (field != null) {
+				FieldBinding originalBinding = field.original();
+				if (originalBinding != field) {
+				    // extra cast needed if method return type has type variable
+				    if ((originalBinding.type.tagBits & TagBits.HasTypeVariable) != 0 && type.id != T_JavaLangObject) {
+				    	setGenericCast(index-1,originalBinding.type.genericCast(type)); // type cannot be base-type even in boxing case
+				    }
+				} 	
+			}
 			bits &= ~DepthMASK; // flush previous depth if any			
-			FieldBinding field = scope.getField(type, token, this);
+			field = scope.getField(type, token, this);
 			int place = index - indexOfFirstFieldBinding;
 			otherBindings[place] = field;
 			otherDepths[place] = (bits & DepthMASK) >> DepthSHIFT;
@@ -597,124 +681,72 @@
 		if (((bits & DepthMASK) == 0) || (constant != NotAConstant)) {
 			return;
 		}
-		if ((bits & RestrictiveFlagMASK) == LOCAL) {
+		if ((bits & RestrictiveFlagMASK) == Binding.LOCAL) {
 			currentScope.emulateOuterAccess((LocalVariableBinding) binding);
 		}
 	}
-	public void manageSyntheticReadAccessIfNecessary(
+	/**
+	 * index is <0 to denote write access emulation
+	 */
+	public void manageSyntheticAccessIfNecessary(
 			BlockScope currentScope,
 			FieldBinding fieldBinding,
 			TypeBinding lastReceiverType,
 			int index,
 			FlowInfo flowInfo) {
+	    
 		if (!flowInfo.isReachable()) return;
-		// index == 0 denotes the first fieldBinding, index > 0 denotes one of the 'otherBindings'
-		if (fieldBinding.constant != NotAConstant)
+		// 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())
 			return;
-		if (fieldBinding.isPrivate()) { // private access
-			if (fieldBinding.declaringClass != currentScope.enclosingSourceType()) {
-				if (syntheticReadAccessors == null) {
-					if (otherBindings == null)
-						syntheticReadAccessors = new SyntheticAccessMethodBinding[1];
-					else
-						syntheticReadAccessors =
-							new SyntheticAccessMethodBinding[otherBindings.length + 1];
-				}
-				syntheticReadAccessors[index] = ((SourceTypeBinding) fieldBinding.declaringClass).addSyntheticMethod(fieldBinding, true);
-				currentScope.problemReporter().needToEmulateFieldReadAccess(fieldBinding, this);
-				return;
-			}
-		} else if (fieldBinding.isProtected()){
-			int depth = index == 0 ? (bits & DepthMASK) >> DepthSHIFT : otherDepths[index-1];
-			// implicit protected access (only for first one)
-			if (depth > 0 && (fieldBinding.declaringClass.getPackage()
-								!= currentScope.enclosingSourceType().getPackage())) {
-				if (syntheticReadAccessors == null) {
-					if (otherBindings == null)
-						syntheticReadAccessors = new SyntheticAccessMethodBinding[1];
-					else
-						syntheticReadAccessors =
-							new SyntheticAccessMethodBinding[otherBindings.length + 1];
-				}
-				syntheticReadAccessors[index] =
-					((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth))
-											.addSyntheticMethod(fieldBinding, true);
-				currentScope.problemReporter().needToEmulateFieldReadAccess(fieldBinding, this);
-				return;
-			}
-		}
-		// if the binding declaring class is not visible, need special action
-		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
-		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
-		if (fieldBinding.declaringClass != lastReceiverType
-			&& !lastReceiverType.isArrayType()			
-			&& fieldBinding.declaringClass != null
-			&& fieldBinding.constant == NotAConstant
-			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
-					&& (index > 0 || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
-					&& fieldBinding.declaringClass.id != T_Object)
-				|| !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
-			if (index == 0){
-				this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
-			} else {
-				if (this.otherCodegenBindings == this.otherBindings){
-					int l = this.otherBindings.length;
-					System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l);
-				}
-				this.otherCodegenBindings[index-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
-			}
-		}
-	}
-	/*
-	 * No need to emulate access to protected fields since not implicitly accessed
-	 */
-	public void manageSyntheticWriteAccessIfNecessary(
-			BlockScope currentScope,
-			FieldBinding fieldBinding,
-			TypeBinding lastReceiverType,
-			FlowInfo flowInfo) {
-		if (!flowInfo.isReachable()) return;
-		if (fieldBinding.isPrivate()) {
-			if (fieldBinding.declaringClass != currentScope.enclosingSourceType()) {
-				syntheticWriteAccessor = ((SourceTypeBinding) fieldBinding.declaringClass)
-											.addSyntheticMethod(fieldBinding, false);
-				currentScope.problemReporter().needToEmulateFieldWriteAccess(fieldBinding, this);
-				return;
-			}
-		} else if (fieldBinding.isProtected()){
-			int depth = fieldBinding == binding ? (bits & DepthMASK) >> DepthSHIFT : otherDepths[otherDepths.length-1];
-			if (depth > 0 && (fieldBinding.declaringClass.getPackage()
-								!= currentScope.enclosingSourceType().getPackage())) {
-				syntheticWriteAccessor = ((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth))
-											.addSyntheticMethod(fieldBinding, false);
-				currentScope.problemReporter().needToEmulateFieldWriteAccess(fieldBinding, this);
-				return;
-			}
-		}
-		// if the binding declaring class is not visible, need special action
-		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
-		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
-		if (fieldBinding.declaringClass != lastReceiverType
-			&& !lastReceiverType.isArrayType()			
-			&& fieldBinding.declaringClass != null
-			&& fieldBinding.constant == NotAConstant
-			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
-					&& (fieldBinding != binding || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
-					&& fieldBinding.declaringClass.id != T_Object)
-				|| !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
-			if (fieldBinding == binding){
-				this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
-			} else {
-				if (this.otherCodegenBindings == this.otherBindings){
-					int l = this.otherBindings.length;
-					System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l);
-				}
-				this.otherCodegenBindings[this.otherCodegenBindings.length-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
-			}
+
+		// if field from parameterized type got found, use the original field at codegen time
+		FieldBinding originalField = fieldBinding.original();
+		if (originalField != fieldBinding) {
+			setCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index, originalField);
 		}
 		
+		if (fieldBinding.isPrivate()) { // private access
+		    FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index);
+			if (someCodegenBinding.declaringClass != currentScope.enclosingSourceType()) {
+			    setSyntheticAccessor(fieldBinding, index, 
+			            ((SourceTypeBinding) someCodegenBinding.declaringClass).addSyntheticMethod(someCodegenBinding, index >= 0 /*read-access?*/));
+				currentScope.problemReporter().needToEmulateFieldAccess(someCodegenBinding, this, index >= 0 /*read-access?*/);
+				return;
+			}
+		} else if (fieldBinding.isProtected()){
+		    int depth = fieldBinding == binding 
+		    		? (bits & DepthMASK) >> DepthSHIFT 
+		    		 : otherDepths[index < 0 ? otherDepths.length-1 : index-1];
+			
+			// implicit protected access 
+			if (depth > 0 && (fieldBinding.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage())) {
+			    FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index);
+			    setSyntheticAccessor(fieldBinding, index, 
+			            ((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth)).addSyntheticMethod(someCodegenBinding, index >= 0 /*read-access?*/));
+				currentScope.problemReporter().needToEmulateFieldAccess(someCodegenBinding, this, index >= 0 /*read-access?*/);
+				return;
+			}
+		}
+		// if the binding declaring class is not visible, need special action
+		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
+		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
+		if (fieldBinding.declaringClass != lastReceiverType
+			&& !lastReceiverType.isArrayType()			
+			&& fieldBinding.declaringClass != null
+			&& !fieldBinding.isConstantValue()
+			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
+					&& (fieldBinding != binding || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
+					&& fieldBinding.declaringClass.id != T_JavaLangObject)
+				|| !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
+		    setCodegenBinding(
+		            index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index, 
+		            currentScope.enclosingSourceType().getUpdatedFieldBinding(
+		                    getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index), 
+		                    (ReferenceBinding)lastReceiverType.erasure()));
+		}
 	}
-	
+
 	public StringBuffer printExpression(int indent, StringBuffer output) {
 		
 		for (int i = 0; i < tokens.length; i++) {
@@ -741,19 +773,19 @@
 		// 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 = this.receiverType = scope.enclosingSourceType();
+		this.actualReceiverType = scope.enclosingSourceType();
 		constant = Constant.NotAConstant;
 		if ((this.codegenBinding = this.binding = scope.getBinding(tokens, bits & RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) {
 			switch (bits & RestrictiveFlagMASK) {
-				case VARIABLE : //============only variable===========
-				case TYPE | VARIABLE :
+				case Binding.VARIABLE : //============only variable===========
+				case Binding.TYPE | Binding.VARIABLE :
 					if (binding instanceof LocalVariableBinding) {
 						if (!((LocalVariableBinding) binding).isFinal() && ((bits & DepthMASK) != 0))
 							scope.problemReporter().cannotReferToNonFinalOuterLocal(
 								(LocalVariableBinding) binding,
 								this);
 						bits &= ~RestrictiveFlagMASK; // clear bits
-						bits |= LOCAL;
+						bits |= Binding.LOCAL;
 						return this.resolvedType = getOtherFieldBindings(scope);
 					}
 					if (binding instanceof FieldBinding) {
@@ -774,7 +806,7 @@
 							scope.problemReporter().unqualifiedFieldAccess(this, fieldBinding);
 						}
 						bits &= ~RestrictiveFlagMASK; // clear bits
-						bits |= FIELD;
+						bits |= Binding.FIELD;
 						
 						// check for deprecated receiver type
 						// deprecation check for receiver type if not first token
@@ -787,16 +819,56 @@
 					}
 					// thus it was a type
 					bits &= ~RestrictiveFlagMASK; // clear bits
-					bits |= TYPE;
-				case TYPE : //=============only type ==============
-					if (isTypeUseDeprecated((TypeBinding) binding, scope))
-						scope.problemReporter().deprecatedType((TypeBinding) binding, this);
-					return this.resolvedType = (TypeBinding) binding;
+					bits |= Binding.TYPE;
+				case Binding.TYPE : //=============only type ==============
+				    TypeBinding type = (TypeBinding) binding;
+					if (isTypeUseDeprecated(type, scope))
+						scope.problemReporter().deprecatedType(type, this);
+					return this.resolvedType = scope.convertToRawType(type);
 			}
 		}
 		//========error cases===============
 		return this.resolvedType = this.reportError(scope);
 	}
+
+	// set the matching codegenBinding and generic cast
+	protected void setCodegenBinding(int index, FieldBinding someCodegenBinding) {
+
+		if (index == 0){
+			this.codegenBinding = someCodegenBinding;
+		} else {
+		    int length = this.otherBindings.length;
+			if (this.otherCodegenBindings == this.otherBindings){
+				System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[length], 0, length);
+			}
+			this.otherCodegenBindings[index-1] = someCodegenBinding;
+		}	    
+	}
+
+	// set the matching codegenBinding and generic cast
+	protected void setGenericCast(int index, TypeBinding someGenericCast) {
+
+		if (index == 0){
+			this.genericCast = someGenericCast;
+		} else {
+		    if (this.otherGenericCasts == null) {
+		        this.otherGenericCasts = new TypeBinding[this.otherBindings.length];
+		    }
+		    this.otherGenericCasts[index-1] = someGenericCast;
+		}	    
+	}
+	
+	// set the matching synthetic accessor
+	protected void setSyntheticAccessor(FieldBinding fieldBinding, int index, SyntheticMethodBinding syntheticAccessor) {
+		if (index < 0) { // write-access ?
+			syntheticWriteAccessor = syntheticAccessor;
+	    } else {
+			if (syntheticReadAccessors == null) {
+				syntheticReadAccessors = new SyntheticMethodBinding[otherBindings == null ? 1 : otherBindings.length + 1];
+			}
+			syntheticReadAccessors[index] = syntheticAccessor;
+	    }
+	}
 	
 	public void setFieldIndex(int index) {
 		this.indexOfFirstFieldBinding = index;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java
index 592c433..67e95fc 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java
@@ -44,7 +44,7 @@
 		if (currentCompatibleType == null)
 			return null; // error case
 
-		if (currentCompatibleType.id == T_Object) {
+		if (currentCompatibleType.id == T_JavaLangObject) {
 			scope.problemReporter().cannotUseSuperInJavaLangObject(this);
 			return null;
 		}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java
index 93e4c1c..9dcbb4c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java
@@ -72,15 +72,19 @@
 	public TypeBinding resolveType(BlockScope scope) {
 
 		constant = NotAConstant;
-		this.resolvedType = this.qualification.resolveType(scope);
-		if (this.resolvedType == null) return null;
-
+		TypeBinding type = this.resolvedType = this.qualification.resolveType(scope, true /* check bounds*/);
+		if (type == null) return null;
+		// X.this is not a raw type as denoting enclosing instance
+		if (type.isRawType()) {
+		    RawTypeBinding rawType = (RawTypeBinding) type;
+		    type = this.resolvedType = rawType.type; // unwrap
+		}
 		// the qualification MUST exactly match some enclosing type name
 		// Its possible to qualify 'this' by the name of the current class
 		int depth = 0;
 		this.currentCompatibleType = scope.referenceType().binding;
 		while (this.currentCompatibleType != null
-			&& this.currentCompatibleType != this.resolvedType) {
+			&& this.currentCompatibleType != type) {
 			depth++;
 			this.currentCompatibleType = this.currentCompatibleType.isStatic() ? null : this.currentCompatibleType.enclosingType();
 		}
@@ -88,15 +92,15 @@
 		bits |= (depth & 0xFF) << DepthSHIFT; // encoded depth into 8 bits
 
 		if (this.currentCompatibleType == null) {
-			scope.problemReporter().noSuchEnclosingInstance(this.resolvedType, this, false);
-			return this.resolvedType;
+			scope.problemReporter().noSuchEnclosingInstance(type, this, false);
+			return type;
 		}
 
 		// Ensure one cannot write code like: B() { super(B.this); }
 		if (depth == 0) {
 			checkAccess(scope.methodScope());
 		} // if depth>0, path emulation will diagnose bad scenarii
-		return this.resolvedType;
+		return type;
 	}
 
 	public StringBuffer printExpression(int indent, StringBuffer output) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
index b37276b..d3518a0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 
 public class QualifiedTypeReference extends TypeReference {
 
@@ -25,24 +26,65 @@
 		sourceStart = (int) (sourcePositions[0]>>>32) ;
 		sourceEnd = (int)(sourcePositions[sourcePositions.length-1] & 0x00000000FFFFFFFFL ) ;
 	}
-	
-	public QualifiedTypeReference(char[][] sources , TypeBinding type , long[] poss) {
 		
-		this(sources,poss);
-		this.resolvedType = type;
-	}
-	
 	public TypeReference copyDims(int dim){
 		//return a type reference copy of me with some dimensions
 		//warning : the new type ref has a null binding
-		return new ArrayQualifiedTypeReference(tokens,null,dim,sourcePositions) ;
+		return new ArrayQualifiedTypeReference(tokens, dim, sourcePositions);
 	}
-	
-	public TypeBinding getTypeBinding(Scope scope) {
+
+	protected TypeBinding findNextTypeBinding(int tokenIndex, Scope scope, PackageBinding packageBinding) {
+		try {
+		    if (this.resolvedType == null) {
+				this.resolvedType = scope.getType(this.tokens[tokenIndex], packageBinding);
+		    } else {
+			    this.resolvedType = scope.getMemberType(this.tokens[tokenIndex], (ReferenceBinding) this.resolvedType);
+				if (this.resolvedType instanceof ProblemReferenceBinding) {
+					ProblemReferenceBinding problemBinding = (ProblemReferenceBinding) this.resolvedType;
+					this.resolvedType = new ProblemReferenceBinding(
+						org.eclipse.jdt.core.compiler.CharOperation.subarray(this.tokens, 0, tokenIndex + 1),
+						problemBinding.original,
+						this.resolvedType.problemId());
+				}
+			}
+		    return this.resolvedType;
+		} catch (AbortCompilation e) {
+			e.updateContext(this, scope.referenceCompilationUnit().compilationResult);
+			throw e;
+		}
+	}
+
+	protected TypeBinding getTypeBinding(Scope scope) {
 		
 		if (this.resolvedType != null)
 			return this.resolvedType;
-		return scope.getType(tokens);
+
+		Binding binding = scope.getPackage(this.tokens);
+		if (binding != null && !binding.isValidBinding())
+			return (ReferenceBinding) binding; // not found
+
+	    PackageBinding packageBinding = binding == null ? null : (PackageBinding) binding;
+	    boolean isClassScope = scope.kind == Scope.CLASS_SCOPE;
+	    ReferenceBinding qualifiedType = null;
+		for (int i = packageBinding == null ? 0 : packageBinding.compoundName.length, max = this.tokens.length; i < max; i++) {
+			findNextTypeBinding(i, scope, packageBinding);
+			if (!this.resolvedType.isValidBinding())
+				return this.resolvedType;
+			
+			if (isClassScope)
+				if (((ClassScope) scope).detectHierarchyCycle(this.resolvedType, this, null)) // must connect hierarchy to find inherited member types
+					return null;
+			ReferenceBinding currentType = (ReferenceBinding) this.resolvedType;
+			if (currentType.isGenericType()) {
+				qualifiedType = scope.environment().createRawType(currentType, qualifiedType);
+			} else {
+				qualifiedType = (qualifiedType != null && (qualifiedType.isRawType() || qualifiedType.isParameterizedType()))
+										? scope.createParameterizedType((ReferenceBinding)currentType.erasure(), null, qualifiedType)
+										: currentType;
+			}
+		}
+		this.resolvedType = qualifiedType;
+		return this.resolvedType;
 	}
 	
 	public char[][] getTypeName(){
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java
index 41d498b..5a62bb6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java
@@ -67,4 +67,19 @@
 
 public abstract void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired);
 
+public int nullStatus(FlowInfo flowInfo) {
+
+	if (this.constant != null && this.constant != NotAConstant)
+		return FlowInfo.NON_NULL; // constant expression cannot be null
+	
+	LocalVariableBinding local = localVariableBinding();
+	if (local != null) {
+		if (flowInfo.isDefinitelyNull(local))
+			return FlowInfo.NULL;
+		if (flowInfo.isDefinitelyNonNull(local))
+			return FlowInfo.NON_NULL;
+	}	
+	return FlowInfo.UNKNOWN;
+}
+
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
index ca74dae..74b3192 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
@@ -18,7 +18,6 @@
 public class ReturnStatement extends Statement {
 		
 	public Expression expression;
-	public TypeBinding expressionType;
 	public boolean isSynchronized;
 	public SubRoutineStatement[] subroutines;
 	public boolean isAnySubRoutineEscaping = false;
@@ -92,7 +91,7 @@
 			}
 		} else {
 			this.saveValueVariable = null;
-			if ((!isSynchronized) && (expressionType == BooleanBinding)) {
+			if (!isSynchronized && this.expression != null && this.expression.resolvedType == BooleanBinding) {
 				this.expression.bits |= ValueForReturnMASK;
 			}
 		}
@@ -151,7 +150,13 @@
 		if (expression == null) {
 			codeStream.return_();
 		} else {
-			switch (expression.implicitConversion >> 4) {
+			final int implicitConversion = expression.implicitConversion;
+			if ((implicitConversion & BOXING) != 0) {
+				codeStream.areturn();
+				return;
+			}
+			int runtimeType = (implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
+			switch (runtimeType) {
 				case T_boolean :
 				case T_int :
 					codeStream.ireturn();
@@ -187,7 +192,9 @@
 			expression.printExpression(0, output) ;
 		return output.append(';');
 	}
+	
 	public void resolve(BlockScope scope) {
+		
 		MethodScope methodScope = scope.methodScope();
 		MethodBinding methodBinding;
 		TypeBinding methodType =
@@ -196,6 +203,7 @@
 					? null 
 					: methodBinding.returnType)
 				: VoidBinding;
+		TypeBinding expressionType;
 		if (methodType == VoidBinding) {
 			// the expression should be null
 			if (expression == null)
@@ -208,25 +216,30 @@
 			if (methodType != null) scope.problemReporter().shouldReturn(methodType, this);
 			return;
 		}
-		if ((expressionType = expression.resolveType(scope)) == null)
-			return;
-	
-		if (methodType != null && expression.isConstantValueOfTypeAssignableToType(expressionType, methodType)) {
-			// dealing with constant
-			expression.implicitWidening(methodType, expressionType);
-			return;
-		}
+		expression.setExpectedType(methodType); // needed in case of generic method invocation
+		if ((expressionType = expression.resolveType(scope)) == null) return;
 		if (expressionType == VoidBinding) {
 			scope.problemReporter().attemptToReturnVoidValue(this);
 			return;
 		}
-		if (methodType != null && expressionType.isCompatibleWith(methodType)) {
-			expression.implicitWidening(methodType, expressionType);
+		if (methodType == null) 
+			return;
+	
+		if (methodType != expressionType) // must call before computeConversion() and typeMismatchError()
+			scope.compilationUnitScope().recordTypeConversion(methodType, expressionType);
+		if (expression.isConstantValueOfTypeAssignableToType(expressionType, methodType)
+				|| expressionType.isCompatibleWith(methodType)) {
+
+			expression.computeConversion(scope, methodType, expressionType);
+			if (expressionType.needsUncheckedConversion(methodType)) {
+			    scope.problemReporter().unsafeRawConversion(this.expression, expressionType, methodType);
+			}
+			return;
+		} else if (scope.isBoxingCompatibleWith(expressionType, methodType)) {
+			expression.computeConversion(scope, methodType, expressionType);
 			return;
 		}
-		if (methodType != null){
-			scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionType, methodType);
-		}
+		scope.problemReporter().typeMismatchError(expressionType, methodType, expression);
 	}
 	public void traverse(ASTVisitor visitor, BlockScope scope) {
 		if (visitor.visit(this, scope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleMemberAnnotation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleMemberAnnotation.java
new file mode 100644
index 0000000..ff9881f
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleMemberAnnotation.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+
+/**
+ * SingleMemberAnnotation node
+ */
+public class SingleMemberAnnotation extends Annotation {
+	
+	public Expression memberValue;
+	public MemberValuePair singlePair; // fake pair, only value has accurate positions
+
+	public SingleMemberAnnotation(TypeReference type, int sourceStart) {
+		this.type = type;
+		this.sourceStart = sourceStart;
+		this.sourceEnd = type.sourceEnd;
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.Annotation#memberValuePairs()
+	 */
+	public MemberValuePair[] memberValuePairs() {
+		this.singlePair =  new MemberValuePair(VALUE, this.memberValue.sourceStart, this.memberValue.sourceEnd, this.memberValue);
+		return new MemberValuePair[] { singlePair };
+	}
+	
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+		super.printExpression(indent, output);
+		output.append('(');
+		this.memberValue.printExpression(indent, output);
+		return output.append(')');
+	}
+	
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		if (visitor.visit(this, scope)) {
+			if (this.memberValue != null) {
+				this.memberValue.traverse(visitor, scope);
+			}
+		}
+		visitor.endVisit(this, scope);
+	}
+	public void traverse(ASTVisitor visitor, CompilationUnitScope scope) {
+		if (visitor.visit(this, scope)) {
+			if (this.memberValue != null) {
+				this.memberValue.traverse(visitor, scope);
+			}
+		}
+		visitor.endVisit(this, scope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
index 908732b..eb937a6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
@@ -19,11 +19,12 @@
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 
 public class SingleNameReference extends NameReference implements OperatorIds {
+    
 	public char[] token;
-
 	public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor
 	public static final int READ = 0;
 	public static final int WRITE = 1;
+	public TypeBinding genericCast;
 	
 	public SingleNameReference(char[] source, long pos) {
 		super();
@@ -37,7 +38,7 @@
 		// compound assignment extra work
 		if (isCompound) { // check the variable part is initialized if blank final
 			switch (bits & RestrictiveFlagMASK) {
-				case FIELD : // reading a field
+				case Binding.FIELD : // reading a field
 					FieldBinding fieldBinding;
 					if ((fieldBinding = (FieldBinding) binding).isBlankFinal() 
 							&& currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
@@ -45,9 +46,9 @@
 							currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
 						}
 					}
-					manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
+					manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/);
 					break;
-				case LOCAL : // reading a local variable
+				case Binding.LOCAL : // reading a local variable
 					// check if assigning a final blank field
 					LocalVariableBinding localBinding;
 					if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
@@ -65,8 +66,8 @@
 			flowInfo = assignment.expression.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
 		}
 		switch (bits & RestrictiveFlagMASK) {
-			case FIELD : // assigning to a field
-				manageSyntheticWriteAccessIfNecessary(currentScope, flowInfo);
+			case Binding.FIELD : // assigning to a field
+				manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/);
 	
 				// check if assigning a final field
 				FieldBinding fieldBinding;
@@ -84,7 +85,7 @@
 					}
 				}
 				break;
-			case LOCAL : // assigning to a local variable 
+			case Binding.LOCAL : // assigning to a local variable 
 				LocalVariableBinding localBinding = (LocalVariableBinding) binding;
 				if (!flowInfo.isDefinitelyAssigned(localBinding)){// for local variable debug attributes
 					bits |= FirstAssignmentToLocalMASK;
@@ -116,9 +117,9 @@
 	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
 	
 		switch (bits & RestrictiveFlagMASK) {
-			case FIELD : // reading a field
+			case Binding.FIELD : // reading a field
 				if (valueRequired) {
-					manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
+					manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/);
 				}
 				// check if reading a final blank field
 				FieldBinding fieldBinding;
@@ -129,7 +130,7 @@
 					}
 				}
 				break;
-			case LOCAL : // reading a local variable
+			case Binding.LOCAL : // reading a local variable
 				LocalVariableBinding localBinding;
 				if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
 					currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
@@ -145,12 +146,13 @@
 		}
 		return flowInfo;
 	}
+	
 	public TypeBinding checkFieldAccess(BlockScope scope) {
 	
 		FieldBinding fieldBinding = (FieldBinding) binding;
 		
 		bits &= ~RestrictiveFlagMASK; // clear bits
-		bits |= FIELD;
+		bits |= Binding.FIELD;
 		if (!((FieldBinding) binding).isStatic()) {
 			// must check for the static status....
 			if (scope.methodScope().isStatic) {
@@ -178,6 +180,26 @@
 		return fieldBinding.type;
 	
 	}
+	
+	/**
+	 * @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;				
+		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) {
+			    // extra cast needed if method return type has type variable
+			    if ((originalBinding.type.tagBits & TagBits.HasTypeVariable) != 0 && runtimeTimeType.id != T_JavaLangObject) {
+			        this.genericCast = originalBinding.type.genericCast(scope.boxing(runtimeTimeType)); // runtimeType could be base type in boxing case
+			    }
+			} 	
+		}
+		super.computeConversion(scope, runtimeTimeType, compileTimeType);
+	}	
+
 	public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
 	
 		// optimizing assignment like: i = i + 1 or i = 1 + i
@@ -194,15 +216,15 @@
 				&& ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations
 				&& ((variableReference = (SingleNameReference) operation.right).binding == binding)
 				&& (operation.left.constant != NotAConstant) // exclude non constant expressions, since could have side-effect
-				&& ((operation.left.implicitConversion >> 4) != T_String) // exclude string concatenation which would occur backwards
-				&& ((operation.right.implicitConversion >> 4) != T_String)) { // exclude string concatenation which would occur backwards
+				&& (((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
 				variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.left, operator, operation.right.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
 				return;
 			}
 		}
 		switch (bits & RestrictiveFlagMASK) {
-			case FIELD : // assigning to a field
+			case Binding.FIELD : // assigning to a field
 				FieldBinding fieldBinding;
 				if (!(fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) { // need a receiver?
 					if ((bits & DepthMASK) != 0) {
@@ -218,8 +240,9 @@
 				if (valueRequired) {
 					codeStream.generateImplicitConversion(assignment.implicitConversion);
 				}
+				// no need for generic cast as value got dupped
 				return;
-			case LOCAL : // assigning to a local variable
+			case Binding.LOCAL : // assigning to a local variable
 				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 				if (localBinding.resolvedPosition != -1) {
 					assignment.expression.generateCode(currentScope, codeStream, true);
@@ -272,10 +295,10 @@
 			}
 		} else {
 			switch (bits & RestrictiveFlagMASK) {
-				case FIELD : // reading a field
+				case Binding.FIELD : // reading a field
 					FieldBinding fieldBinding;
 					if (valueRequired) {
-						if ((fieldBinding = (FieldBinding) this.codegenBinding).constant == NotAConstant) { // directly use inlined value for constant fields
+						if (!(fieldBinding = (FieldBinding) this.codegenBinding).isConstantValue()) { // directly use inlined value for constant fields
 							boolean isStatic;
 							if (!(isStatic = fieldBinding.isStatic())) {
 								if ((bits & DepthMASK) != 0) {
@@ -296,13 +319,14 @@
 							} else {
 								codeStream.invokestatic(syntheticAccessors[READ]);
 							}
+							if (this.genericCast != null) codeStream.checkcast(this.genericCast);
 							codeStream.generateImplicitConversion(implicitConversion);
-						} else { // directly use the inlined value
-							codeStream.generateConstant(fieldBinding.constant, implicitConversion);
+					} else { // directly use the inlined value
+							codeStream.generateConstant(fieldBinding.constant(), implicitConversion);
 						}
 					}
 					break;
-				case LOCAL : // reading a local
+				case Binding.LOCAL : // reading a local
 					LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 					if (valueRequired) {
 						// outer local?
@@ -343,7 +367,7 @@
 	 */
 	public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
 		switch (bits & RestrictiveFlagMASK) {
-			case FIELD : // assigning to a field
+			case Binding.FIELD : // assigning to a field
 				FieldBinding fieldBinding;
 				if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
 					if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
@@ -367,14 +391,14 @@
 					}
 				}
 				break;
-			case LOCAL : // assigning to a local variable (cannot assign to outer local)
+			case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
 				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 				Constant assignConstant;
 				int increment;
 				// using incr bytecode if possible
 				switch (localBinding.type.id) {
-					case T_String :
-						codeStream.generateStringAppend(currentScope, this, expression);
+					case T_JavaLangString :
+						codeStream.generateStringConcatenationAppend(currentScope, this, expression);
 						if (valueRequired) {
 							codeStream.dup();
 						}
@@ -406,31 +430,37 @@
 		}
 		// perform the actual compound operation
 		int operationTypeID;
-		if ((operationTypeID = implicitConversion >> 4) == T_String || operationTypeID == T_Object) {
-			// we enter here if the single name reference is a field of type java.lang.String or if the type of the 
-			// operation is java.lang.Object
-			// For example: o = o + ""; // where the compiled type of o is java.lang.Object.
-			codeStream.generateStringAppend(currentScope, null, expression);
-		} else {
-			// promote the array reference to the suitable operation type
-			codeStream.generateImplicitConversion(implicitConversion);
-			// generate the increment value (will by itself  be promoted to the operation value)
-			if (expression == IntLiteral.One){ // prefix operation
-				codeStream.generateConstant(expression.constant, implicitConversion);			
-			} 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);
+		switch(operationTypeID = (implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
+			case T_JavaLangString :
+			case T_JavaLangObject :
+			case T_undefined :
+				// we enter here if the single name reference is a field of type java.lang.String or if the type of the 
+				// operation is java.lang.Object
+				// For example: o = o + ""; // where the compiled type of o is java.lang.Object.
+				codeStream.generateStringConcatenationAppend(currentScope, null, expression);
+				// no need for generic cast on previous #getfield since using Object string buffer methods.			
+				break;
+			default :
+				// 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);
 		}
 		// store the result back into the variable
 		switch (bits & RestrictiveFlagMASK) {
-			case FIELD : // assigning to a field
+			case Binding.FIELD : // assigning to a field
 				fieldStore(codeStream, (FieldBinding) this.codegenBinding, writeAccessor, valueRequired);
+				// no need for generic cast as value got dupped
 				return;
-			case LOCAL : // assigning to a local variable
+			case Binding.LOCAL : // assigning to a local variable
 				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 				if (valueRequired) {
 					if ((localBinding.type == LongBinding) || (localBinding.type == DoubleBinding)) {
@@ -445,7 +475,7 @@
 	
 	public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
 		switch (bits & RestrictiveFlagMASK) {
-			case FIELD : // assigning to a field
+			case Binding.FIELD : // assigning to a field
 				FieldBinding fieldBinding;
 				if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
 					if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
@@ -483,12 +513,14 @@
 						}
 					}
 				}
+				codeStream.generateImplicitConversion(implicitConversion);		
 				codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
-				codeStream.sendOperator(postIncrement.operator, fieldBinding.type.id);
+				codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
 				codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
 				fieldStore(codeStream, fieldBinding, syntheticAccessors == null ? null : syntheticAccessors[WRITE], false);
+				// no need for generic cast 
 				return;
-			case LOCAL : // assigning to a local variable
+			case Binding.LOCAL : // assigning to a local variable
 				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 				// using incr bytecode if possible
 				if (localBinding.type == IntBinding) {
@@ -509,8 +541,9 @@
 							codeStream.dup();
 						}
 					}
+					codeStream.generateImplicitConversion(implicitConversion);
 					codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
-					codeStream.sendOperator(postIncrement.operator, localBinding.type.id);
+					codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
 					codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
 	
 					codeStream.store(localBinding, false);
@@ -522,6 +555,13 @@
 		
 		codeStream.aload_0();
 	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+	 */
+	public TypeBinding[] genericTypeArguments() {
+		return null;
+	}
 	
 	public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 	
@@ -529,11 +569,11 @@
 		//If inlinable field, forget the access emulation, the code gen will directly target it
 		if (((bits & DepthMASK) == 0) || (constant != NotAConstant)) return;
 	
-		if ((bits & RestrictiveFlagMASK) == LOCAL) {
+		if ((bits & RestrictiveFlagMASK) == Binding.LOCAL) {
 			currentScope.emulateOuterAccess((LocalVariableBinding) binding);
 		}
 	}
-	public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+	public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess) {
 	
 		if (!flowInfo.isReachable()) return;
 	
@@ -541,20 +581,20 @@
 		if (constant != NotAConstant)
 			return;
 	
-		if ((bits & FIELD) != 0) {
+		if ((bits & Binding.FIELD) != 0) {
 			FieldBinding fieldBinding = (FieldBinding) binding;
+			FieldBinding codegenField = fieldBinding.original();
+			this.codegenBinding = codegenField;
 			if (((bits & DepthMASK) != 0)
-				&& (fieldBinding.isPrivate() // private access
-					|| (fieldBinding.isProtected() // implicit protected access
-							&& fieldBinding.declaringClass.getPackage() 
-								!= currentScope.enclosingSourceType().getPackage()))) {
+				&& (codegenField.isPrivate() // private access
+					|| (codegenField.isProtected() // implicit protected access
+							&& codegenField.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage()))) {
 				if (syntheticAccessors == null)
 					syntheticAccessors = new MethodBinding[2];
-				syntheticAccessors[READ] = 
-					((SourceTypeBinding)currentScope.enclosingSourceType().
-						enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).
-							addSyntheticMethod(fieldBinding, true);
-				currentScope.problemReporter().needToEmulateFieldReadAccess(fieldBinding, this);
+				syntheticAccessors[isReadAccess ? READ : WRITE] = 
+				    ((SourceTypeBinding)currentScope.enclosingSourceType().
+						enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).addSyntheticMethod(codegenField, isReadAccess);
+				currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, isReadAccess);
 				return;
 			}
 			// if the binding declaring class is not visible, need special action
@@ -564,47 +604,15 @@
 			if (fieldBinding.declaringClass != this.actualReceiverType
 				&& !this.actualReceiverType.isArrayType()	
 				&& fieldBinding.declaringClass != null
-				&& fieldBinding.constant == NotAConstant
+				&& !fieldBinding.isConstantValue()
 				&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2 
 						&& !fieldBinding.isStatic()
-						&& fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
-					|| !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
-				this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.actualReceiverType);
-			}
-		}
-	}
-	public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
-	
-		if (!flowInfo.isReachable()) return;
-		if ((bits & FIELD) != 0) {
-			FieldBinding fieldBinding = (FieldBinding) binding;
-			if (((bits & DepthMASK) != 0) 
-				&& (fieldBinding.isPrivate() // private access
-					|| (fieldBinding.isProtected() // implicit protected access
-							&& fieldBinding.declaringClass.getPackage() 
-								!= currentScope.enclosingSourceType().getPackage()))) {
-				if (syntheticAccessors == null)
-					syntheticAccessors = new MethodBinding[2];
-				syntheticAccessors[WRITE] = 
-					((SourceTypeBinding)currentScope.enclosingSourceType().
-						enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).
-							addSyntheticMethod(fieldBinding, false);
-				currentScope.problemReporter().needToEmulateFieldWriteAccess(fieldBinding, this);
-				return;
-			}
-			// if the binding declaring class is not visible, need special action
-			// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
-			// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
-			// and not from Object or implicit static field access.	
-			if (fieldBinding.declaringClass != this.actualReceiverType
-				&& !this.actualReceiverType.isArrayType()	
-				&& fieldBinding.declaringClass != null
-				&& fieldBinding.constant == NotAConstant
-				&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2 
-						&& !fieldBinding.isStatic()
-						&& fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
-					|| !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
-				this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.actualReceiverType);
+						&& fieldBinding.declaringClass.id != T_JavaLangObject) // no change for Object fields (if there was any)
+					|| !codegenField.declaringClass.canBeSeenBy(currentScope))){
+				this.codegenBinding = 
+				    currentScope.enclosingSourceType().getUpdatedFieldBinding(
+					       codegenField, 
+					        (ReferenceBinding)this.actualReceiverType.erasure());
 			}
 		}
 	}
@@ -629,19 +637,24 @@
 	public TypeBinding resolveType(BlockScope scope) {
 		// for code gen, harm the restrictiveFlag 	
 	
-		this.actualReceiverType = this.receiverType = scope.enclosingSourceType();
-		
-		if ((this.codegenBinding = this.binding = scope.getBinding(token, bits & RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) {
+		if (this.actualReceiverType != null) {
+			this.binding = scope.getField(this.actualReceiverType, token, this);
+		} else {
+			this.actualReceiverType = scope.enclosingSourceType();
+			this.binding = scope.getBinding(token, bits & RestrictiveFlagMASK, this, true /*resolve*/);
+		}
+		this.codegenBinding = this.binding;
+		if (this.binding.isValidBinding()) {
 			switch (bits & RestrictiveFlagMASK) {
-				case VARIABLE : // =========only variable============
-				case VARIABLE | TYPE : //====both variable and type============
+				case Binding.VARIABLE : // =========only variable============
+				case Binding.VARIABLE | Binding.TYPE : //====both variable and type============
 					if (binding instanceof VariableBinding) {
 						VariableBinding variable = (VariableBinding) binding;
 						if (binding instanceof LocalVariableBinding) {
 							bits &= ~RestrictiveFlagMASK;  // clear bits
-							bits |= LOCAL;
+							bits |= Binding.LOCAL;
 							if ((this.bits & IsStrictlyAssignedMASK) == 0) {
-								constant = variable.constant;
+								constant = variable.constant();
 							} else {
 								constant = NotAConstant;
 							}
@@ -660,13 +673,14 @@
 	
 					// thus it was a type
 					bits &= ~RestrictiveFlagMASK;  // clear bits
-					bits |= TYPE;
-				case TYPE : //========only type==============
+					bits |= Binding.TYPE;
+				case Binding.TYPE : //========only type==============
 					constant = Constant.NotAConstant;
 					//deprecated test
-					if (isTypeUseDeprecated((TypeBinding) binding, scope))
-						scope.problemReporter().deprecatedType((TypeBinding) binding, this);
-					return this.resolvedType = (TypeBinding) binding;
+					TypeBinding type = (TypeBinding)binding;
+					if (isTypeUseDeprecated(type, scope))
+						scope.problemReporter().deprecatedType(type, this);
+					return this.resolvedType = scope.convertToRawType(type);
 			}
 		}
 	
@@ -684,4 +698,18 @@
 	
 		return new String(token);
 	}
+	
+	/**
+	 * Returns the local variable referenced by this node. Can be a direct reference (SingleNameReference)
+	 * or thru a cast expression etc...
+	 */
+	public LocalVariableBinding localVariableBinding() {
+		switch (bits & RestrictiveFlagMASK) {
+			case Binding.FIELD : // reading a field
+				break;
+			case Binding.LOCAL : // reading a local variable
+				return (LocalVariableBinding) this.binding;
+		}
+		return null;
+	}	
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
index 4d29467..55655f0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
@@ -25,22 +25,23 @@
 		
 	}
 
-	public SingleTypeReference(char[] source ,TypeBinding type, long pos) {
-		this(source, pos) ;
-		this.resolvedType = type ;
-	}
-
 	public TypeReference copyDims(int dim){
 		//return a type reference copy of me with some dimensions
 		//warning : the new type ref has a null binding
 		
-		return new ArrayTypeReference(token,null,dim,(((long)sourceStart)<<32)+sourceEnd) ;
+		return new ArrayTypeReference(token, dim,(((long)sourceStart)<<32)+sourceEnd);
 	}
 
-	public TypeBinding getTypeBinding(Scope scope) {
+	protected TypeBinding getTypeBinding(Scope scope) {
 		if (this.resolvedType != null)
 			return this.resolvedType;
-		return scope.getType(token);
+
+		this.resolvedType = scope.getType(token);
+
+		if (scope.kind == Scope.CLASS_SCOPE && this.resolvedType.isValidBinding())
+			if (((ClassScope) scope).detectHierarchyCycle(this.resolvedType, this, null))
+				return null;
+		return this.resolvedType;
 	}
 
 	public char [][] getTypeName() {
@@ -54,14 +55,15 @@
 
 	public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
 
-		ReferenceBinding memberTb = scope.getMemberType(token, enclosingType);
-		if (!memberTb.isValidBinding()) {
-			scope.problemReporter().invalidEnclosingType(this, memberTb, enclosingType);
+		ReferenceBinding memberType = scope.getMemberType(token, enclosingType);
+		if (!memberType.isValidBinding()) {
+			this.resolvedType = memberType;
+			scope.problemReporter().invalidEnclosingType(this, memberType, enclosingType);
 			return null;
 		}
-		if (isTypeUseDeprecated(memberTb, scope))
-			scope.problemReporter().deprecatedType(memberTb, this);
-		return this.resolvedType = memberTb;
+		if (isTypeUseDeprecated(memberType, scope))
+			scope.problemReporter().deprecatedType(memberType, this);
+		return this.resolvedType = scope.convertToRawType(memberType);
 	}
 
 	public void traverse(ASTVisitor visitor, BlockScope scope) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
index 2e240f7..591165d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
@@ -10,9 +10,9 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public abstract class Statement extends ASTNode {
@@ -40,7 +40,59 @@
 		}
 		return false;
 	}
-	
+
+	/**
+	 * Generate invocation arguments, considering varargs methods
+	 */
+	public void generateArguments(MethodBinding binding, Expression[] arguments, BlockScope currentScope, CodeStream codeStream) {
+		
+		if (binding.isVarargs()) {
+			// 5 possibilities exist for a call to the vararg method foo(int i, int ... value) : 
+			//      foo(1), foo(1, null), foo(1, 2), foo(1, 2, 3, 4) & foo(1, new int[] {1, 2})
+			TypeBinding[] params = binding.parameters;
+			int paramLength = params.length;
+			int varArgIndex = paramLength - 1;
+			for (int i = 0; i < varArgIndex; i++) {
+				arguments[i].generateCode(currentScope, codeStream, true);
+			}
+
+			ArrayBinding varArgsType = (ArrayBinding) params[varArgIndex]; // parameterType has to be an array type
+			int argLength = arguments == null ? 0 : arguments.length;
+
+			generateVarargsArgument: {
+				if (argLength >= paramLength) {
+					// right number of arguments - could be inexact - pass argument as is
+					TypeBinding lastType = arguments[varArgIndex].resolvedType;
+					if (lastType == NullBinding || varArgsType.dimensions() == lastType.dimensions()) {
+						// foo(1, new int[]{2, 3}) or foo(1, null) --> last arg is passed as-is
+						arguments[varArgIndex].generateCode(currentScope, codeStream, true);
+						break generateVarargsArgument;
+					}
+					// right number but not directly compatible or too many arguments - wrap extra into array
+					// called with (argLength - lastIndex) elements : foo(1, 2) or foo(1, 2, 3, 4)
+					// need to gen elements into an array, then gen each remaining element into created array
+					codeStream.generateInlinedValue(argLength - varArgIndex);
+					codeStream.newArray(varArgsType); // create a mono-dimensional array
+					int elementsTypeID = varArgsType.elementsType().id;
+					for (int i = varArgIndex; i < argLength; i++) {
+						codeStream.dup();
+						codeStream.generateInlinedValue(i - varArgIndex);
+						arguments[i].generateCode(currentScope, codeStream, true);
+						codeStream.arrayAtPut(elementsTypeID, false);
+					}
+				} else { // not enough arguments - pass extra empty array
+					// scenario: foo(1) --> foo(1, new int[0])
+					// generate code for an empty array of parameterType
+					codeStream.generateInlinedValue(0);
+					codeStream.newArray(varArgsType); // create a mono-dimensional array
+				}
+			}
+		} else if (arguments != null) { // standard generation for method arguments
+			for (int i = 0, max = arguments.length; i < max; i++)
+				arguments[i].generateCode(currentScope, codeStream, true);
+		}
+	}
+
 	public abstract void generateCode(BlockScope currentScope, CodeStream codeStream);
 	
 	public boolean isEmptyBlock() {
@@ -69,11 +121,14 @@
 
 	public abstract void resolve(BlockScope scope);
 	
+	/**
+	 * Returns case constant associated to this statement (NotAConstant if none)
+	 */
 	public Constant resolveCase(BlockScope scope, TypeBinding testType, SwitchStatement switchStatement) {
 		// statement within a switch that are not case are treated as normal statement.... 
 
 		resolve(scope);
-		return null;
+		return NotAConstant;
 	}
 
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/StringLiteralConcatenation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/StringLiteralConcatenation.java
index 77ee9cc..1ea7892 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/StringLiteralConcatenation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/StringLiteralConcatenation.java
@@ -18,7 +18,7 @@
  */
 public class StringLiteralConcatenation extends StringLiteral {
 	private static final int INITIAL_SIZE = 5;
-	public StringLiteral[] literals;
+	public Expression[] literals;
 	public int counter;
 	/**	
 	 * Build a two-strings literal
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java
index 59b697b..754efdf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java
@@ -44,8 +44,10 @@
 		if (currentLabel.start == currentLabel.codeStream.position) {
 			// discard empty exception handler
 			this.anyExceptionLabels[--this.anyExceptionLabelsCount] = null;
+			currentLabel.codeStream.removeExceptionHandler(currentLabel);
+		} else {
+			currentLabel.placeEnd();
 		}
-		currentLabel.placeEnd();
 	}
 	
 	public void placeAllAnyExceptionHandlers() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SuperReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SuperReference.java
index a877d12..9519a34 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SuperReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SuperReference.java
@@ -54,7 +54,7 @@
 		if (!checkAccess(scope.methodScope()))
 			return null;
 		SourceTypeBinding enclosingTb = scope.enclosingSourceType();
-		if (enclosingTb.id == T_Object) {
+		if (enclosingTb.id == T_JavaLangObject) {
 			scope.problemReporter().cannotUseSuperInJavaLangObject(this);
 			return null;
 		}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
index 65cddb1..6050f9f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
@@ -11,10 +11,10 @@
 package org.eclipse.jdt.internal.compiler.ast;
 
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class SwitchStatement extends Statement {
@@ -26,8 +26,9 @@
 	public Label breakLabel;
 	public CaseStatement[] cases;
 	public CaseStatement defaultCase;
-	public int caseCount = 0;
 	public int blockStart;
+	public int caseCount;
+	int[] constants;
 	
 	// for local variables table attributes
 	int preSwitchInitStateIndex = -1;
@@ -101,87 +102,79 @@
 	public void generateCode(BlockScope currentScope, CodeStream codeStream) {
 
 	    try {
-			int[] sortedIndexes = new int[caseCount];
-			int[] localKeysCopy;
 			if ((bits & IsReachableMASK) == 0) {
 				return;
 			}
 			int pc = codeStream.position;
 	
 			// prepare the labels and constants
-			breakLabel.initialize(codeStream);
-			CaseLabel[] caseLabels = new CaseLabel[caseCount];
-			int[] constants = new int[caseCount];
-			boolean needSwitch = caseCount != 0;
+			this.breakLabel.initialize(codeStream);
+			CaseLabel[] caseLabels = new CaseLabel[this.caseCount];
+			boolean needSwitch = this.caseCount != 0;
 			for (int i = 0; i < caseCount; i++) {
-				constants[i] = cases[i].constantExpression.constant.intValue();
 				cases[i].targetLabel = (caseLabels[i] = new CaseLabel(codeStream));
 			}
-	
-			// we sort the keys to be able to generate the code for tableswitch or lookupswitch
-			for (int i = 0; i < caseCount; i++) {
-				sortedIndexes[i] = i;
-			}
-			System.arraycopy(
-				constants,
-				0,
-				(localKeysCopy = new int[caseCount]),
-				0,
-				caseCount);
-			CodeStream.sort(localKeysCopy, 0, caseCount - 1, sortedIndexes);
 			CaseLabel defaultLabel = new CaseLabel(codeStream);
 			if (defaultCase != null) {
 				defaultCase.targetLabel = defaultLabel;
 			}
 			// generate expression testes
 			expression.generateCode(currentScope, codeStream, needSwitch);
-	
 			// generate the appropriate switch table/lookup bytecode
 			if (needSwitch) {
-				int max = localKeysCopy[caseCount - 1];
+				int[] sortedIndexes = new int[this.caseCount];
+				// we sort the keys to be able to generate the code for tableswitch or lookupswitch
+				for (int i = 0; i < caseCount; i++) {
+					sortedIndexes[i] = i;
+				}
+				int[] localKeysCopy;
+				System.arraycopy(this.constants, 0, (localKeysCopy = new int[this.caseCount]), 0, this.caseCount);
+				CodeStream.sort(localKeysCopy, 0, this.caseCount - 1, sortedIndexes);
+
+				// for enum constants, actually switch on constant ordinal()
+				if (this.expression.resolvedType.isEnum()) {
+					codeStream.invokeEnumOrdinal(this.expression.resolvedType.constantPoolName());
+				}
+				int max = localKeysCopy[this.caseCount - 1];
 				int min = localKeysCopy[0];
 				if ((long) (caseCount * 2.5) > ((long) max - (long) min)) {
 					
 					// work-around 1.3 VM bug, if max>0x7FFF0000, must use lookup bytecode
 					// see http://dev.eclipse.org/bugs/show_bug.cgi?id=21557
 					if (max > 0x7FFF0000 && currentScope.environment().options.complianceLevel < ClassFileConstants.JDK1_4) {
-						codeStream.lookupswitch(defaultLabel, constants, sortedIndexes, caseLabels);
+						codeStream.lookupswitch(defaultLabel, this.constants, sortedIndexes, caseLabels);
 	
 					} else {
 						codeStream.tableswitch(
 							defaultLabel,
 							min,
 							max,
-							constants,
+							this.constants,
 							sortedIndexes,
 							caseLabels);
 					}
 				} else {
-					codeStream.lookupswitch(defaultLabel, constants, sortedIndexes, caseLabels);
+					codeStream.lookupswitch(defaultLabel, this.constants, sortedIndexes, caseLabels);
 				}
 				codeStream.updateLastRecordedEndPC(codeStream.position);
 			}
 			
 			// generate the switch block statements
 			int caseIndex = 0;
-			if (statements != null) {
-				for (int i = 0, maxCases = statements.length; i < maxCases; i++) {
-					Statement statement = statements[i];
-					if ((caseIndex < caseCount) && (statement == cases[caseIndex])) { // statements[i] is a case
-						this.scope.switchCase = cases[caseIndex]; // record entering in a switch case block
+			if (this.statements != null) {
+				for (int i = 0, maxCases = this.statements.length; i < maxCases; i++) {
+					Statement statement = this.statements[i];
+					if ((caseIndex < this.caseCount) && (statement == this.cases[caseIndex])) { // statements[i] is a case
+						this.scope.switchCase = this.cases[caseIndex]; // record entering in a switch case block
 						if (preSwitchInitStateIndex != -1) {
-							codeStream.removeNotDefinitelyAssignedVariables(
-								currentScope,
-								preSwitchInitStateIndex);
+							codeStream.removeNotDefinitelyAssignedVariables(currentScope, preSwitchInitStateIndex);
 						}
 						caseIndex++;
 					} else {
-						if (statement == defaultCase) { // statements[i] is a case or a default case
-							this.scope.switchCase = defaultCase; // record entering in a switch case block
+						if (statement == this.defaultCase) { // statements[i] is a case or a default case
+							this.scope.switchCase = this.defaultCase; // record entering in a switch case block
 							if (preSwitchInitStateIndex != -1) {
-								codeStream.removeNotDefinitelyAssignedVariables(
-									currentScope,
-									preSwitchInitStateIndex);
+								codeStream.removeNotDefinitelyAssignedVariables(currentScope, preSwitchInitStateIndex);
 							}
 						}
 					}
@@ -189,19 +182,17 @@
 				}
 			}
 			// place the trailing labels (for break and default case)
-			breakLabel.place();
+			this.breakLabel.place();
 			if (defaultCase == null) {
 				defaultLabel.place();
 			}
 			// May loose some local variable initializations : affecting the local variable attributes
 			if (mergedInitStateIndex != -1) {
-				codeStream.removeNotDefinitelyAssignedVariables(
-					currentScope,
-					mergedInitStateIndex);
+				codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
 				codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
 			}
 			if (scope != currentScope) {
-				codeStream.exitUserScope(scope);
+				codeStream.exitUserScope(this.scope);
 			}
 			codeStream.recordPositionsFrom(pc, this.sourceStart);
 	    } finally {
@@ -230,60 +221,71 @@
 	public void resolve(BlockScope upperScope) {
 	
 	    try {
-			TypeBinding testType = expression.resolveType(upperScope);
-			if (testType == null)
+			TypeBinding expressionType = expression.resolveType(upperScope);
+			if (expressionType == null)
 				return;
-			expression.implicitWidening(testType, testType);
-			if (!(expression.isConstantValueOfTypeAssignableToType(testType, IntBinding))) {
-				if (!testType.isCompatibleWith(IntBinding)) {
-					upperScope.problemReporter().incorrectSwitchType(expression, testType);
-					return;
+			expression.computeConversion(upperScope, expressionType, expressionType);
+			checkType: {
+				if (expressionType.isBaseType()) {
+					if (expression.isConstantValueOfTypeAssignableToType(expressionType, IntBinding))
+						break checkType;
+					if (expressionType.isCompatibleWith(IntBinding))
+						break checkType;
+				} else if (expressionType.isEnum()) {
+					break checkType;
+				} else if (upperScope.isBoxingCompatibleWith(expressionType, IntBinding)) {
+					expression.computeConversion(upperScope, IntBinding, expressionType);
+					break checkType;
 				}
+				upperScope.problemReporter().incorrectSwitchType(expression, expressionType);
+				// TODO (philippe) could keep analyzing switch statements in case of error
+				return;
 			}
 			if (statements != null) {
 				scope = explicitDeclarations == 0 ? upperScope : new BlockScope(upperScope);
 				int length;
 				// collection of cases is too big but we will only iterate until caseCount
 				cases = new CaseStatement[length = statements.length];
-				int[] casesValues = new int[length];
+				this.constants = new int[length];
 				CaseStatement[] duplicateCaseStatements = null;
 				int duplicateCaseStatementsCounter = 0;
 				int counter = 0;
 				for (int i = 0; i < length; i++) {
 					Constant constant;
 					final Statement statement = statements[i];
-					if ((constant = statement.resolveCase(scope, testType, this)) != null) {
+					if ((constant = statement.resolveCase(scope, expressionType, this)) != Constant.NotAConstant) {
+						int key = constant.intValue();
 						//----check for duplicate case statement------------
-						if (constant != NotAConstant) {
-							int key = constant.intValue();
-							for (int j = 0; j < counter; j++) {
-								if (casesValues[j] == key) {
-									final CaseStatement currentCaseStatement = (CaseStatement) statement;
-									if (duplicateCaseStatements == null) {
-										scope.problemReporter().duplicateCase(cases[j]);
+						for (int j = 0; j < counter; j++) {
+							if (this.constants[j] == key) {
+								final CaseStatement currentCaseStatement = (CaseStatement) statement;
+								if (duplicateCaseStatements == null) {
+									scope.problemReporter().duplicateCase(cases[j]);
+									scope.problemReporter().duplicateCase(currentCaseStatement);
+									duplicateCaseStatements = new CaseStatement[length];
+									duplicateCaseStatements[duplicateCaseStatementsCounter++] = cases[j];
+									duplicateCaseStatements[duplicateCaseStatementsCounter++] = currentCaseStatement;
+								} else {
+									boolean found = false;
+									searchReportedDuplicate: for (int k = 2; k < duplicateCaseStatementsCounter; k++) {
+										if (duplicateCaseStatements[k] == statement) {
+											found = true;
+											break searchReportedDuplicate;
+										}
+									}
+									if (!found) {
 										scope.problemReporter().duplicateCase(currentCaseStatement);
-										duplicateCaseStatements = new CaseStatement[length];
-										duplicateCaseStatements[duplicateCaseStatementsCounter++] = cases[j];
 										duplicateCaseStatements[duplicateCaseStatementsCounter++] = currentCaseStatement;
-									} else {
-										boolean found = false;
-										searchReportedDuplicate: for (int k = 2; k < duplicateCaseStatementsCounter; k++) {
-											if (duplicateCaseStatements[k] == statement) {
-												found = true;
-												break searchReportedDuplicate;
-											}
-										}
-										if (!found) {
-											scope.problemReporter().duplicateCase(currentCaseStatement);
-											duplicateCaseStatements[duplicateCaseStatementsCounter++] = currentCaseStatement;
-										}
 									}
 								}
 							}
-							casesValues[counter++] = key;
 						}
+						this.constants[counter++] = key;
 					}
 				}
+				if (length != counter) { // resize constants array
+					System.arraycopy(this.constants, 0, this.constants = new int[counter], 0, counter);
+				}
 			} else {
 				if ((this.bits & UndocumentedEmptyBlockMASK) != 0) {
 					upperScope.problemReporter().undocumentedEmptyBlock(this.blockStart, this.sourceEnd);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
index 2a45c54..b49d6ad 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
@@ -41,6 +41,8 @@
 		FlowContext flowContext,
 		FlowInfo flowInfo) {
 
+	    // TODO (philippe) shouldn't it be protected by a check whether reachable statement ?
+	    
 		// mark the synthetic variable as being used
 		synchroVariable.useFlag = LocalVariableBinding.USED;
 
@@ -69,7 +71,7 @@
 	 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
 	 */
 	public void generateCode(BlockScope currentScope, CodeStream codeStream) {
-
+	
 		if ((bits & IsReachableMASK) == 0) {
 			return;
 		}
@@ -80,7 +82,7 @@
 			this.anyExceptionLabelsCount = 0;
 		}
 		int pc = codeStream.position;
-
+	
 		// generate the synchronization expression
 		expression.generateCode(scope, codeStream, true);
 		if (block.isEmptyBlock()) {
@@ -97,7 +99,7 @@
 			// enter the monitor
 			codeStream.store(synchroVariable, true);
 			codeStream.monitorenter();
-
+	
 			// generate  the body of the synchronized block
 			this.enterAnyExceptionHandler(codeStream);
 			block.generateCode(scope, codeStream);
@@ -105,14 +107,16 @@
 			if (!blockExit) {
 				codeStream.load(synchroVariable);
 				codeStream.monitorexit();
+				this.exitAnyExceptionHandler();
 				codeStream.goto_(endLabel);
+				this.enterAnyExceptionHandler(codeStream);
 			}
 			// generate the body of the exception handler
-			this.exitAnyExceptionHandler();
 			this.placeAllAnyExceptionHandlers();
 			codeStream.incrStackSize(1);
 			codeStream.load(synchroVariable);
 			codeStream.monitorexit();
+			this.exitAnyExceptionHandler();
 			codeStream.athrow();
 			if (!blockExit) {
 				endLabel.place();
@@ -163,8 +167,8 @@
 		//continue even on errors in order to have the TC done into the statements
 		synchroVariable = new LocalVariableBinding(SecretLocalDeclarationName, type, AccDefault, false);
 		scope.addLocalVariable(synchroVariable);
-		synchroVariable.constant = NotAConstant; // not inlinable
-		expression.implicitWidening(type, type);
+		synchroVariable.setConstant(NotAConstant); // not inlinable
+		expression.computeConversion(scope, type, type);
 		block.resolveUsing(scope);
 	}
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThisReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
index 78ccdfa..c81c876 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
@@ -97,6 +97,10 @@
 		return true ;
 	}
 
+	public int nullStatus(FlowInfo flowInfo) {
+		return FlowInfo.NON_NULL;
+	}
+	
 	public StringBuffer printExpression(int indent, StringBuffer output){
 	
 		if (this.isImplicitThis()) return output;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
index dac8920..515d313 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
@@ -68,7 +68,7 @@
 			// if compliant with 1.4, this problem will not be reported
 			scope.problemReporter().cannotThrowNull(this);
 	 	}
-		exception.implicitWidening(exceptionType, exceptionType);
+		exception.computeConversion(scope, exceptionType, exceptionType);
 	}
 
 	public void traverse(ASTVisitor visitor, BlockScope blockScope) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java
index 14dc78f..a3bd34d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java
@@ -23,8 +23,8 @@
 	super(s,e);
 }
 public void computeConstant() {
-
-	constant = Constant.fromValue(true);}
+	this.constant = Constant.fromValue(true);
+}
 /**
  * Code generation for the true literal
  *
@@ -34,8 +34,9 @@
  */ 
 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
 	int pc = codeStream.position;
-	if (valueRequired)
-		codeStream.iconst_1();
+	if (valueRequired) {
+		codeStream.generateConstant(constant, implicitConversion);
+	}
 	codeStream.recordPositionsFrom(pc, this.sourceStart);
 }
 public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
index bda4130..9101bce 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
@@ -83,7 +83,7 @@
 					.analyseCode(
 						currentScope,
 						finallyContext = new FinallyFlowContext(flowContext, finallyBlock),
-						flowInfo.copy())
+						flowInfo.copy().unconditionalInits().discardNullRelatedInitializations())
 					.unconditionalInits();
 			if (subInfo == FlowInfo.DEAD_END) {
 				isSubRoutineEscaping = true;
@@ -128,7 +128,10 @@
 						.addPotentialInitializationsFrom(handlingContext.initsOnReturn);
 
 				// catch var is always set
-				catchInfo.markAsDefinitelyAssigned(catchArguments[i].binding);
+				LocalVariableBinding catchArg = catchArguments[i].binding;
+				FlowContext catchContext = insideSubContext == null ? flowContext : insideSubContext;
+				catchInfo.markAsDefinitelyAssigned(catchArg);
+				catchInfo.markAsDefinitelyNonNull(catchArg);
 				/*
 				"If we are about to consider an unchecked exception handler, potential inits may have occured inside
 				the try block that need to be detected , e.g. 
@@ -136,15 +139,13 @@
 				"(uncheckedExceptionTypes notNil and: [uncheckedExceptionTypes at: index])
 				ifTrue: [catchInits addPotentialInitializationsFrom: tryInits]."
 				*/
-				// TODO (philippe) should only tag as unreachable if the catchblock cannot be reached?
-				//??? if (!handlingContext.initsOnException(caughtExceptionTypes[i]).isReachable()){
 				if (tryBlock.statements == null) {
 					catchInfo.setReachMode(FlowInfo.UNREACHABLE);
 				}
 				catchInfo =
 					catchBlocks[i].analyseCode(
 						currentScope,
-						insideSubContext == null ? flowContext : insideSubContext,
+						catchContext,
 						catchInfo);
 				catchExits[i] = !catchInfo.isReachable();
 				tryInfo = tryInfo.mergedWith(catchInfo.unconditionalInits());
@@ -159,7 +160,7 @@
 
 		// we also need to check potential multiple assignments of final variables inside the finally block
 		// need to include potential inits from returns inside the try/catch parts - 1GK2AOF
-		finallyContext.complainOnRedundantFinalAssignments(
+		finallyContext.complainOnDeferredChecks(
 			tryInfo.isReachable() 
 				? (tryInfo.addPotentialInitializationsFrom(insideSubContext.initsOnReturn))
 				: insideSubContext.initsOnReturn, 
@@ -187,7 +188,6 @@
 	 * returnAddress is only allocated if jsr is allowed
 	 */
 	public void generateCode(BlockScope currentScope, CodeStream codeStream) {
-
 		if ((bits & IsReachableMASK) == 0) {
 			return;
 		}
@@ -260,15 +260,11 @@
 			thrown) into their own catch variables, the one specified in the source
 			that must denote the handled exception.
 			*/
-			if (catchArguments == null) {
-				this.exitAnyExceptionHandler();
-			} else {
+			if (catchArguments != null) {
 				for (int i = 0; i < maxCatches; i++) {
 					// May loose some local variable initializations : affecting the local variable attributes
 					if (preTryInitStateIndex != -1) {
-						codeStream.removeNotDefinitelyAssignedVariables(
-							currentScope,
-							preTryInitStateIndex);
+						codeStream.removeNotDefinitelyAssignedVariables(currentScope, preTryInitStateIndex);
 					}
 					exceptionLabels[i].place();
 					codeStream.incrStackSize(1);
@@ -286,10 +282,6 @@
 					// Keep track of the pcs at diverging point for computing the local attribute
 					// since not passing the catchScope, the block generation will exitUserScope(catchScope)
 					catchBlocks[i].generateCode(scope, codeStream);
-
-					if (i == maxCatches - 1) {
-						this.exitAnyExceptionHandler();
-					}
 					if (!catchExits[i]) {
 						switch(finallyMode) {
 							case FINALLY_SUBROUTINE :
@@ -306,55 +298,57 @@
 					}
 				}
 			}
+			this.exitAnyExceptionHandler();
 			// extra handler for trailing natural exit (will be fixed up later on when natural exit is generated below)
 			ExceptionLabel naturalExitExceptionHandler = 
-				finallyMode == FINALLY_SUBROUTINE && requiresNaturalExit ? this.enterAnyExceptionHandler(codeStream) : null;
-						
+				finallyMode == FINALLY_SUBROUTINE && requiresNaturalExit ? new ExceptionLabel(codeStream, null) : null;
+
 			// addition of a special handler so as to ensure that any uncaught exception (or exception thrown
 			// inside catch blocks) will run the finally block
 			int finallySequenceStartPC = codeStream.position;
 			if (subRoutineStartLabel != null) {
-				// the additional handler is doing: jsr finallyBlock and rethrow TOS-exception
 				this.placeAllAnyExceptionHandlers();
-
+				if (naturalExitExceptionHandler != null) naturalExitExceptionHandler.place();
+				
 				if (preTryInitStateIndex != -1) {
 					// reset initialization state, as for a normal catch block
-					codeStream.removeNotDefinitelyAssignedVariables(
-						currentScope,
-						preTryInitStateIndex);
+					codeStream.removeNotDefinitelyAssignedVariables(currentScope, preTryInitStateIndex);
 				}
 
 				codeStream.incrStackSize(1);
 				switch(finallyMode) {
-					
 					case FINALLY_SUBROUTINE :
 						codeStream.store(anyExceptionVariable, false);
 						codeStream.jsr(subRoutineStartLabel);
+						codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
+						int position = codeStream.position;						
 						codeStream.load(anyExceptionVariable);
 						codeStream.athrow();
+						codeStream.recordPositionsFrom(position, finallyBlock.sourceEnd);
 						subRoutineStartLabel.place();
 						codeStream.incrStackSize(1);
+						position = codeStream.position;	
 						codeStream.store(returnAddressVariable, false);
-						codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
+						codeStream.recordPositionsFrom(position, finallyBlock.sourceStart);
 						finallyBlock.generateCode(scope, codeStream);
-						int position = codeStream.position;
+						position = codeStream.position;
 						codeStream.ret(returnAddressVariable.resolvedPosition);
-						codeStream.updateLastRecordedEndPC(position);
+//						codeStream.updateLastRecordedEndPC(position);
 						codeStream.recordPositionsFrom(
 							position,
 							finallyBlock.sourceEnd);
 						// the ret bytecode is part of the subroutine
 						break;
-						
 					case FINALLY_MUST_BE_INLINED :
 						codeStream.store(anyExceptionVariable, false);
+						codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
 						this.finallyBlock.generateCode(currentScope, codeStream);
+						position = codeStream.position;
 						codeStream.load(anyExceptionVariable);
 						codeStream.athrow();
 						subRoutineStartLabel.place();
-						codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
+						codeStream.recordPositionsFrom(position, finallyBlock.sourceEnd);
 						break;
-						
 					case FINALLY_DOES_NOT_COMPLETE :
 						codeStream.pop();
 						subRoutineStartLabel.place();
@@ -366,30 +360,25 @@
 				naturalExitLabel.place();
 				if (requiresNaturalExit) {
 					switch(finallyMode) {
-
 						case FINALLY_SUBROUTINE :
-							int position = codeStream.position;					
+							int position = codeStream.position;
 							// fix up natural exit handler
 							naturalExitExceptionHandler.placeStart();
 							codeStream.jsr(subRoutineStartLabel);
 							naturalExitExceptionHandler.placeEnd();
 							codeStream.recordPositionsFrom(
 								position,
-								finallyBlock.sourceStart);					
+								finallyBlock.sourceEnd);	
 							break;
-						
 						case FINALLY_MUST_BE_INLINED :
 							// May loose some local variable initializations : affecting the local variable attributes
 							// needed since any exception handler got inlined subroutine
 							if (preTryInitStateIndex != -1) {
-								codeStream.removeNotDefinitelyAssignedVariables(
-									currentScope,
-									preTryInitStateIndex);
+								codeStream.removeNotDefinitelyAssignedVariables(currentScope, preTryInitStateIndex);
 							}
 							// entire sequence for finally is associated to finally block
 							finallyBlock.generateCode(scope, codeStream);
 							break;
-						
 						case FINALLY_DOES_NOT_COMPLETE :
 							break;
 					}
@@ -406,9 +395,7 @@
 		}
 		// May loose some local variable initializations : affecting the local variable attributes
 		if (mergedInitStateIndex != -1) {
-			codeStream.removeNotDefinitelyAssignedVariables(
-				currentScope,
-				mergedInitStateIndex);
+			codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
 			codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
 		}
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
@@ -480,14 +467,14 @@
 					this.returnAddressVariable =
 						new LocalVariableBinding(SecretReturnName, upperScope.getJavaLangObject(), AccDefault, false);
 					finallyScope.addLocalVariable(returnAddressVariable);
-					this.returnAddressVariable.constant = NotAConstant; // not inlinable
+					this.returnAddressVariable.setConstant(NotAConstant); // not inlinable
 				}
 				this.subRoutineStartLabel = new Label();
 	
 				this.anyExceptionVariable =
 					new LocalVariableBinding(SecretAnyHandlerName, scope.getJavaLangThrowable(), AccDefault, false);
 				finallyScope.addLocalVariable(this.anyExceptionVariable);
-				this.anyExceptionVariable.constant = NotAConstant; // not inlinable
+				this.anyExceptionVariable.setConstant(NotAConstant); // not inlinable
 	
 				if (!methodScope.isInsideInitializer()) {
 					MethodBinding methodBinding =
@@ -502,7 +489,7 @@
 									AccDefault,
 									false);
 							finallyScope.addLocalVariable(this.secretReturnValue);
-							this.secretReturnValue.constant = NotAConstant; // not inlinable
+							this.secretReturnValue.setConstant(NotAConstant); // not inlinable
 						}
 					}
 				}
@@ -518,17 +505,21 @@
 		if (this.catchBlocks != null) {
 			int length = this.catchArguments.length;
 			TypeBinding[] argumentTypes = new TypeBinding[length];
+			boolean catchHasError = false;
 			for (int i = 0; i < length; i++) {
 				BlockScope catchScope = new BlockScope(scope);
 				if (finallyScope != null){
 					finallyScope.shiftScopes[i+1] = catchScope;
 				}
 				// side effect on catchScope in resolveForCatch(..)
-				if ((argumentTypes[i] = catchArguments[i].resolveForCatch(catchScope)) == null)
-					return;
+				if ((argumentTypes[i] = catchArguments[i].resolveForCatch(catchScope)) == null) {
+					catchHasError = true;
+				}
 				catchBlocks[i].resolveUsing(catchScope);
 			}
-
+			if (catchHasError) {
+				return;
+			}
 			// Verify that the catch clause are ordered in the right way:
 			// more specialized first.
 			this.caughtExceptionTypes = new ReferenceBinding[length];
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
index b6ba6f1..580877d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
@@ -15,6 +15,7 @@
 import org.eclipse.jdt.internal.compiler.*;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.parser.*;
@@ -28,6 +29,7 @@
 
 	public int modifiers = AccDefault;
 	public int modifiersSourceStart;
+	public Annotation[] annotations;
 	public char[] name;
 	public TypeReference superclass;
 	public TypeReference[] superInterfaces;
@@ -46,12 +48,17 @@
 	public int bodyEnd; // doesn't include the trailing comment if any.
 	protected boolean hasBeenGenerated = false;
 	public CompilationResult compilationResult;
-	private MethodDeclaration[] missingAbstractMethods;
+	public MethodDeclaration[] missingAbstractMethods;
 	public Javadoc javadoc;	
 
 	public QualifiedAllocationExpression allocation; // for anonymous only
 	public TypeDeclaration enclosingType; // for member types only
 	
+	public FieldBinding enumValuesSyntheticfield; 	// for enum
+
+	// 1.5 support
+	public TypeParameter[] typeParameters;
+	
 	public TypeDeclaration(CompilationResult compilationResult){
 		this.compilationResult = compilationResult;
 	}
@@ -282,7 +289,7 @@
 							methods[i] = m;
 						}
 					} else {
-						if (this.isInterface()) {
+						if (this.kind() == IGenericType.INTERFACE_DECL) {
 							// report the problem and continue the parsing
 							parser.problemReporter().interfaceCannotHaveConstructors(
 								(ConstructorDeclaration) am);
@@ -300,7 +307,7 @@
 		return this.compilationResult;
 	}
 
-	public ConstructorDeclaration createsInternalConstructor(
+	public ConstructorDeclaration createDefaultConstructor(
 		boolean needExplicitConstructorCall,
 		boolean needToInsert) {
 
@@ -312,7 +319,7 @@
 		//the constructor
 		ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
 		constructor.isDefaultConstructor = true;
-		constructor.selector = name;
+		constructor.selector = this.name;
 		if (modifiers != AccDefault) {
 			constructor.modifiers =
 				(((this.bits & ASTNode.IsMemberTypeMASK) != 0) && (modifiers & AccPrivate) != 0)
@@ -353,7 +360,7 @@
 	}
 	
 	// anonymous type constructor creation
-	public MethodBinding createsInternalConstructorWithBinding(MethodBinding inheritedConstructorBinding) {
+	public MethodBinding createDefaultConstructorWithBinding(MethodBinding inheritedConstructorBinding) {
 
 		//Add to method'set, the default constuctor that just recall the
 		//super constructor with the same arguments
@@ -550,10 +557,7 @@
 					methods[i].generateCode(scope, classFile);
 				}
 			}
-			
-			classFile.generateMissingAbstractMethods(this.missingAbstractMethods, scope.referenceCompilationUnit().compilationResult);
-
-			// generate all methods
+			// generate all synthetic and abstract methods
 			classFile.addSpecialMethods();
 
 			if (ignoreFurtherInvestigation) { // trigger problem type generation for code gen errors
@@ -660,14 +664,14 @@
 					if (nonStaticFieldInfo == FlowInfo.DEAD_END) {
 						initializerScope.problemReporter().initializerMustCompleteNormally(field);
 						nonStaticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
-					}
+					} 
 				}
 			}
 		}
 		if (memberTypes != null) {
 			for (int i = 0, count = memberTypes.length; i < count; i++) {
 				if (flowContext != null){ // local type
-					memberTypes[i].analyseCode(scope, flowContext, nonStaticFieldInfo.copy());
+					memberTypes[i].analyseCode(scope, flowContext, nonStaticFieldInfo.copy().setReachMode(flowInfo.reachMode())); // reset reach mode in case initializers did abrupt completely
 				} else {
 					memberTypes[i].analyseCode(scope);
 				}
@@ -684,23 +688,32 @@
 					if (method.isStatic()) { // <clinit>
 						method.analyseCode(
 							scope, 
-							staticInitializerContext, 
-							staticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo));
+							staticInitializerContext,  
+							staticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo).setReachMode(flowInfo.reachMode()));  // reset reach mode in case initializers did abrupt completely
 					} else { // constructor
-						method.analyseCode(scope, initializerContext, constructorInfo.copy());
+						method.analyseCode(scope, initializerContext, constructorInfo.copy().setReachMode(flowInfo.reachMode())); // reset reach mode in case initializers did abrupt completely
 					}
 				} else { // regular method
 					method.analyseCode(scope, null, flowInfo.copy());
 				}
 			}
 		}
+		// enable enum support ?
+		if (this.binding.isEnum()) {
+			this.enumValuesSyntheticfield = this.binding.addSyntheticFieldForEnumValues();
+		}
 	}
 
-	public boolean isInterface() {
-
-		return (modifiers & AccInterface) != 0;
+	public int kind() {
+		if ((modifiers & AccInterface) != 0) {
+			if ((modifiers & AccAnnotation) != 0) 
+				return IGenericType.ANNOTATION_TYPE_DECL;
+			return IGenericType.INTERFACE_DECL;
+		} else if ((modifiers & AccEnum) != 0) 
+			return IGenericType.ENUM_DECL;
+		return IGenericType.CLASS_DECL;
 	}
-
+	
 	/* 
 	 * Access emulation for a local type
 	 * force to emulation of access to direct enclosing instance.
@@ -721,7 +734,7 @@
 		}
 		// add superclass enclosing instance arg for anonymous types (if necessary)
 		if (binding.isAnonymousType()) { 
-			ReferenceBinding superclassBinding = binding.superclass;
+			ReferenceBinding superclassBinding = (ReferenceBinding)binding.superclass.erasure();
 			if (superclassBinding.enclosingType() != null && !superclassBinding.isStatic()) {
 				if (!superclassBinding.isLocalType()
 						|| ((NestedTypeBinding)superclassBinding).getSyntheticField(superclassBinding.enclosingType(), true) != null){
@@ -759,12 +772,15 @@
 			return true;
 		if (fields == null)
 			return false;
-		if (isInterface())
+		
+		if (kind() == IGenericType.INTERFACE_DECL)
 			return true; // fields are implicitly statics
 		for (int i = fields.length; --i >= 0;) {
 			FieldDeclaration field = fields[i];
 			//need to test the modifier directly while there is no binding yet
 			if ((field.modifiers & AccStatic) != 0)
+				return true; // TODO (philippe) shouldn't it check whether field is initializer or has some initial value ?
+			if (field.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT)
 				return true;
 		}
 		return false;
@@ -786,16 +802,20 @@
 		//methods
 		if (methods != null) {
 			int length = methods.length;
-			for (int i = 0; i < length; i++)
+			for (int i = 0; i < length; i++) {
 				methods[i].parseStatements(parser, unit);
+			}
 		}
 
 		//initializers
 		if (fields != null) {
 			int length = fields.length;
 			for (int i = 0; i < length; i++) {
-				if (fields[i] instanceof Initializer) {
-					((Initializer) fields[i]).parseStatements(parser, this, unit);
+				final FieldDeclaration fieldDeclaration = fields[i];
+				switch(fieldDeclaration.getKind()) {
+					case AbstractVariableDeclaration.INITIALIZER:
+						((Initializer) fieldDeclaration).parseStatements(parser, this, unit);
+						break;
 				}
 			}
 		}
@@ -823,7 +843,7 @@
 		}
 		if (fields != null) {
 			for (int fieldI = 0; fieldI < fields.length; fieldI++) {
-				if (fields[fieldI] != null) {
+				if (fields[fieldI] != null) { // TODO (olivier) should improve to deal with enumconstants using ',' separator
 					output.append('\n');
 					fields[fieldI].print(indent + 1, output);
 				}
@@ -844,14 +864,46 @@
 	public StringBuffer printHeader(int indent, StringBuffer output) {
 
 		printModifiers(this.modifiers, output);
-		output.append(isInterface() ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
+		if (this.annotations != null) printAnnotations(this.annotations, output);
+		
+		switch (kind()) {
+			case IGenericType.CLASS_DECL :
+				output.append("class "); //$NON-NLS-1$
+				break;
+			case IGenericType.INTERFACE_DECL :
+				output.append("interface "); //$NON-NLS-1$
+				break;
+			case IGenericType.ENUM_DECL :
+				output.append("enum "); //$NON-NLS-1$
+				break;
+			case IGenericType.ANNOTATION_TYPE_DECL :
+				output.append("@interface "); //$NON-NLS-1$
+				break;
+		}			
 		output.append(name);
+		if (typeParameters != null) {
+			output.append("<");//$NON-NLS-1$
+			for (int i = 0; i < typeParameters.length; i++) {
+				if (i > 0) output.append( ", "); //$NON-NLS-1$
+				typeParameters[i].print(0, output);
+			}
+			output.append(">");//$NON-NLS-1$
+		}
 		if (superclass != null) {
 			output.append(" extends ");  //$NON-NLS-1$
 			superclass.print(0, output);
 		}
 		if (superInterfaces != null && superInterfaces.length > 0) {
-			output.append(isInterface() ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$
+			switch (kind()) {
+				case IGenericType.CLASS_DECL :
+				case IGenericType.ENUM_DECL :
+					output.append(" implements "); //$NON-NLS-1$
+					break;
+				case IGenericType.INTERFACE_DECL :
+				case IGenericType.ANNOTATION_TYPE_DECL :
+					output.append(" extends "); //$NON-NLS-1$
+					break;
+			}			
 			for (int i = 0; i < superInterfaces.length; i++) {
 				if (i > 0) output.append( ", "); //$NON-NLS-1$
 				superInterfaces[i].print(0, output);
@@ -863,51 +915,92 @@
 	public StringBuffer printStatement(int tab, StringBuffer output) {
 		return print(tab, output);
 	}
+	
+
 
 	public void resolve() {
-
-		if (this.binding == null) {
+		SourceTypeBinding sourceType = this.binding;
+		if (sourceType == null) {
 			this.ignoreFurtherInvestigation = true;
 			return;
 		}
 		try {
+			resolveAnnotations(this.staticInitializerScope, this.annotations, sourceType);
+			
 			if ((this.bits & UndocumentedEmptyBlockMASK) != 0) {
 				this.scope.problemReporter().undocumentedEmptyBlock(this.bodyStart-1, this.bodyEnd);
 			}
-			// check superclass & interfaces
-			if (this.binding.superclass != null) // watch out for Object ! (and other roots)	
-				if (isTypeUseDeprecated(this.binding.superclass, this.scope))
-					this.scope.problemReporter().deprecatedType(this.binding.superclass, this.superclass);
-			if (this.superInterfaces != null)
-				for (int i = this.superInterfaces.length; --i >= 0;)
-					if (this.superInterfaces[i].resolvedType != null)
-						if (isTypeUseDeprecated(this.superInterfaces[i].resolvedType, this.scope))
-							this.scope.problemReporter().deprecatedType(
-								this.superInterfaces[i].resolvedType,
-								this.superInterfaces[i]);
+			boolean needSerialVersion = 
+							this.scope.environment().options.getSeverity(CompilerOptions.MissingSerialVersion) != ProblemSeverities.Ignore
+							&& sourceType.isClass() 
+							&& !sourceType.isAbstract() 
+							&& sourceType.findSuperTypeErasingTo(T_JavaIoSerializable, false /*Serializable is not a class*/) != null;
+			
+			if (this.typeParameters != null && scope.getJavaLangThrowable().isSuperclassOf(sourceType)) {
+				this.scope.problemReporter().genericTypeCannotExtendThrowable(this);
+			}
 			this.maxFieldCount = 0;
 			int lastVisibleFieldID = -1;
+			boolean hasEnumConstants = false;
+			boolean hasEnumConstantsWithoutBody = false;
+			if (this.memberTypes != null) {
+				for (int i = 0, count = this.memberTypes.length; i < count; i++) {
+					this.memberTypes[i].resolve(this.scope);
+				}
+			}
 			if (this.fields != null) {
 				for (int i = 0, count = this.fields.length; i < count; i++) {
 					FieldDeclaration field = this.fields[i];
-					if (field.isField()) {
-						if (field.binding == null) {
-							// still discover secondary errors
-							if (field.initialization != null) field.initialization.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope);
-							this.ignoreFurtherInvestigation = true;
-							continue;
-						}
-						this.maxFieldCount++;
-						lastVisibleFieldID = field.binding.id;
-					} else { // initializer
-						 ((Initializer) field).lastVisibleFieldID = lastVisibleFieldID + 1;
+					switch(field.getKind()) {
+						case AbstractVariableDeclaration.ENUM_CONSTANT:
+							hasEnumConstants = true;
+							if (!(field.initialization instanceof QualifiedAllocationExpression))
+								hasEnumConstantsWithoutBody = true;
+						case AbstractVariableDeclaration.FIELD:
+							FieldBinding fieldBinding = field.binding;
+							if (fieldBinding == null) {
+								// still discover secondary errors
+								if (field.initialization != null) field.initialization.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope);
+								this.ignoreFurtherInvestigation = true;
+								continue;
+							}
+							if (needSerialVersion
+									&& ((fieldBinding.modifiers & (AccStatic | AccFinal)) == (AccStatic | AccFinal))
+									&& CharOperation.equals(TypeConstants.SERIALVERSIONUID, fieldBinding.name)
+									&& BaseTypes.LongBinding == fieldBinding.type) {
+								needSerialVersion = false;
+							}
+							this.maxFieldCount++;
+							lastVisibleFieldID = field.binding.id;
+							break;
+	
+						case AbstractVariableDeclaration.INITIALIZER:
+							 ((Initializer) field).lastVisibleFieldID = lastVisibleFieldID + 1;
+							break;
 					}
 					field.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope);
 				}
 			}
-			if (this.memberTypes != null) {
-				for (int i = 0, count = this.memberTypes.length; i < count; i++) {
-					this.memberTypes[i].resolve(this.scope);
+			if (needSerialVersion) {
+				this.scope.problemReporter().missingSerialVersion(this);
+			}
+			// check extends/implements for annotation type
+			if (kind() == IGenericType.ANNOTATION_TYPE_DECL) {
+				if (this.superclass != null) {
+					this.scope.problemReporter().annotationTypeDeclarationCannotHaveSuperclass(this);
+				}
+				if (this.superInterfaces != null) {
+					this.scope.problemReporter().annotationTypeDeclarationCannotHaveSuperinterfaces(this);
+				}
+			}
+			// check enum abstract methods
+			if (kind() == IGenericType.ENUM_DECL && this.binding.isAbstract()) {
+				if (!hasEnumConstants || hasEnumConstantsWithoutBody) {
+					for (int i = 0, count = this.methods.length; i < count; i++) {
+						if (this.methods[i].isAbstract()) {
+							this.scope.problemReporter().enumAbstractMethodMustBeImplemented(this.methods[i]);
+						}
+					}
 				}
 			}
 			int missingAbstractMethodslength = this.missingAbstractMethods == null ? 0 : this.missingAbstractMethods.length;
@@ -926,8 +1019,8 @@
 				if (this.scope != null) {
 					this.javadoc.resolve(this.scope);
 				}
-			} else if (this.binding != null && !this.binding.isLocalType()) {
-				this.scope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
+			} else if (sourceType != null && !sourceType.isLocalType()) {
+				this.scope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, sourceType.modifiers);
 			}
 			
 		} catch (AbortType e) {
@@ -988,33 +1081,44 @@
 			return;
 		try {
 			if (visitor.visit(this, unitScope)) {
-				if (superclass != null)
-					superclass.traverse(visitor, scope);
-				if (superInterfaces != null) {
-					int superInterfaceLength = superInterfaces.length;
-					for (int i = 0; i < superInterfaceLength; i++)
-						superInterfaces[i].traverse(visitor, scope);
+				if (this.annotations != null) {
+					int annotationsLength = this.annotations.length;
+					for (int i = 0; i < annotationsLength; i++)
+						this.annotations[i].traverse(visitor, scope);
 				}
-				if (memberTypes != null) {
-					int memberTypesLength = memberTypes.length;
-					for (int i = 0; i < memberTypesLength; i++)
-						memberTypes[i].traverse(visitor, scope);
+				if (this.superclass != null)
+					this.superclass.traverse(visitor, scope);
+				if (this.superInterfaces != null) {
+					int length = this.superInterfaces.length;
+					for (int i = 0; i < length; i++)
+						this.superInterfaces[i].traverse(visitor, scope);
 				}
-				if (fields != null) {
-					int fieldsLength = fields.length;
-					for (int i = 0; i < fieldsLength; i++) {
+				if (this.typeParameters != null) {
+					int length = this.typeParameters.length;
+					for (int i = 0; i < length; i++) {
+						this.typeParameters[i].traverse(visitor, scope);
+					}
+				}				
+				if (this.memberTypes != null) {
+					int length = this.memberTypes.length;
+					for (int i = 0; i < length; i++)
+						this.memberTypes[i].traverse(visitor, scope);
+				}
+				if (this.fields != null) {
+					int length = this.fields.length;
+					for (int i = 0; i < length; i++) {
 						FieldDeclaration field;
-						if ((field = fields[i]).isStatic()) {
+						if ((field = this.fields[i]).isStatic()) {
 							field.traverse(visitor, staticInitializerScope);
 						} else {
 							field.traverse(visitor, initializerScope);
 						}
 					}
 				}
-				if (methods != null) {
-					int methodsLength = methods.length;
-					for (int i = 0; i < methodsLength; i++)
-						methods[i].traverse(visitor, scope);
+				if (this.methods != null) {
+					int length = this.methods.length;
+					for (int i = 0; i < length; i++)
+						this.methods[i].traverse(visitor, scope);
 				}
 			}
 			visitor.endVisit(this, unitScope);
@@ -1032,33 +1136,44 @@
 			return;
 		try {
 			if (visitor.visit(this, blockScope)) {
-				if (superclass != null)
-					superclass.traverse(visitor, scope);
-				if (superInterfaces != null) {
-					int superInterfaceLength = superInterfaces.length;
-					for (int i = 0; i < superInterfaceLength; i++)
-						superInterfaces[i].traverse(visitor, scope);
+				if (this.annotations != null) {
+					int annotationsLength = this.annotations.length;
+					for (int i = 0; i < annotationsLength; i++)
+						this.annotations[i].traverse(visitor, scope);
 				}
-				if (memberTypes != null) {
-					int memberTypesLength = memberTypes.length;
-					for (int i = 0; i < memberTypesLength; i++)
-						memberTypes[i].traverse(visitor, scope);
+				if (this.superclass != null)
+					this.superclass.traverse(visitor, scope);
+				if (this.superInterfaces != null) {
+					int length = this.superInterfaces.length;
+					for (int i = 0; i < length; i++)
+						this.superInterfaces[i].traverse(visitor, scope);
 				}
-				if (fields != null) {
-					int fieldsLength = fields.length;
-					for (int i = 0; i < fieldsLength; i++) {
+				if (this.typeParameters != null) {
+					int length = this.typeParameters.length;
+					for (int i = 0; i < length; i++) {
+						this.typeParameters[i].traverse(visitor, scope);
+					}
+				}				
+				if (this.memberTypes != null) {
+					int length = this.memberTypes.length;
+					for (int i = 0; i < length; i++)
+						this.memberTypes[i].traverse(visitor, scope);
+				}
+				if (this.fields != null) {
+					int length = this.fields.length;
+					for (int i = 0; i < length; i++) {
 						FieldDeclaration field;
-						if ((field = fields[i]).isStatic()) {
+						if ((field = this.fields[i]).isStatic()) {
 							// local type cannot have static fields
 						} else {
 							field.traverse(visitor, initializerScope);
 						}
 					}
 				}
-				if (methods != null) {
-					int methodsLength = methods.length;
-					for (int i = 0; i < methodsLength; i++)
-						methods[i].traverse(visitor, scope);
+				if (this.methods != null) {
+					int length = this.methods.length;
+					for (int i = 0; i < length; i++)
+						this.methods[i].traverse(visitor, scope);
 				}
 			}
 			visitor.endVisit(this, blockScope);
@@ -1076,33 +1191,44 @@
 			return;
 		try {
 			if (visitor.visit(this, classScope)) {
-				if (superclass != null)
-					superclass.traverse(visitor, scope);
-				if (superInterfaces != null) {
-					int superInterfaceLength = superInterfaces.length;
-					for (int i = 0; i < superInterfaceLength; i++)
-						superInterfaces[i].traverse(visitor, scope);
+				if (this.annotations != null) {
+					int annotationsLength = this.annotations.length;
+					for (int i = 0; i < annotationsLength; i++)
+						this.annotations[i].traverse(visitor, scope);
 				}
-				if (memberTypes != null) {
-					int memberTypesLength = memberTypes.length;
-					for (int i = 0; i < memberTypesLength; i++)
-						memberTypes[i].traverse(visitor, scope);
+				if (this.superclass != null)
+					this.superclass.traverse(visitor, scope);
+				if (this.superInterfaces != null) {
+					int length = this.superInterfaces.length;
+					for (int i = 0; i < length; i++)
+						this.superInterfaces[i].traverse(visitor, scope);
 				}
-				if (fields != null) {
-					int fieldsLength = fields.length;
-					for (int i = 0; i < fieldsLength; i++) {
+				if (this.typeParameters != null) {
+					int length = this.typeParameters.length;
+					for (int i = 0; i < length; i++) {
+						this.typeParameters[i].traverse(visitor, scope);
+					}
+				}				
+				if (this.memberTypes != null) {
+					int length = this.memberTypes.length;
+					for (int i = 0; i < length; i++)
+						this.memberTypes[i].traverse(visitor, scope);
+				}
+				if (this.fields != null) {
+					int length = this.fields.length;
+					for (int i = 0; i < length; i++) {
 						FieldDeclaration field;
-						if ((field = fields[i]).isStatic()) {
+						if ((field = this.fields[i]).isStatic()) {
 							field.traverse(visitor, staticInitializerScope);
 						} else {
 							field.traverse(visitor, initializerScope);
 						}
 					}
 				}
-				if (methods != null) {
-					int methodsLength = methods.length;
-					for (int i = 0; i < methodsLength; i++)
-						methods[i].traverse(visitor, scope);
+				if (this.methods != null) {
+					int length = this.methods.length;
+					for (int i = 0; i < length; i++)
+						this.methods[i].traverse(visitor, scope);
 				}
 			}
 			visitor.endVisit(this, classScope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java
new file mode 100644
index 0000000..bfa7e3f
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
+
+public class TypeParameter extends AbstractVariableDeclaration {
+
+    public TypeVariableBinding binding;
+	public TypeReference[] bounds;
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
+	 */
+	public int getKind() {
+		return TYPE_PARAMETER;
+	}
+
+	public void checkBounds(Scope scope) {
+		
+		if (this.type != null) {
+			this.type.checkBounds(scope);
+		}
+		if (this.bounds != null) {
+			for (int i = 0, length = this.bounds.length; i < length; i++) {
+				this.bounds[i].checkBounds(scope);
+			}
+		}
+	}
+	
+	public void resolve(ClassScope scope) {
+	    // TODO (philippe) add warning for detecting variable name collisions
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.ast.AstNode#print(int, java.lang.StringBuffer)
+	 */
+	public StringBuffer printStatement(int indent, StringBuffer output) {
+		output.append(this.name);
+		if (this.type != null) {
+			output.append(" extends "); //$NON-NLS-1$
+			this.type.print(0, output);
+		}
+		if (this.bounds != null){
+			for (int i = 0; i < this.bounds.length; i++) {
+				output.append(" & "); //$NON-NLS-1$
+				this.bounds[i].print(0, output);
+			}
+		}
+		return output;
+	}
+	
+	public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+	    // nothing to do
+	}
+	
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		if (visitor.visit(this, scope)) {
+			if (type != null) {
+				type.traverse(visitor, scope);
+			}
+			if (bounds != null) {
+				int boundsLength = this.bounds.length;
+				for (int i = 0; i < boundsLength; i++) {
+					this.bounds[i].traverse(visitor, scope);
+				}
+			}
+		}
+		visitor.endVisit(this, scope);
+	}
+
+	public void traverse(ASTVisitor visitor, ClassScope scope) {
+		if (visitor.visit(this, scope)) {
+			if (type != null) {
+				type.traverse(visitor, scope);
+			}
+			if (bounds != null) {
+				int boundsLength = this.bounds.length;
+				for (int i = 0; i < boundsLength; i++) {
+					this.bounds[i].traverse(visitor, scope);
+				}
+			}
+		}
+		visitor.endVisit(this, scope);
+	}	
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
index 2e8e10c..5865269 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
@@ -77,11 +77,21 @@
 			return new ArrayTypeReference(LongBinding.simpleName, dim, 0);
 	}
 }
+public void checkBounds(Scope scope) {
+	// only parameterized type references have bounds
+}
 public abstract TypeReference copyDims(int dim);
 public int dimensions() {
 	return 0;
 }
-public abstract TypeBinding getTypeBinding(Scope scope);
+/**
+ * @return char[][]
+ * TODO (jerome) should merge back into #getTypeName()
+ */
+public char [][] getParameterizedTypeName(){
+	return getTypeName();
+}
+protected abstract TypeBinding getTypeBinding(Scope scope);
 /**
  * @return char[][]
  */
@@ -89,43 +99,65 @@
 public boolean isTypeReference() {
 	return true;
 }
-public TypeBinding resolveType(BlockScope blockScope) {
-	// handle the error here
-	this.constant = NotAConstant;
-	if (this.resolvedType != null) { // is a shared type reference which was already resolved
-		if (!this.resolvedType.isValidBinding())
-			return null; // already reported error
-	} else {
-		this.resolvedType = getTypeBinding(blockScope);
-		if (!this.resolvedType.isValidBinding()) {
-			reportInvalidType(blockScope);
-			return null;
-		}
-		if (isTypeUseDeprecated(this.resolvedType, blockScope)) {
-			reportDeprecatedType(blockScope);
-		}
+public TypeBinding resolveSuperType(ClassScope scope) {
+	// assumes the implementation of resolveType(ClassScope) will call back to detect cycles
+	if (resolveType(scope) == null) return null;
+
+	if (this.resolvedType.isTypeVariable()) {
+		this.resolvedType = new ProblemReferenceBinding(getTypeName(), (ReferenceBinding) this.resolvedType, ProblemReasons.IllegalSuperTypeVariable);
+		reportInvalidType(scope);
+		return null;
 	}
 	return this.resolvedType;
 }
 
+public final TypeBinding resolveType(BlockScope blockScope) {
+	return resolveType(blockScope, true /* checkbounds if any */);
+}
+
+public TypeBinding resolveType(BlockScope blockScope, boolean checkBounds) {
+	// handle the error here
+	this.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
+
+	this.resolvedType = getTypeBinding(blockScope);
+	if (this.resolvedType == null)
+		return null; // detected cycle while resolving hierarchy	
+	if (!this.resolvedType.isValidBinding()) {
+		reportInvalidType(blockScope);
+		return null;
+	}
+	if (isTypeUseDeprecated(this.resolvedType, blockScope))
+		reportDeprecatedType(blockScope);
+	return this.resolvedType = blockScope.convertToRawType(this.resolvedType);
+}
 public TypeBinding resolveType(ClassScope classScope) {
 	// handle the error here
 	this.constant = NotAConstant;
-	if (this.resolvedType != null) { // is a shared type reference which was already resolved
-		if (!this.resolvedType.isValidBinding())
-			return null; // already reported error
-	} else {
-		this.resolvedType = getTypeBinding(classScope);
-		if (!this.resolvedType.isValidBinding()) {
-			reportInvalidType(classScope);
-			return null;
-		}
-		if (isTypeUseDeprecated(this.resolvedType, classScope)) {
-			reportDeprecatedType(classScope);
-		}
+	if (this.resolvedType != null) // is a shared type reference which was already resolved
+		return this.resolvedType.isValidBinding() ? this.resolvedType : null; // already reported error
+
+	this.resolvedType = getTypeBinding(classScope);
+	if (this.resolvedType == null)
+		return null; // detected cycle while resolving hierarchy	
+	if (!this.resolvedType.isValidBinding()) {
+		reportInvalidType(classScope);
+		return null;
 	}
-	return this.resolvedType;
+	if (isTypeUseDeprecated(this.resolvedType, classScope))
+		reportDeprecatedType(classScope);
+	return this.resolvedType = classScope.convertToRawType(this.resolvedType);
 }
+
+public TypeBinding resolveTypeArgument(BlockScope blockScope, ReferenceBinding genericType, int rank) {
+    return resolveType(blockScope, true /* check bounds*/);
+}
+
+public TypeBinding resolveTypeArgument(ClassScope classScope, ReferenceBinding genericType, int rank) {
+    return resolveType(classScope);
+}
+	
 protected void reportInvalidType(Scope scope) {
 	scope.problemReporter().invalidType(this, this.resolvedType);
 }
@@ -133,4 +165,5 @@
 	scope.problemReporter().deprecatedType(this.resolvedType, this);
 }
 public abstract void traverse(ASTVisitor visitor, ClassScope classScope);
+public abstract void traverse(ASTVisitor visitor, BlockScope classScope);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
index 1e3a2fc..7e38c26 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
@@ -71,7 +71,7 @@
 		}
 		switch ((bits & OperatorMASK) >> OperatorSHIFT) {
 			case NOT :
-				switch (this.expression.implicitConversion >> 4) /* runtime type */ {
+				switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) /* runtime type */ {
 					case T_boolean :
 						// ! <boolean>
 						// Generate code for the condition
@@ -97,8 +97,7 @@
 				}
 				break;
 			case TWIDDLE :
-				switch (this.expression.implicitConversion >> 4 /* runtime */
-					) {
+				switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4 /* runtime */) {
 					case T_int :
 						// ~int
 						this.expression.generateCode(currentScope, codeStream, valueRequired);
@@ -119,7 +118,7 @@
 				// - <num>
 				if (this.constant != NotAConstant) {
 					if (valueRequired) {
-						switch (this.expression.implicitConversion >> 4){ /* runtime */
+						switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4){ /* runtime */
 							case T_int :
 								codeStream.generateInlinedValue(this.constant.intValue() * -1);
 								break;
@@ -136,7 +135,7 @@
 				} else {
 					this.expression.generateCode(currentScope, codeStream, valueRequired);
 					if (valueRequired) {
-						switch (expression.implicitConversion >> 4){ /* runtime type */
+						switch ((expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4){ /* runtime type */
 							case T_int :
 								codeStream.ineg();
 								break;
@@ -213,8 +212,16 @@
 			this.constant = NotAConstant;
 			return null;
 		}
-		int expressionTypeId = expressionType.id;
-		if (expressionTypeId > 15) {
+		int expressionTypeID = expressionType.id;
+		// autoboxing support
+		LookupEnvironment env = scope.environment();
+		boolean use15specifics = env.options.sourceLevel >= JDK1_5;
+		if (use15specifics) {
+			if (!expressionType.isBaseType()) {
+				expressionTypeID = env.computeBoxingType(expressionType).id;
+			}
+		}		
+		if (expressionTypeID > 15) {
 			this.constant = NotAConstant;
 			scope.problemReporter().invalidOperator(this, expressionType);
 			return null;
@@ -236,8 +243,8 @@
 		// (cast)  left   Op (cast)  rigth --> result
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       <<0
-		int operatorSignature = OperatorSignatures[tableId][(expressionTypeId << 4) + expressionTypeId];
-		this.expression.implicitConversion = operatorSignature >>> 12;
+		int operatorSignature = OperatorSignatures[tableId][(expressionTypeID << 4) + expressionTypeID];
+		this.expression.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 16) & 0x0000F), expressionType);
 		this.bits |= operatorSignature & 0xF;
 		switch (operatorSignature & 0xF) { // only switch on possible result type.....
 			case T_boolean :
@@ -263,7 +270,7 @@
 				break;
 			default : //error........
 				this.constant = Constant.NotAConstant;
-				if (expressionTypeId != T_undefined)
+				if (expressionTypeID != T_undefined)
 					scope.problemReporter().invalidOperator(this, expressionType);
 				return null;
 		}
@@ -272,7 +279,7 @@
 			this.constant =
 				Constant.computeConstantOperation(
 					this.expression.constant,
-					expressionTypeId,
+					expressionTypeID,
 					(bits & OperatorMASK) >> OperatorSHIFT);
 		} else {
 			this.constant = Constant.NotAConstant;
@@ -284,7 +291,7 @@
 		}
 		if (expressionIsCast) {
 		// check need for operand cast
-			CastExpression.checkNeedForArgumentCast(scope, tableId, operatorSignature, this.expression, expressionTypeId);
+			CastExpression.checkNeedForArgumentCast(scope, tableId, operatorSignature, this.expression, expressionTypeID);
 		}
 		return this.resolvedType;
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
index b7e1441..fc7be36 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
@@ -55,22 +55,23 @@
 		preCondInitStateIndex =
 			currentScope.methodScope().recordInitializationStates(flowInfo);
 		LoopingFlowContext condLoopContext;
-		FlowInfo postCondInfo =
-			this.condition.analyseCode(
+		FlowInfo condInfo = flowInfo.copy().unconditionalInits().discardNullRelatedInitializations();
+		condInfo = this.condition.analyseCode(
 				currentScope,
 				(condLoopContext =
 					new LoopingFlowContext(flowContext, this, null, null, currentScope)),
-				flowInfo);
+				condInfo);
 
 		LoopingFlowContext loopingContext;
 		FlowInfo actionInfo;
+		FlowInfo exitBranch;
 		if (action == null 
 			|| (action.isEmptyBlock() && currentScope.environment().options.complianceLevel <= ClassFileConstants.JDK1_3)) {
-			condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
+			condLoopContext.complainOnDeferredChecks(currentScope, condInfo);
 			if (isConditionTrue) {
 				return FlowInfo.DEAD_END;
 			} else {
-				FlowInfo mergedInfo = postCondInfo.initsWhenFalse().unconditionalInits();
+				FlowInfo mergedInfo = condInfo.initsWhenFalse().unconditionalInits();
 				if (isConditionOptimizedTrue){
 					mergedInfo.setReachMode(FlowInfo.UNREACHABLE);
 				}
@@ -91,7 +92,7 @@
 			if (isConditionFalse) {
 				actionInfo = FlowInfo.DEAD_END;
 			} else {
-				actionInfo = postCondInfo.initsWhenTrue().copy();
+				actionInfo = condInfo.initsWhenTrue().copy();
 				if (isConditionOptimizedFalse){
 					actionInfo.setReachMode(FlowInfo.UNREACHABLE);
 				}
@@ -100,20 +101,22 @@
 			// for computing local var attributes
 			condIfTrueInitStateIndex =
 				currentScope.methodScope().recordInitializationStates(
-					postCondInfo.initsWhenTrue());
+					condInfo.initsWhenTrue());
 
 			if (!this.action.complainIfUnreachable(actionInfo, currentScope, false)) {
 				actionInfo = this.action.analyseCode(currentScope, loopingContext, actionInfo);
 			}
 
 			// code generation can be optimized when no need to continue in the loop
+			exitBranch = condInfo.initsWhenFalse();
+			exitBranch.addInitializationsFrom(flowInfo); // recover null inits from before condition analysis
 			if (!actionInfo.isReachable() && !loopingContext.initsOnContinue.isReachable()) {
 				continueLabel = null;
 			} else {
-				// TODO (philippe) should simplify in one Loop context
-				condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
+				condLoopContext.complainOnDeferredChecks(currentScope, condInfo);
 				actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue.unconditionalInits());
-				loopingContext.complainOnFinalAssignmentsInLoop(currentScope, actionInfo);
+				loopingContext.complainOnDeferredChecks(currentScope, actionInfo);
+				exitBranch.addPotentialInitializationsFrom(actionInfo.unconditionalInits());
 			}
 		}
 
@@ -121,7 +124,7 @@
 		FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
 				loopingContext.initsOnBreak, 
 				isConditionOptimizedTrue, 
-				postCondInfo.initsWhenFalse(), 
+				exitBranch,
 				isConditionOptimizedFalse,
 				!isConditionTrue /*while(true); unreachable(); */);
 		mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
@@ -178,9 +181,7 @@
 			action.generateCode(currentScope, codeStream);
 			// May loose some local variable initializations : affecting the local variable attributes
 			if (preCondInitStateIndex != -1) {
-				codeStream.removeNotDefinitelyAssignedVariables(
-					currentScope,
-					preCondInitStateIndex);
+				codeStream.removeNotDefinitelyAssignedVariables(currentScope, preCondInitStateIndex);
 			}
 
 		}
@@ -207,7 +208,7 @@
 	public void resolve(BlockScope scope) {
 
 		TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
-		condition.implicitWidening(type, type);
+		condition.computeConversion(scope, type, type);
 		if (action != null)
 			action.resolve(scope);
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Wildcard.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Wildcard.java
new file mode 100644
index 0000000..8c99f7d
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Wildcard.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/**
+ * Node to represent Wildcard
+ */
+public class Wildcard extends SingleTypeReference {
+
+    public static final int UNBOUND = 0;
+    public static final int EXTENDS = 1;
+    public static final int SUPER = 2;
+    
+	public TypeReference bound;
+	public int kind;
+
+	public Wildcard(int kind) {
+		super(WILDCARD_NAME, 0);
+		this.kind = kind;
+	}
+	
+	public char [][] getParameterizedTypeName() {
+        switch (this.kind) {
+            case Wildcard.UNBOUND : 
+               return new char[][] { WILDCARD_NAME };
+            case Wildcard.EXTENDS :
+                return new char[][] { CharOperation.concat(WILDCARD_NAME, WILDCARD_EXTENDS, CharOperation.concatWith(this.bound.getParameterizedTypeName(), '.')) };
+			default: // SUPER
+                return new char[][] { CharOperation.concat(WILDCARD_NAME, WILDCARD_SUPER, CharOperation.concatWith(this.bound.getParameterizedTypeName(), '.')) };
+        }        	    
+	}	
+
+	public char [][] getTypeName() {
+        switch (this.kind) {
+            case Wildcard.UNBOUND : 
+               return new char[][] { WILDCARD_NAME };
+            case Wildcard.EXTENDS :
+                return new char[][] { CharOperation.concat(WILDCARD_NAME, WILDCARD_EXTENDS, CharOperation.concatWith(this.bound.getTypeName(), '.')) };
+			default: // SUPER
+                return new char[][] { CharOperation.concat(WILDCARD_NAME, WILDCARD_SUPER, CharOperation.concatWith(this.bound.getTypeName(), '.')) };
+        }        	    
+	}
+	
+	private TypeBinding internalResolveType(Scope scope, ReferenceBinding genericType, int rank) {
+	    TypeBinding boundType = null;
+	    if (this.bound != null) {
+			boundType = scope.kind == Scope.CLASS_SCOPE
+	       		? this.bound.resolveType((ClassScope)scope)
+	       		: this.bound.resolveType((BlockScope)scope, true /* check bounds*/);
+	       		        
+			if (boundType == null) {
+				return null;
+			}	    
+		}
+	    WildcardBinding wildcard = scope.environment().createWildcard(genericType, rank, boundType, this.kind);
+	    return this.resolvedType = wildcard;
+	}
+	
+	public StringBuffer printExpression(int indent, StringBuffer output){
+        switch (this.kind) {
+            case Wildcard.UNBOUND : 
+                output.append(WILDCARD_NAME);
+                break;
+            case Wildcard.EXTENDS :
+                output.append(WILDCARD_NAME).append(WILDCARD_EXTENDS);
+            	this.bound.printExpression(0, output);
+            	break;
+			default: // SUPER
+                output.append(WILDCARD_NAME).append(WILDCARD_SUPER);
+            	this.bound.printExpression(0, output);
+            	break;
+        }        	    
+		return output;
+	}	
+	
+	public TypeBinding resolveTypeArgument(BlockScope blockScope, ReferenceBinding genericType, int rank) {
+	    return internalResolveType(blockScope, genericType, rank);
+	}
+	
+	public TypeBinding resolveTypeArgument(ClassScope classScope, ReferenceBinding genericType, int rank) {
+	    return internalResolveType(classScope, genericType, rank);
+	}
+
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		if (visitor.visit(this, scope)) {
+			if (this.bound != null) {
+				this.bound.traverse(visitor, scope);
+			}
+		}
+		visitor.endVisit(this, scope);
+	}
+
+	public void traverse(ASTVisitor visitor, ClassScope scope) {
+		if (visitor.visit(this, scope)) {
+			if (this.bound != null) {
+				this.bound.traverse(visitor, scope);
+			}
+		}
+		visitor.endVisit(this, scope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
index 127b0cd..57b09e0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
@@ -59,5 +59,14 @@
 	
 	// jdk level used to denote future releases: optional behavior is not enabled for now, but may become so. In order to enable these,
 	// search for references to this constant, and change it to one of the official JDT constants above.
-	long JDK_DEFERRED = Long.MAX_VALUE; 
+	long JDK_DEFERRED = Long.MAX_VALUE;
+	
+	int INT_ARRAY = 10;
+	int BYTE_ARRAY = 8;
+	int BOOLEAN_ARRAY = 4;
+	int SHORT_ARRAY = 9;
+	int CHAR_ARRAY = 5;
+	int LONG_ARRAY = 11;
+	int FLOAT_ARRAY = 6;
+	int DOUBLE_ARRAY = 7;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
index 6899fa0..20897c2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
@@ -14,33 +14,88 @@
 import java.io.IOException;
 import java.util.Arrays;
 
+import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
 import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
 import org.eclipse.jdt.internal.compiler.env.*;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.lookup.TagBits;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 public class ClassFileReader extends ClassFileStruct implements AttributeNamesConstants, IBinaryType {
+public static ClassFileReader read(File file) throws ClassFormatException, IOException {
+	return read(file, false);
+}
+public static ClassFileReader read(File file, boolean fullyInitialize) throws ClassFormatException, IOException {
+	byte classFileBytes[] = Util.getFileByteContent(file);
+	ClassFileReader classFileReader = new ClassFileReader(classFileBytes, file.getAbsolutePath().toCharArray());
+	if (fullyInitialize) {
+		classFileReader.initialize();
+	}
+	return classFileReader;
+}
+public static ClassFileReader read(
+	java.util.zip.ZipFile zip, 
+	String filename)
+	throws ClassFormatException, java.io.IOException {
+		return read(zip, filename, false);
+}
+public static ClassFileReader read(
+	java.util.zip.ZipFile zip, 
+	String filename,
+	boolean fullyInitialize)
+	throws ClassFormatException, java.io.IOException {
+	java.util.zip.ZipEntry ze = zip.getEntry(filename);
+	if (ze == null)
+		return null;
+	byte classFileBytes[] = Util.getZipEntryByteContent(ze, zip);
+	ClassFileReader classFileReader = new ClassFileReader(classFileBytes, filename.toCharArray());
+	if (fullyInitialize) {
+		classFileReader.initialize();
+	}
+	return classFileReader;
+}
+public static ClassFileReader read(String fileName) throws ClassFormatException, java.io.IOException {
+	return read(fileName, false);
+}
+public static ClassFileReader read(String fileName, boolean fullyInitialize) throws ClassFormatException, java.io.IOException {
+	return read(new File(fileName), fullyInitialize);
+}
+	private int accessFlags;
+	private char[] classFileName;
+	private char[] className;
+	private int classNameIndex;
 	private int constantPoolCount;
 	private int[] constantPoolOffsets;
-	private long version;
-	private int accessFlags;
-	private char[] className;
-	private char[] superclassName;
-	private int interfacesCount;
-	private char[][] interfaceNames;
-	private int fieldsCount;
 	private FieldInfo[] fields;
-	private int methodsCount;
-	private MethodInfo[] methods;
-	private InnerClassInfo[] innerInfos;
-	private char[] sourceFileName;
+	private int fieldsCount;
 	// initialized in case the .class file is a nested type
 	private InnerClassInfo innerInfo;
-	private char[] classFileName;
-	private int classNameIndex;
 	private int innerInfoIndex;
+	private InnerClassInfo[] innerInfos;
+	private char[][] interfaceNames;
+	private int interfacesCount;
+	private MethodInfo[] methods;
+	private int methodsCount;
+	private char[] signature;
+	private char[] sourceFileName;
+	private char[] superclassName;
+	private long tagBits;
+	private long version;
+
+/**
+ * @param classFileBytes Actual bytes of a .class file
+ * @param fileName	Actual name of the file that contains the bytes, can be null
+ * 
+ * @exception ClassFormatException
+ */
+public ClassFileReader(byte classFileBytes[], char[] fileName) throws ClassFormatException {
+	this(classFileBytes, fileName, false);
+}
+
 /**
  * @param classFileBytes byte[]
  * 		Actual bytes of a .class file
@@ -176,35 +231,62 @@
 		for (int i = 0; i < attributesCount; i++) {
 			int utf8Offset = this.constantPoolOffsets[u2At(readOffset)];
 			char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
-			if (CharOperation.equals(attributeName, DeprecatedName)) {
-				this.accessFlags |= AccDeprecated;
-			} else {
-				if (CharOperation.equals(attributeName, InnerClassName)) {
-					int innerOffset = readOffset + 6;
-					int number_of_classes = u2At(innerOffset);
-					if (number_of_classes != 0) {
-						innerOffset+= 2;
-						this.innerInfos = new InnerClassInfo[number_of_classes];
-						for (int j = 0; j < number_of_classes; j++) {
-							this.innerInfos[j] = 
-								new InnerClassInfo(reference, this.constantPoolOffsets, innerOffset); 
-							if (this.classNameIndex == this.innerInfos[j].innerClassNameIndex) {
-								this.innerInfo = this.innerInfos[j];
-								this.innerInfoIndex = j;
+			if (attributeName.length == 0) {
+				readOffset += (6 + u4At(readOffset + 2));
+				continue;
+			}
+			switch(attributeName[0] ) {
+				case 'D' :
+					if (CharOperation.equals(attributeName, DeprecatedName)) {
+						this.accessFlags |= AccDeprecated;
+					}
+					break;
+				case 'I' :
+					if (CharOperation.equals(attributeName, InnerClassName)) {
+						int innerOffset = readOffset + 6;
+						int number_of_classes = u2At(innerOffset);
+						if (number_of_classes != 0) {
+							innerOffset+= 2;
+							this.innerInfos = new InnerClassInfo[number_of_classes];
+							for (int j = 0; j < number_of_classes; j++) {
+								this.innerInfos[j] = 
+									new InnerClassInfo(reference, this.constantPoolOffsets, innerOffset); 
+								if (this.classNameIndex == this.innerInfos[j].innerClassNameIndex) {
+									this.innerInfo = this.innerInfos[j];
+									this.innerInfoIndex = j;
+								}
+								innerOffset += 8;
 							}
-							innerOffset += 8;
 						}
 					}
-				} else {
-					if (CharOperation.equals(attributeName, SourceName)) {
-						utf8Offset = this.constantPoolOffsets[u2At(readOffset + 6)];
-						this.sourceFileName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
-					} else {
-						if (CharOperation.equals(attributeName, SyntheticName)) {
-							this.accessFlags |= AccSynthetic;
+					break;
+				case 'S' :
+					if (attributeName.length > 2) {
+						switch(attributeName[1]) {
+							case 'o' :
+								if (CharOperation.equals(attributeName, SourceName)) {
+									utf8Offset = this.constantPoolOffsets[u2At(readOffset + 6)];
+									this.sourceFileName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+								}
+								break;
+							case 'y' :
+								if (CharOperation.equals(attributeName, SyntheticName)) {
+									this.accessFlags |= AccSynthetic;
+								}
+								break;
+							case 'i' :
+								if (CharOperation.equals(attributeName, SignatureName)) {
+									utf8Offset = this.constantPoolOffsets[u2At(readOffset + 6)];
+									this.signature = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));				
+								}
 						}
 					}
-				}
+					break;
+				case 'R' :
+					if (CharOperation.equals(attributeName, RuntimeVisibleAnnotationsName)) {
+						decodeStandardAnnotations(readOffset);
+					}
+					break;
 			}
 			readOffset += (6 + u4At(readOffset + 2));
 		}
@@ -221,16 +303,6 @@
 }
 
 /**
- * @param classFileBytes Actual bytes of a .class file
- * @param fileName	Actual name of the file that contains the bytes, can be null
- * 
- * @exception ClassFormatException
- */
-public ClassFileReader(byte classFileBytes[], char[] fileName) throws ClassFormatException {
-	this(classFileBytes, fileName, false);
-}
-
-/**
  * 	Answer the receiver's access flags.  The value of the access_flags
  *	item is a mask of modifiers used with class and interface declarations.
  *  @return int 
@@ -238,6 +310,207 @@
 public int accessFlags() {
 	return this.accessFlags;
 }
+private int decodeAnnotation(int offset) {
+	int readOffset = offset;
+	int utf8Offset = this.constantPoolOffsets[u2At(offset)];
+	char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+	typeName = Signature.toCharArray(typeName);
+	CharOperation.replace(typeName, '/', '.');
+	char[][] qualifiedTypeName = CharOperation.splitOn('.', typeName);
+	int numberOfPairs = u2At(offset + 2);
+	readOffset += 4;
+	switch(qualifiedTypeName.length) {
+		case 3 :
+			if (CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_DEPRECATED)) {
+				this.tagBits |= TagBits.AnnotationDeprecated;
+				return readOffset;		
+			}
+			break;
+		case 4 :
+			char[] lastPart = qualifiedTypeName[3];
+			if (lastPart.length > 0) {
+				switch(lastPart[0]) {
+					case 'R' :
+						if (CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_ANNOTATION_RETENTION)) {
+							for (int i = 0; i < numberOfPairs; i++) {
+								readOffset += 2;
+								readOffset = decodeElementValueForJavaLangAnnotationRetention(readOffset);
+							}
+							return readOffset;
+						}
+						break;
+					case 'T' :
+						if (CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_ANNOTATION_TARGET)) {
+							for (int i = 0; i < numberOfPairs; i++) {
+								readOffset += 2;
+								readOffset = decodeElementValueForJavaLangAnnotationTarget(readOffset);
+							}
+							return readOffset;		
+						}
+						break;
+					case 'D' :
+						if (CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_ANNOTATION_DOCUMENTED)) {
+							this.tagBits |= TagBits.AnnotationDocumented;
+							return readOffset;		
+						}
+						break;
+					case 'I' :
+						if (CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_ANNOTATION_INHERITED)) {
+							this.tagBits |= TagBits.AnnotationInherited;
+							return readOffset;		
+						}
+				}
+			}
+	}
+	for (int i = 0; i < numberOfPairs; i++) {
+		readOffset += 2;
+		readOffset = decodeElementValue(readOffset);
+	}
+	return readOffset;
+}
+private int decodeElementValue(int offset) {
+	int readOffset = offset;
+	int tag = u1At(readOffset);
+	readOffset++;
+	switch(tag) {
+		case 'B' :
+		case 'C' :
+		case 'D' :
+		case 'F' :
+		case 'I' :
+		case 'J' :
+		case 'S' :
+		case 'Z' :
+		case 's' :
+			readOffset += 2;
+			break;
+		case 'e' :
+			readOffset += 4;
+			break;
+		case 'c' :
+			readOffset += 2;
+			break;
+		case '@' :
+			readOffset = decodeAnnotation(readOffset);
+			break;
+		case '[' :
+			int numberOfValues = u2At(readOffset);
+			readOffset += 2;
+			for (int i = 0; i < numberOfValues; i++) {
+				readOffset = decodeElementValue(readOffset);
+			}
+			break;
+	}
+	return readOffset;
+}
+private int decodeElementValueForJavaLangAnnotationTarget(int offset) {
+	int readOffset = offset;
+	int tag = u1At(readOffset);
+	readOffset++;
+	switch(tag) {
+		case 'B' :
+		case 'C' :
+		case 'D' :
+		case 'F' :
+		case 'I' :
+		case 'J' :
+		case 'S' :
+		case 'Z' :
+		case 's' :
+			readOffset += 2;
+			break;
+		case 'e' :
+			int utf8Offset = this.constantPoolOffsets[u2At(readOffset)];
+			char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+			typeName = Signature.toCharArray(typeName);
+			CharOperation.replace(typeName, '/', '.');
+			char[][] qualifiedTypeName = CharOperation.splitOn('.', typeName);
+			readOffset += 2;
+			utf8Offset = this.constantPoolOffsets[u2At(readOffset)];
+			char[] constName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+			readOffset += 2;
+			if (qualifiedTypeName.length == 4 && CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE)) {
+				this.tagBits |= Annotation.getTargetElementType(constName);
+			}
+			break;
+		case 'c' :
+			readOffset += 2;
+			break;
+		case '@' :
+			readOffset = decodeAnnotation(readOffset);
+			break;
+		case '[' :
+			int numberOfValues = u2At(readOffset);
+			readOffset += 2;
+			if (numberOfValues == 0) {
+				this.tagBits |= TagBits.AnnotationTarget;
+			} else {
+				for (int i = 0; i < numberOfValues; i++) {
+					readOffset = decodeElementValueForJavaLangAnnotationTarget(readOffset);
+				}
+			}
+			break;
+	}
+	return readOffset;
+}
+private int decodeElementValueForJavaLangAnnotationRetention(int offset) {
+	int readOffset = offset;
+	int tag = u1At(readOffset);
+	readOffset++;
+	switch(tag) {
+		case 'B' :
+		case 'C' :
+		case 'D' :
+		case 'F' :
+		case 'I' :
+		case 'J' :
+		case 'S' :
+		case 'Z' :
+		case 's' :
+			readOffset += 2;
+			break;
+		case 'e' :
+			int utf8Offset = this.constantPoolOffsets[u2At(readOffset)];
+			char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+			typeName = Signature.toCharArray(typeName);
+			CharOperation.replace(typeName, '/', '.');
+			char[][] qualifiedTypeName = CharOperation.splitOn('.', typeName);
+			readOffset += 2;
+			utf8Offset = this.constantPoolOffsets[u2At(readOffset)];
+			char[] constName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+			readOffset += 2;
+			this.tagBits |= Annotation.getRetentionPolicy(constName);
+			if (qualifiedTypeName.length == 4 && CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_ANNOTATION_RETENTIONPOLICY)) {
+				this.tagBits |= Annotation.getRetentionPolicy(constName);
+			}
+			break;
+		case 'c' :
+			readOffset += 2;
+			break;
+		case '@' :
+			readOffset = decodeAnnotation(readOffset);
+			break;
+		case '[' :
+			int numberOfValues = u2At(readOffset);
+			readOffset += 2;
+			for (int i = 0; i < numberOfValues; i++) {
+				readOffset = decodeElementValue(readOffset); // retention policy cannot be in an array initializer
+			}
+			break;
+	}
+	return readOffset;
+}
+/**
+ * @param offset the offset is located at the beginning of the runtime visible 
+ * annotation attribute.
+ */
+private void decodeStandardAnnotations(int offset) {
+	int numberOfAnnotations = u2At(offset + 6);
+	int readOffset = offset + 8;
+	for (int i = 0; i < numberOfAnnotations; i++) {
+		readOffset = decodeAnnotation(readOffset);
+	}
+}
 /**
  * Answer the char array that corresponds to the class name of the constant class.
  * constantPoolIndex is the index in the constant pool that is a constant class entry.
@@ -275,12 +548,14 @@
 	return this.fields;
 }
 /**
- * Answer the file name which defines the type.
- * The format is unspecified.
+ * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
  */
 public char[] getFileName() {
 	return this.classFileName;
 }
+public char[] getGenericSignature() {
+	return this.signature;
+}
 /**
  * Answer the source name if the receiver is a inner type. Return null if it is an anonymous class or if the receiver is a top-level class.
  * e.g.
@@ -318,11 +593,25 @@
 public char[][] getInterfaceNames() {
 	return this.interfaceNames;
 }
+
+/**
+ * @see org.eclipse.jdt.internal.compiler.env.IGenericType#getKind()
+ */
+public int getKind() {
+	int modifiers = getModifiers();
+	if ((modifiers & AccInterface) != 0) {
+		if ((modifiers & AccAnnotation) != 0) return IGenericType.ANNOTATION_TYPE_DECL;
+		return IGenericType.INTERFACE_DECL;
+	}
+	if ((modifiers & AccEnum) != 0)	return IGenericType.ENUM_DECL;
+	return IGenericType.CLASS_DECL;
+}
 /**
  * Answer the receiver's nested types or null if the array is empty.
- *
- * This nested type info is extracted from the inner class attributes.
- * Ask the name environment to find a member type using its compound name
+ * 
+ * This nested type info is extracted from the inner class attributes. Ask the
+ * name environment to find a member type using its compound name
+ * 
  * @return org.eclipse.jdt.internal.compiler.api.IBinaryNestedType[]
  */
 public IBinaryNestedType[] getMemberTypes() {
@@ -389,11 +678,7 @@
  */
 public int getModifiers() {
 	if (this.innerInfo != null) {
-		if ((this.accessFlags & AccDeprecated) != 0) {
-			return this.innerInfo.getModifiers() | AccDeprecated;
-		} else {
-			return this.innerInfo.getModifiers();
-		}
+		return this.innerInfo.getModifiers() | (this.accessFlags & AccDeprecated);
 	}
 	return this.accessFlags;
 }
@@ -418,6 +703,9 @@
 public char[] getSuperclassName() {
 	return this.superclassName;
 }
+public long getTagBits() {
+	return this.tagBits;
+}
 /**
  * Answer the major/minor version defined in this class file according to the VM spec.
  * as a long: (major<<16)+minor
@@ -426,126 +714,56 @@
 public long getVersion() {
 	return this.version;
 }
-/**
- * Answer true if the receiver is an anonymous type, false otherwise
- *
- * @return <CODE>boolean</CODE>
- */
-public boolean isAnonymous() {
-	if (this.innerInfo == null) return false;
-	char[] sourceName = this.innerInfo.getSourceName();
-	return (sourceName == null || sourceName.length == 0);
-}
-/**
- * Answer whether the receiver contains the resolved binary form
- * or the unresolved source form of the type.
- * @return boolean
- */
-public boolean isBinaryType() {
-	return true;
-}
-/**
- * Answer true if the receiver is a class. False otherwise.
- * @return boolean
- */
-public boolean isClass() {
-	return (getModifiers() & AccInterface) == 0;
-}
-/**
- * Answer true if the receiver is an interface. False otherwise.
- * @return boolean
- */
-public boolean isInterface() {
-	return (getModifiers() & AccInterface) != 0;
-}
-/**
- * Answer true if the receiver is a local type, false otherwise
- *
- * @return <CODE>boolean</CODE>
- */
-public boolean isLocal() {
-	if (this.innerInfo == null) return false;
-	if (this.innerInfo.getEnclosingTypeName() != null) return false;
-	char[] sourceName = this.innerInfo.getSourceName();
-	return (sourceName != null && sourceName.length > 0);	
-}
-/**
- * Answer true if the receiver is a member type, false otherwise
- *
- * @return <CODE>boolean</CODE>
- */
-public boolean isMember() {
-	if (this.innerInfo == null) return false;
-	if (this.innerInfo.getEnclosingTypeName() == null) return false;
-	char[] sourceName = this.innerInfo.getSourceName();
-	return (sourceName != null && sourceName.length > 0);	 // protection against ill-formed attributes (67600)
-}
-/**
- * Answer true if the receiver is a nested type, false otherwise
- *
- * @return <CODE>boolean</CODE>
- */
-public boolean isNestedType() {
-	return this.innerInfo != null;
-}
-public static ClassFileReader read(File file) throws ClassFormatException, IOException {
-	return read(file, false);
-}
-public static ClassFileReader read(File file, boolean fullyInitialize) throws ClassFormatException, IOException {
-	byte classFileBytes[] = Util.getFileByteContent(file);
-	ClassFileReader classFileReader = new ClassFileReader(classFileBytes, file.getAbsolutePath().toCharArray());
-	if (fullyInitialize) {
-		classFileReader.initialize();
-	}
-	return classFileReader;
-}
-public static ClassFileReader read(String fileName) throws ClassFormatException, java.io.IOException {
-	return read(fileName, false);
-}
-public static ClassFileReader read(String fileName, boolean fullyInitialize) throws ClassFormatException, java.io.IOException {
-	return read(new File(fileName), fullyInitialize);
-}
-public static ClassFileReader read(
-	java.util.zip.ZipFile zip, 
-	String filename)
-	throws ClassFormatException, java.io.IOException {
-		return read(zip, filename, false);
-}
-public static ClassFileReader read(
-	java.util.zip.ZipFile zip, 
-	String filename,
-	boolean fullyInitialize)
-	throws ClassFormatException, java.io.IOException {
-	java.util.zip.ZipEntry ze = zip.getEntry(filename);
-	if (ze == null)
-		return null;
-	byte classFileBytes[] = Util.getZipEntryByteContent(ze, zip);
-	ClassFileReader classFileReader = new ClassFileReader(classFileBytes, filename.toCharArray());
-	if (fullyInitialize) {
-		classFileReader.initialize();
-	}
-	return classFileReader;
-}
+private boolean hasNonSyntheticFieldChanges(FieldInfo[] currentFieldInfos, FieldInfo[] otherFieldInfos) {
+	int length1 = currentFieldInfos == null ? 0 : currentFieldInfos.length;
+	int length2 = otherFieldInfos == null ? 0 : otherFieldInfos.length;
+	int index1 = 0;
+	int index2 = 0;
 
-/**
- * Answer the source file name attribute. Return null if there is no source file attribute for the receiver.
- * 
- * @return char[]
- */
-public char[] sourceFileName() {
-	return this.sourceFileName;
-}
-public String toString() {
-	java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
-	java.io.PrintWriter print = new java.io.PrintWriter(out);
-	
-	print.println(this.getClass().getName() + "{"); //$NON-NLS-1$
-	print.println(" this.className: " + new String(getName())); //$NON-NLS-1$
-	print.println(" this.superclassName: " + (getSuperclassName() == null ? "null" : new String(getSuperclassName()))); //$NON-NLS-2$ //$NON-NLS-1$
-	print.println(" access_flags: " + ClassFileStruct.printTypeModifiers(this.accessFlags()) + "(" + this.accessFlags() + ")"); //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-2$
+	end : while (index1 < length1 && index2 < length2) {
+		while (currentFieldInfos[index1].isSynthetic()) {
+			if (++index1 >= length1) break end;
+		}
+		while (otherFieldInfos[index2].isSynthetic()) {
+			if (++index2 >= length2) break end;
+		}
+		if (hasStructuralFieldChanges(currentFieldInfos[index1++], otherFieldInfos[index2++]))
+			return true;
+	}
 
-	print.flush();
-	return out.toString();
+	while (index1 < length1) {
+		if (!currentFieldInfos[index1++].isSynthetic()) return true;
+	}
+	while (index2 < length2) {
+		if (!otherFieldInfos[index2++].isSynthetic()) return true;
+	}
+	return false;
+}
+private boolean hasNonSyntheticMethodChanges(MethodInfo[] currentMethodInfos, MethodInfo[] otherMethodInfos) {
+	int length1 = currentMethodInfos == null ? 0 : currentMethodInfos.length;
+	int length2 = otherMethodInfos == null ? 0 : otherMethodInfos.length;
+	int index1 = 0;
+	int index2 = 0;
+
+	MethodInfo m;
+	end : while (index1 < length1 && index2 < length2) {
+		while ((m = currentMethodInfos[index1]).isSynthetic() || m.isClinit()) {
+			if (++index1 >= length1) break end;
+		}
+		while ((m = otherMethodInfos[index2]).isSynthetic() || m.isClinit()) {
+			if (++index2 >= length2) break end;
+		}
+		if (hasStructuralMethodChanges(currentMethodInfos[index1++], otherMethodInfos[index2++]))
+			return true;
+	}
+
+	while (index1 < length1) {
+		if (!((m = currentMethodInfos[index1++]).isSynthetic() || m.isClinit())) return true;
+	}
+	while (index2 < length2) {
+		if (!((m = otherMethodInfos[index2++]).isSynthetic() || m.isClinit())) return true;
+	}
+	return false;
 }
 /**
  * Check if the receiver has structural changes compare to the byte array in argument.
@@ -589,6 +807,11 @@
 		// modifiers
 		if (this.getModifiers() != newClassFile.getModifiers())
 			return true;
+
+		// meta-annotations
+		if ((this.getTagBits() & TagBits.AnnotationTargetMASK|TagBits.AnnotationDeprecated|TagBits.AnnotationRetentionMASK) != (newClassFile.getTagBits() & TagBits.AnnotationTargetMASK|TagBits.AnnotationDeprecated|TagBits.AnnotationRetentionMASK))
+			return true;
+		
 		// superclass
 		if (!CharOperation.equals(this.getSuperclassName(), newClassFile.getSuperclassName()))
 			return true;
@@ -682,34 +905,11 @@
 		return true;
 	}
 }
-private boolean hasNonSyntheticFieldChanges(FieldInfo[] currentFieldInfos, FieldInfo[] otherFieldInfos) {
-	int length1 = currentFieldInfos == null ? 0 : currentFieldInfos.length;
-	int length2 = otherFieldInfos == null ? 0 : otherFieldInfos.length;
-	int index1 = 0;
-	int index2 = 0;
-
-	end : while (index1 < length1 && index2 < length2) {
-		while (currentFieldInfos[index1].isSynthetic()) {
-			if (++index1 >= length1) break end;
-		}
-		while (otherFieldInfos[index2].isSynthetic()) {
-			if (++index2 >= length2) break end;
-		}
-		if (hasStructuralFieldChanges(currentFieldInfos[index1++], otherFieldInfos[index2++]))
-			return true;
-	}
-
-	while (index1 < length1) {
-		if (!currentFieldInfos[index1++].isSynthetic()) return true;
-	}
-	while (index2 < length2) {
-		if (!otherFieldInfos[index2++].isSynthetic()) return true;
-	}
-	return false;
-}
 private boolean hasStructuralFieldChanges(FieldInfo currentFieldInfo, FieldInfo otherFieldInfo) {
 	if (currentFieldInfo.getModifiers() != otherFieldInfo.getModifiers())
 		return true;
+	if ((currentFieldInfo.getTagBits() & TagBits.AnnotationDeprecated) != (otherFieldInfo.getTagBits() & TagBits.AnnotationDeprecated))
+		return true;
 	if (!CharOperation.equals(currentFieldInfo.getName(), otherFieldInfo.getName()))
 		return true;
 	if (!CharOperation.equals(currentFieldInfo.getTypeName(), otherFieldInfo.getTypeName()))
@@ -740,45 +940,23 @@
 				return currentConstant.doubleValue() != otherConstant.doubleValue();
 			case TypeIds.T_boolean :
 				return currentConstant.booleanValue() != otherConstant.booleanValue();
-			case TypeIds.T_String :
+			case TypeIds.T_JavaLangString :
 				return !currentConstant.stringValue().equals(otherConstant.stringValue());
 		}
 	}
 	return false;
 }
-private boolean hasNonSyntheticMethodChanges(MethodInfo[] currentMethodInfos, MethodInfo[] otherMethodInfos) {
-	int length1 = currentMethodInfos == null ? 0 : currentMethodInfos.length;
-	int length2 = otherMethodInfos == null ? 0 : otherMethodInfos.length;
-	int index1 = 0;
-	int index2 = 0;
-
-	MethodInfo m;
-	end : while (index1 < length1 && index2 < length2) {
-		while ((m = currentMethodInfos[index1]).isSynthetic() || m.isClinit()) {
-			if (++index1 >= length1) break end;
-		}
-		while ((m = otherMethodInfos[index2]).isSynthetic() || m.isClinit()) {
-			if (++index2 >= length2) break end;
-		}
-		if (hasStructuralMethodChanges(currentMethodInfos[index1++], otherMethodInfos[index2++]))
-			return true;
-	}
-
-	while (index1 < length1) {
-		if (!((m = currentMethodInfos[index1++]).isSynthetic() || m.isClinit())) return true;
-	}
-	while (index2 < length2) {
-		if (!((m = otherMethodInfos[index2++]).isSynthetic() || m.isClinit())) return true;
-	}
-	return false;
-}
 private boolean hasStructuralMethodChanges(MethodInfo currentMethodInfo, MethodInfo otherMethodInfo) {
 	if (currentMethodInfo.getModifiers() != otherMethodInfo.getModifiers())
 		return true;
+	if ((currentMethodInfo.getTagBits() & TagBits.AnnotationDeprecated) != (otherMethodInfo.getTagBits() & TagBits.AnnotationDeprecated))
+		return true;
 	if (!CharOperation.equals(currentMethodInfo.getSelector(), otherMethodInfo.getSelector()))
 		return true;
 	if (!CharOperation.equals(currentMethodInfo.getMethodDescriptor(), otherMethodInfo.getMethodDescriptor()))
 		return true;
+	if (!CharOperation.equals(currentMethodInfo.getGenericSignature(), otherMethodInfo.getGenericSignature()))
+		return true;
 
 	char[][] currentThrownExceptions = currentMethodInfo.getExceptionTypeNames();
 	char[][] otherThrownExceptions = otherMethodInfo.getExceptionTypeNames();
@@ -816,9 +994,75 @@
 		throw exception;
 	}
 }
+/**
+ * Answer true if the receiver is an anonymous type, false otherwise
+ *
+ * @return <CODE>boolean</CODE>
+ */
+public boolean isAnonymous() {
+	if (this.innerInfo == null) return false;
+	char[] sourceName = this.innerInfo.getSourceName();
+	return (sourceName == null || sourceName.length == 0);
+}
+/**
+ * Answer whether the receiver contains the resolved binary form
+ * or the unresolved source form of the type.
+ * @return boolean
+ */
+public boolean isBinaryType() {
+	return true;
+}
+
+/**
+ * Answer true if the receiver is a local type, false otherwise
+ *
+ * @return <CODE>boolean</CODE>
+ */
+public boolean isLocal() {
+	if (this.innerInfo == null) return false;
+	if (this.innerInfo.getEnclosingTypeName() != null) return false;
+	char[] sourceName = this.innerInfo.getSourceName();
+	return (sourceName != null && sourceName.length > 0);	
+}
+/**
+ * Answer true if the receiver is a member type, false otherwise
+ *
+ * @return <CODE>boolean</CODE>
+ */
+public boolean isMember() {
+	if (this.innerInfo == null) return false;
+	if (this.innerInfo.getEnclosingTypeName() == null) return false;
+	char[] sourceName = this.innerInfo.getSourceName();
+	return (sourceName != null && sourceName.length > 0);	 // protection against ill-formed attributes (67600)
+}
+/**
+ * Answer true if the receiver is a nested type, false otherwise
+ *
+ * @return <CODE>boolean</CODE>
+ */
+public boolean isNestedType() {
+	return this.innerInfo != null;
+}
 protected void reset() {
 	this.constantPoolOffsets = null;
 	super.reset();
 }
-
+/**
+ * Answer the source file name attribute. Return null if there is no source file attribute for the receiver.
+ * 
+ * @return char[]
+ */
+public char[] sourceFileName() {
+	return this.sourceFileName;
+}
+public String toString() {
+	java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
+	java.io.PrintWriter print = new java.io.PrintWriter(out);
+	print.println(this.getClass().getName() + "{"); //$NON-NLS-1$
+	print.println(" this.className: " + new String(getName())); //$NON-NLS-1$
+	print.println(" this.superclassName: " + (getSuperclassName() == null ? "null" : new String(getSuperclassName()))); //$NON-NLS-2$ //$NON-NLS-1$
+	print.println(" access_flags: " + ClassFileStruct.printTypeModifiers(this.accessFlags()) + "(" + this.accessFlags() + ")"); //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-2$
+	print.flush();
+	return out.toString();
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.java
index 72f1646..019ff5e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.java
@@ -10,6 +10,7 @@
 import java.io.PrintStream;
 import java.io.PrintWriter;
 public class ClassFormatException extends Exception {
+	
 	public static final int ErrBadMagic = 1;
 	public static final int ErrBadMinorVersion = 2;
 	public static final int ErrBadMajorVersion = 3;
@@ -40,6 +41,8 @@
 	public static final int ErrInvalidMethodName = 27;
 	public static final int ErrInvalidMethodSignature = 28;
 
+	private static final long serialVersionUID = 6667458511042774540L; // backward compatible
+
 	private int errorCode;
 	private int bufferPosition;
 	private RuntimeException nestedException;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
index 26392d8..b986492 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.classfmt;
 
+import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
 import org.eclipse.jdt.internal.compiler.env.IBinaryField;
@@ -23,18 +24,21 @@
 import org.eclipse.jdt.internal.compiler.impl.LongConstant;
 import org.eclipse.jdt.internal.compiler.impl.ShortConstant;
 import org.eclipse.jdt.internal.compiler.impl.StringConstant;
+import org.eclipse.jdt.internal.compiler.lookup.TagBits;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 public class FieldInfo extends ClassFileStruct implements AttributeNamesConstants, IBinaryField, Comparable, TypeIds {
-	private Constant constant;
-	private boolean isDeprecated;
-	private boolean isSynthetic;
-	private int[] constantPoolOffsets;
 	private int accessFlags;
+	private int attributeBytes;
+	private Constant constant;
+	private int[] constantPoolOffsets;
+	private char[] descriptor;
 	private char[] name;
 	private char[] signature;
-	private int attributeBytes;
+	private int signatureUtf8Offset;
+	private long tagBits;	
 	private Object wrappedConstantValue;
 /**
  * @param classFileBytes byte[]
@@ -47,11 +51,105 @@
 	accessFlags = -1;
 	int attributesCount = u2At(6);
 	int readOffset = 8;
+	this.signatureUtf8Offset = -1;
 	for (int i = 0; i < attributesCount; i++) {
+		// check the name of each attribute
+		int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset;
+		char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+		if (attributeName.length > 0) {
+			switch(attributeName[0]) {
+				case 'S' :
+					if (CharOperation.equals(AttributeNamesConstants.SignatureName, attributeName)) {
+						this.signatureUtf8Offset = constantPoolOffsets[u2At(readOffset + 6)] - structOffset;
+					}
+					break;
+				case 'R' :
+					if (CharOperation.equals(attributeName, RuntimeVisibleAnnotationsName)) {
+						decodeStandardAnnotations(readOffset);
+					}
+			}
+		}
 		readOffset += (6 + u4At(readOffset + 2));
 	}
 	attributeBytes = readOffset;
 }
+
+public int compareTo(Object o) {
+	if (!(o instanceof FieldInfo)) {
+		throw new ClassCastException();
+	}
+	return new String(this.getName()).compareTo(new String(((FieldInfo) o).getName()));
+}
+private int decodeAnnotation(int offset) {
+	int readOffset = offset;
+	int utf8Offset = this.constantPoolOffsets[u2At(offset)] - structOffset;
+	char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+	typeName = Signature.toCharArray(typeName);
+	CharOperation.replace(typeName, '/', '.');
+	char[][] qualifiedTypeName = CharOperation.splitOn('.', typeName);
+	int numberOfPairs = u2At(offset + 2);
+	readOffset += 4;
+	if (qualifiedTypeName.length == 3) {
+		char[] lastPart = qualifiedTypeName[2];
+		if (lastPart[0] == 'D') {
+			if (CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_DEPRECATED)) {
+				this.tagBits |= TagBits.AnnotationDeprecated;
+				return readOffset;		
+			}
+		}
+	}
+	for (int i = 0; i < numberOfPairs; i++) {
+		readOffset += 2;
+		readOffset = decodeElementValue(readOffset);
+	}
+	return readOffset;
+}
+private int decodeElementValue(int offset) {
+	int readOffset = offset;
+	int tag = u1At(readOffset);
+	readOffset++;
+	switch(tag) {
+		case 'B' :
+		case 'C' :
+		case 'D' :
+		case 'F' :
+		case 'I' :
+		case 'J' :
+		case 'S' :
+		case 'Z' :
+		case 's' :
+			readOffset += 2;
+			break;
+		case 'e' :
+			readOffset += 4;
+			break;
+		case 'c' :
+			readOffset += 2;
+			break;
+		case '@' :
+			readOffset += decodeAnnotation(readOffset);
+			break;
+		case '[' :
+			int numberOfValues = u2At(readOffset);
+			readOffset += 2;
+			for (int i = 0; i < numberOfValues; i++) {
+				readOffset = decodeElementValue(readOffset);
+			}
+			break;
+	}
+	return readOffset;
+}
+/**
+ * @param offset the offset is located at the beginning of the runtime visible 
+ * annotation attribute.
+ */
+private void decodeStandardAnnotations(int offset) {
+	int numberOfAnnotations = u2At(offset + 6);
+	int readOffset = offset + 8;
+	for (int i = 0; i < numberOfAnnotations; i++) {
+		readOffset = decodeAnnotation(readOffset);
+	}
+}
 /**
  * Return the constant of the field.
  * Return org.eclipse.jdt.internal.compiler.impl.Constant.NotAConstant if there is none.
@@ -64,6 +162,16 @@
 	}
 	return constant;
 }
+public char[] getGenericSignature() {
+	if (this.signatureUtf8Offset != -1) {
+		if (this.signature == null) {
+			// decode the signature
+			this.signature = utf8At(this.signatureUtf8Offset + 3, u2At(this.signatureUtf8Offset + 1));
+		}
+		return this.signature;
+	}
+	return null;
+}
 /**
  * Answer an int whose bits are set according the access constants
  * defined by the VM spec.
@@ -71,18 +179,12 @@
  * @return int
  */
 public int getModifiers() {
-	if (accessFlags == -1) {
+	if (this.accessFlags == -1) {
 		// compute the accessflag. Don't forget the deprecated attribute
-		accessFlags = u2At(0);
-		readDeprecatedAndSyntheticAttributes();
-		if (isDeprecated) {
-			accessFlags |= AccDeprecated;
-		}
-		if (isSynthetic) {
-			accessFlags |= AccSynthetic;
-		}
+		this.accessFlags = u2At(0);
+		readModifierRelatedAttributes();
 	}
-	return accessFlags;
+	return this.accessFlags;
 }
 /**
  * Answer the name of the field.
@@ -96,6 +198,9 @@
 	}
 	return name;
 }
+public long getTagBits() {
+	return this.tagBits;
+}
 /**
  * Answer the resolved name of the receiver's type in the
  * class file format as specified in section 4.3.2 of the Java 2 VM spec.
@@ -108,12 +213,12 @@
  * @return char[]
  */
 public char[] getTypeName() {
-	if (signature == null) {
+	if (descriptor == null) {
 		// read the signature
 		int utf8Offset = constantPoolOffsets[u2At(4)] - structOffset;
-		signature = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+		descriptor = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
 	}
-	return signature;
+	return descriptor;
 }
 /**
  * Return a wrapper that contains the constant of the field.
@@ -149,7 +254,7 @@
 				case T_long :
 					this.wrappedConstantValue = new Long(fieldConstant.longValue());
 					break;
-				case T_String :
+				case T_JavaLangString :
 					this.wrappedConstantValue = fieldConstant.stringValue();
 			}
 		}
@@ -164,6 +269,18 @@
 	return getConstant() != Constant.NotAConstant;
 }
 /**
+ * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos
+ * will be therefore fully initialized and we can get rid of the bytes.
+ */
+void initialize() {
+	getModifiers();
+	getName();
+	getConstant();
+	getTypeName();
+	getGenericSignature();
+	reset();
+}
+/**
  * Return true if the field is a synthetic field, false otherwise.
  * @return boolean
  */
@@ -233,20 +350,32 @@
 		constant = Constant.NotAConstant;
 	}
 }
-private void readDeprecatedAndSyntheticAttributes() {
+private void readModifierRelatedAttributes() {
 	int attributesCount = u2At(6);
 	int readOffset = 8;
 	for (int i = 0; i < attributesCount; i++) {
 		int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset;
 		char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
-		if (CharOperation.equals(attributeName, DeprecatedName)) {
-			isDeprecated = true;
-		} else if (CharOperation.equals(attributeName, SyntheticName)) {
-			isSynthetic = true;
+		// test added for obfuscated .class file. See 79772
+		if (attributeName.length != 0) {
+			switch(attributeName[0]) {
+				case 'D' :
+					if (CharOperation.equals(attributeName, DeprecatedName))
+						this.accessFlags |= AccDeprecated;
+					break;
+				case 'S' :
+					if (CharOperation.equals(attributeName, SyntheticName))
+						this.accessFlags |= AccSynthetic;
+					break;
+			}
 		}
 		readOffset += (6 + u4At(readOffset + 2));
 	}
 }
+protected void reset() {
+	this.constantPoolOffsets = null;
+	super.reset();
+}
 /**
  * Answer the size of the receiver in bytes.
  * 
@@ -281,26 +410,4 @@
 		.toString(); 
 }
 
-public int compareTo(Object o) {
-	if (!(o instanceof FieldInfo)) {
-		throw new ClassCastException();
-	}
-	return new String(this.getName()).compareTo(new String(((FieldInfo) o).getName()));
-}
-/**
- * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos
- * will be therefore fully initialized and we can get rid of the bytes.
- */
-void initialize() {
-	getModifiers();
-	getName();
-	getConstant();
-	getTypeName();
-	reset();
-}
-protected void reset() {
-	this.constantPoolOffsets = null;
-	super.reset();
-}
-
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
index c9255be..7a27b96 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
@@ -10,20 +10,25 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.classfmt;
 
+import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
 import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
+import org.eclipse.jdt.internal.compiler.lookup.TagBits;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 
 public class MethodInfo extends ClassFileStruct implements IBinaryMethod, AttributeNamesConstants, Comparable {
-	private char[][] exceptionNames;
-	private int[] constantPoolOffsets;
-	private boolean isDeprecated;
-	private boolean isSynthetic;
+	static private final char[][] noException = CharOperation.NO_CHAR_CHAR;
 	private int accessFlags;
+	private int attributeBytes;
+	private int[] constantPoolOffsets;
+	private char[] descriptor;
+	private char[][] exceptionNames;
 	private char[] name;
 	private char[] signature;
-	private int attributeBytes;
-	static private final char[][] noException = CharOperation.NO_CHAR_CHAR;
+	private int signatureUtf8Offset;
+	private long tagBits;	
+	
 /**
  * @param classFileBytes byte[]
  * @param offsets int[]
@@ -35,11 +40,108 @@
 	accessFlags = -1;
 	int attributesCount = u2At(6);
 	int readOffset = 8;
+	this.signatureUtf8Offset = -1;
 	for (int i = 0; i < attributesCount; i++) {
+		// check the name of each attribute
+		int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset;
+		char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+		if (attributeName.length > 0) {
+			switch(attributeName[0]) {
+				case 'S' :
+					if (CharOperation.equals(AttributeNamesConstants.SignatureName, attributeName)) {
+						this.signatureUtf8Offset = constantPoolOffsets[u2At(readOffset + 6)] - structOffset;
+					}
+					break;
+				case 'R' :
+					if (CharOperation.equals(attributeName, RuntimeVisibleAnnotationsName)) {
+						decodeStandardAnnotations(readOffset);
+					}
+			}
+		}
 		readOffset += (6 + u4At(readOffset + 2));
 	}
 	attributeBytes = readOffset;
 }
+public int compareTo(Object o) {
+	if (!(o instanceof MethodInfo)) {
+		throw new ClassCastException();
+	}
+
+	MethodInfo otherMethod = (MethodInfo) o;
+	int result = new String(this.getSelector()).compareTo(new String(otherMethod.getSelector()));
+	if (result != 0) return result;
+	return new String(this.getMethodDescriptor()).compareTo(new String(otherMethod.getMethodDescriptor()));
+}
+private int decodeAnnotation(int offset) {
+	int readOffset = offset;
+	int utf8Offset = this.constantPoolOffsets[u2At(offset)] - structOffset;
+	char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+	typeName = Signature.toCharArray(typeName);
+	CharOperation.replace(typeName, '/', '.');
+	char[][] qualifiedTypeName = CharOperation.splitOn('.', typeName);
+	int numberOfPairs = u2At(offset + 2);
+	readOffset += 4;
+	if (qualifiedTypeName.length == 3) {
+		char[] lastPart = qualifiedTypeName[2];
+		if (lastPart[0] == 'D') {
+			if (CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_DEPRECATED)) {
+				this.tagBits |= TagBits.AnnotationDeprecated;
+				return readOffset;		
+			}
+		}
+	}
+	for (int i = 0; i < numberOfPairs; i++) {
+		readOffset += 2;
+		readOffset = decodeElementValue(readOffset);
+	}
+	return readOffset;
+}
+private int decodeElementValue(int offset) {
+	int readOffset = offset;
+	int tag = u1At(readOffset);
+	readOffset++;
+	switch(tag) {
+		case 'B' :
+		case 'C' :
+		case 'D' :
+		case 'F' :
+		case 'I' :
+		case 'J' :
+		case 'S' :
+		case 'Z' :
+		case 's' :
+			readOffset += 2;
+			break;
+		case 'e' :
+			readOffset += 4;
+			break;
+		case 'c' :
+			readOffset += 2;
+			break;
+		case '@' :
+			readOffset += decodeAnnotation(readOffset);
+			break;
+		case '[' :
+			int numberOfValues = u2At(readOffset);
+			readOffset += 2;
+			for (int i = 0; i < numberOfValues; i++) {
+				readOffset = decodeElementValue(readOffset);
+			}
+			break;
+	}
+	return readOffset;
+}
+/**
+ * @param offset the offset is located at the beginning of the runtime visible 
+ * annotation attribute.
+ */
+private void decodeStandardAnnotations(int offset) {
+	int numberOfAnnotations = u2At(offset + 6);
+	int readOffset = offset + 8;
+	for (int i = 0; i < numberOfAnnotations; i++) {
+		readOffset = decodeAnnotation(readOffset);
+	}
+}
 /**
  * @see org.eclipse.jdt.internal.compiler.env.IGenericMethod#getArgumentNames()
  */
@@ -60,6 +162,16 @@
 	}
 	return exceptionNames;
 }
+public char[] getGenericSignature() {
+	if (this.signatureUtf8Offset != -1) {
+		if (this.signature == null) {
+			// decode the signature
+			this.signature = utf8At(this.signatureUtf8Offset + 3, u2At(this.signatureUtf8Offset + 1));
+		}
+		return this.signature;
+	}
+	return null;
+}
 /**
  * Answer the receiver's method descriptor which describes the parameter &
  * return types as specified in section 4.3.3 of the Java 2 VM spec.
@@ -70,12 +182,12 @@
  * @return char[]
  */
 public char[] getMethodDescriptor() {
-	if (signature == null) {
+	if (descriptor == null) {
 		// read the name
 		int utf8Offset = constantPoolOffsets[u2At(4)] - structOffset;
-		signature = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+		descriptor = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
 	}
-	return signature;
+	return descriptor;
 }
 /**
  * Answer an int whose bits are set according the access constants
@@ -84,18 +196,12 @@
  * @return int
  */
 public int getModifiers() {
-	if (accessFlags == -1) {
+	if (this.accessFlags == -1) {
 		// compute the accessflag. Don't forget the deprecated attribute
-		accessFlags = u2At(0);
-		readDeprecatedAndSyntheticAttributes();
-		if (isDeprecated) {
-			accessFlags |= AccDeprecated;
-		}
-		if (isSynthetic) {
-			accessFlags |= AccSynthetic;
-		}
+		this.accessFlags = u2At(0);
+		readModifierRelatedAttributes();
 	}
-	return accessFlags;
+	return this.accessFlags;
 }
 /**
  * Answer the name of the method.
@@ -111,6 +217,21 @@
 	}
 	return name;
 }
+public long getTagBits() {
+	return this.tagBits;
+}
+/**
+ * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos
+ * will be therefore fully initialized and we can get rid of the bytes.
+ */
+void initialize() {
+	getModifiers();
+	getSelector();
+	getMethodDescriptor();
+	getExceptionTypeNames();
+	getGenericSignature();
+	reset();
+}
 /**
  * Answer true if the method is a class initializer, false otherwise.
  * @return boolean
@@ -134,20 +255,6 @@
 public boolean isSynthetic() {
 	return (getModifiers() & AccSynthetic) != 0;
 }
-private void readDeprecatedAndSyntheticAttributes() {
-	int attributesCount = u2At(6);
-	int readOffset = 8;
-	for (int i = 0; i < attributesCount; i++) {
-		int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset;
-		char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
-		if (CharOperation.equals(attributeName, DeprecatedName)) {
-			isDeprecated = true;
-		} else if (CharOperation.equals(attributeName, SyntheticName)) {
-			isSynthetic = true;
-		}
-		readOffset += (6 + u4At(readOffset + 2));
-	}
-}
 private void readExceptionAttributes() {
 	int attributesCount = u2At(6);
 	int readOffset = 8;
@@ -180,6 +287,36 @@
 		exceptionNames = noException;
 	}
 }
+private void readModifierRelatedAttributes() {
+	int attributesCount = u2At(6);
+	int readOffset = 8;
+	for (int i = 0; i < attributesCount; i++) {
+		int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset;
+		char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+		// test added for obfuscated .class file. See 79772
+		if (attributeName.length != 0) {
+			switch(attributeName[0]) {
+				case 'D' :
+					if (CharOperation.equals(attributeName, DeprecatedName))
+						this.accessFlags |= AccDeprecated;
+					break;
+				case 'S' :
+					if (CharOperation.equals(attributeName, SyntheticName))
+						this.accessFlags |= AccSynthetic;
+					break;
+				case 'A' :
+					if (CharOperation.equals(attributeName, AnnotationDefaultName))
+						this.accessFlags |= AccAnnotationDefault;
+					break;
+			}
+		}
+		readOffset += (6 + u4At(readOffset + 2));
+	}
+}
+protected void reset() {
+	this.constantPoolOffsets = null;
+	super.reset();
+}
 /**
  * Answer the size of the receiver in bytes.
  * 
@@ -190,6 +327,9 @@
 }
 public String toString() {
 	int modifiers = getModifiers();
+	char[] desc = getGenericSignature();
+	if (desc == null)
+		desc = getMethodDescriptor();
 	StringBuffer buffer = new StringBuffer(this.getClass().getName());
 	return buffer
 		.append("{") //$NON-NLS-1$
@@ -201,36 +341,10 @@
 				+ ((modifiers & 0x0008) == 0x000008 ? "static " : "") //$NON-NLS-1$ //$NON-NLS-2$
 				+ ((modifiers & 0x0010) == 0x0010 ? "final " : "") //$NON-NLS-1$ //$NON-NLS-2$
 				+ ((modifiers & 0x0040) == 0x0040 ? "volatile " : "") //$NON-NLS-1$ //$NON-NLS-2$
-				+ ((modifiers & 0x0080) == 0x0080 ? "transient " : "")) //$NON-NLS-1$ //$NON-NLS-2$
+				+ ((modifiers & 0x0080) == 0x0080 ? "varargs " : "")) //$NON-NLS-1$ //$NON-NLS-2$
 		.append(getSelector())
-		.append(getMethodDescriptor())
+		.append(desc)
 		.append("}") //$NON-NLS-1$
 		.toString(); 
 }
-public int compareTo(Object o) {
-	if (!(o instanceof MethodInfo)) {
-		throw new ClassCastException();
-	}
-
-	MethodInfo otherMethod = (MethodInfo) o;
-	int result = new String(this.getSelector()).compareTo(new String(otherMethod.getSelector()));
-	if (result != 0) return result;
-	return new String(this.getMethodDescriptor()).compareTo(new String(otherMethod.getMethodDescriptor()));
-}
-
-/**
- * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos
- * will be therefore fully initialized and we can get rid of the bytes.
- */
-void initialize() {
-	getModifiers();
-	getSelector();
-	getMethodDescriptor();
-	getExceptionTypeNames();
-	reset();
-}
-protected void reset() {
-	this.constantPoolOffsets = null;
-	super.reset();
-}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java
index 577b9bd..a49ff00 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java
@@ -11,13 +11,21 @@
 package org.eclipse.jdt.internal.compiler.codegen;
 
 public interface AttributeNamesConstants {
-	final char[] SyntheticName = new char[] {'S', 'y', 'n', 't', 'h', 'e', 't', 'i', 'c'};
-	final char[] ConstantValueName = new char[] {'C', 'o', 'n', 's', 't', 'a', 'n', 't', 'V', 'a', 'l', 'u', 'e'};
-	final char[] LineNumberTableName = new char[] {'L', 'i', 'n', 'e', 'N', 'u', 'm', 'b', 'e', 'r', 'T', 'a', 'b', 'l', 'e'};
-	final char[] LocalVariableTableName = new char[] {'L', 'o', 'c', 'a', 'l', 'V', 'a', 'r', 'i', 'a', 'b', 'l', 'e', 'T', 'a', 'b', 'l', 'e'};
-	final char[] InnerClassName = new char[] {'I', 'n', 'n', 'e', 'r', 'C', 'l', 'a', 's', 's', 'e', 's'};
-	final char[] CodeName = new char[] {'C', 'o', 'd', 'e'};
-	final char[] ExceptionsName = new char[] {'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n', 's'};
-	final char[] SourceName = new char[] {'S', 'o', 'u', 'r', 'c', 'e', 'F', 'i', 'l', 'e'};
-	final char[] DeprecatedName = new char[] {'D', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd'};
+	final char[] SyntheticName = "Synthetic".toCharArray(); //$NON-NLS-1$
+	final char[] ConstantValueName = "ConstantValue".toCharArray(); //$NON-NLS-1$
+	final char[] LineNumberTableName = "LineNumberTable".toCharArray(); //$NON-NLS-1$
+	final char[] LocalVariableTableName = "LocalVariableTable".toCharArray(); //$NON-NLS-1$
+	final char[] InnerClassName = "InnerClasses".toCharArray(); //$NON-NLS-1$
+	final char[] CodeName = "Code".toCharArray(); //$NON-NLS-1$
+	final char[] ExceptionsName = "Exceptions".toCharArray(); //$NON-NLS-1$
+	final char[] SourceName = "SourceFile".toCharArray(); //$NON-NLS-1$
+	final char[] DeprecatedName = "Deprecated".toCharArray(); //$NON-NLS-1$
+	final char[] SignatureName = "Signature".toCharArray(); //$NON-NLS-1$
+	final char[] LocalVariableTypeTableName = "LocalVariableTypeTable".toCharArray(); //$NON-NLS-1$
+	final char[] EnclosingMethodName = "EnclosingMethod".toCharArray(); //$NON-NLS-1$
+	final char[] AnnotationDefaultName = "AnnotationDefault".toCharArray(); //$NON-NLS-1$
+	final char[] RuntimeInvisibleAnnotationsName = "RuntimeInvisibleAnnotations".toCharArray(); //$NON-NLS-1$
+	final char[] RuntimeVisibleAnnotationsName = "RuntimeVisibleAnnotations".toCharArray(); //$NON-NLS-1$
+	final char[] RuntimeInvisibleParameterAnnotationsName = "RuntimeInvisibleParameterAnnotations".toCharArray(); //$NON-NLS-1$
+	final char[] RuntimeVisibleParameterAnnotationsName = "RuntimeVisibleParameterAnnotations".toCharArray(); //$NON-NLS-1$
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
index 4d7a6ef..343c4e6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
@@ -49,7 +49,9 @@
 	public AbstractMethodDeclaration methodDeclaration;
 	public ExceptionLabel[] exceptionHandlers = new ExceptionLabel[LABELS_INCREMENT];
 	static ExceptionLabel[] noExceptionHandlers = new ExceptionLabel[LABELS_INCREMENT];
-	public int exceptionHandlersNumber;
+	public int exceptionHandlersIndex;
+	public int exceptionHandlersCounter;
+	
 	public static FieldBinding[] ImplicitThis = new FieldBinding[] {};
 	public boolean generateLineNumberAttributes;
 	public boolean generateLocalVariableTableAttributes;
@@ -65,11 +67,15 @@
 	public boolean wideMode = false;
 	public static final CompilationResult RESTART_IN_WIDE_MODE = new CompilationResult((char[])null, 0, 0, 0);
 	
-public CodeStream(ClassFile classFile) {
-	generateLineNumberAttributes = (classFile.produceDebugAttributes & CompilerOptions.Lines) != 0;
-	generateLocalVariableTableAttributes = (classFile.produceDebugAttributes & CompilerOptions.Vars) != 0;
-	if (generateLineNumberAttributes) {
-		lineSeparatorPositions = classFile.referenceBinding.scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions;
+	// target level to manage different code generation between different target levels
+	private long targetLevel;
+	
+public CodeStream(ClassFile classFile, long targetLevel) {
+	this.targetLevel = targetLevel;
+	this.generateLineNumberAttributes = (classFile.produceDebugAttributes & CompilerOptions.Lines) != 0;
+	this.generateLocalVariableTableAttributes = (classFile.produceDebugAttributes & CompilerOptions.Vars) != 0;
+	if (this.generateLineNumberAttributes) {
+		this.lineSeparatorPositions = classFile.referenceBinding.scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions;
 	}
 }
 final public void aaload() {
@@ -248,7 +254,7 @@
 	}
 	position++;
 	bCodeStream[classFileOffset++] = OPC_anewarray;
-	writeUnsignedShort(constantPool.literalIndex(typeBinding));
+	writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName()));
 }
 final public void areturn() {
 	if (DEBUG) System.out.println(position + "\t\tareturn"); //$NON-NLS-1$
@@ -482,14 +488,14 @@
 	bCodeStream[classFileOffset++] = OPC_castore;
 }
 public final void checkcast(TypeBinding typeBinding) {
-	if (DEBUG) System.out.println(position + "\t\tcheckcast:"+typeBinding); //$NON-NLS-1$
+	if (DEBUG) System.out.println(position + "\t\tcheckcast:"+typeBinding.debugName()); //$NON-NLS-1$
 	countLabels = 0;
 	if (classFileOffset + 2 >= bCodeStream.length) {
 		resizeByteArray();
 	}
 	position++;
 	bCodeStream[classFileOffset++] = OPC_checkcast;
-	writeUnsignedShort(constantPool.literalIndex(typeBinding));
+	writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName()));
 }
 final public void d2f() {
 	if (DEBUG) System.out.println(position + "\t\td2f"); //$NON-NLS-1$
@@ -1260,80 +1266,85 @@
 		this.getTYPE(accessedType.id);
 		return;
 	}
-	endLabel = new Label(this);
 
-	if (syntheticFieldBinding != null) { // non interface case
-		this.getstatic(syntheticFieldBinding);
-		this.dup();
-		this.ifnonnull(endLabel);
-		this.pop();
-	}
-
-	/* Macro for building a class descriptor object... using or not a field cache to store it into...
-	this sequence is responsible for building the actual class descriptor.
-	
-	If the fieldCache is set, then it is supposed to be the body of a synthetic access method
-	factoring the actual descriptor creation out of the invocation site (saving space).
-	If the fieldCache is nil, then we are dumping the bytecode on the invocation site, since
-	we have no way to get a hand on the field cache to do better. */
-
-
-	// Wrap the code in an exception handler to convert a ClassNotFoundException into a NoClassDefError
-
-	anyExceptionHandler = new ExceptionLabel(this, BaseTypes.NullBinding /* represents ClassNotFoundException*/);
-	this.ldc(accessedType == BaseTypes.NullBinding ? "java.lang.Object" : String.valueOf(accessedType.constantPoolName()).replace('/', '.')); //$NON-NLS-1$
-	this.invokeClassForName();
-
-	/* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=37565
-	if (accessedType == BaseTypes.NullBinding) {
-		this.ldc("java.lang.Object"); //$NON-NLS-1$
-	} else if (accessedType.isArrayType()) {
-		this.ldc(String.valueOf(accessedType.constantPoolName()).replace('/', '.'));
+	if (this.targetLevel >= ClassFileConstants.JDK1_5) {
+		// generation using the new ldc_w bytecode
+		this.ldc(accessedType);
 	} else {
-		// we make it an array type (to avoid class initialization)
-		this.ldc("[L" + String.valueOf(accessedType.constantPoolName()).replace('/', '.') + ";"); //$NON-NLS-1$//$NON-NLS-2$
+		endLabel = new Label(this);
+		if (syntheticFieldBinding != null) { // non interface case
+			this.getstatic(syntheticFieldBinding);
+			this.dup();
+			this.ifnonnull(endLabel);
+			this.pop();
+		}
+
+		/* Macro for building a class descriptor object... using or not a field cache to store it into...
+		this sequence is responsible for building the actual class descriptor.
+		
+		If the fieldCache is set, then it is supposed to be the body of a synthetic access method
+		factoring the actual descriptor creation out of the invocation site (saving space).
+		If the fieldCache is nil, then we are dumping the bytecode on the invocation site, since
+		we have no way to get a hand on the field cache to do better. */
+	
+	
+		// Wrap the code in an exception handler to convert a ClassNotFoundException into a NoClassDefError
+	
+		anyExceptionHandler = new ExceptionLabel(this, BaseTypes.NullBinding /* represents ClassNotFoundException*/);
+		this.ldc(accessedType == BaseTypes.NullBinding ? "java.lang.Object" : String.valueOf(accessedType.constantPoolName()).replace('/', '.')); //$NON-NLS-1$
+		this.invokeClassForName();
+	
+		/* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=37565
+		if (accessedType == BaseTypes.NullBinding) {
+			this.ldc("java.lang.Object"); //$NON-NLS-1$
+		} else if (accessedType.isArrayType()) {
+			this.ldc(String.valueOf(accessedType.constantPoolName()).replace('/', '.'));
+		} else {
+			// we make it an array type (to avoid class initialization)
+			this.ldc("[L" + String.valueOf(accessedType.constantPoolName()).replace('/', '.') + ";"); //$NON-NLS-1$//$NON-NLS-2$
+		}
+		this.invokeClassForName();
+		if (!accessedType.isArrayType()) { // extract the component type, which doesn't initialize the class
+			this.invokeJavaLangClassGetComponentType();
+		}	
+		*/
+		/* We need to protect the runtime code from binary inconsistencies
+		in case the accessedType is missing, the ClassNotFoundException has to be converted
+		into a NoClassDefError(old ex message), we thus need to build an exception handler for this one. */
+		anyExceptionHandler.placeEnd();
+	
+		if (syntheticFieldBinding != null) { // non interface case
+			this.dup();
+			this.putstatic(syntheticFieldBinding);
+		}
+		this.goto_(endLabel);
+	
+	
+		// Generate the body of the exception handler
+		saveStackSize = stackDepth;
+		stackDepth = 1;
+		/* ClassNotFoundException on stack -- the class literal could be doing more things
+		on the stack, which means that the stack may not be empty at this point in the
+		above code gen. So we save its state and restart it from 1. */
+	
+		anyExceptionHandler.place();
+	
+		// Transform the current exception, and repush and throw a 
+		// NoClassDefFoundError(ClassNotFound.getMessage())
+	
+		this.newNoClassDefFoundError();
+		this.dup_x1();
+		this.swap();
+	
+		// Retrieve the message from the old exception
+		this.invokeThrowableGetMessage();
+	
+		// Send the constructor taking a message string as an argument
+		this.invokeNoClassDefFoundErrorStringConstructor();
+		this.athrow();
+		stackDepth = saveStackSize;
+		endLabel.place();
 	}
-	this.invokeClassForName();
-	if (!accessedType.isArrayType()) { // extract the component type, which doesn't initialize the class
-		this.invokeJavaLangClassGetComponentType();
-	}	
-	*/
-	/* We need to protect the runtime code from binary inconsistencies
-	in case the accessedType is missing, the ClassNotFoundException has to be converted
-	into a NoClassDefError(old ex message), we thus need to build an exception handler for this one. */
-	anyExceptionHandler.placeEnd();
-
-	if (syntheticFieldBinding != null) { // non interface case
-		this.dup();
-		this.putstatic(syntheticFieldBinding);
-	}
-	this.goto_(endLabel);
-
-
-	// Generate the body of the exception handler
-	saveStackSize = stackDepth;
-	stackDepth = 1;
-	/* ClassNotFoundException on stack -- the class literal could be doing more things
-	on the stack, which means that the stack may not be empty at this point in the
-	above code gen. So we save its state and restart it from 1. */
-
-	anyExceptionHandler.place();
-
-	// Transform the current exception, and repush and throw a 
-	// NoClassDefFoundError(ClassNotFound.getMessage())
-
-	this.newNoClassDefFoundError();
-	this.dup_x1();
-	this.swap();
-
-	// Retrieve the message from the old exception
-	this.invokeThrowableGetMessage();
-
-	// Send the constructor taking a message string as an argument
-	this.invokeNoClassDefFoundErrorStringConstructor();
-	this.athrow();
-	endLabel.place();
-	stackDepth = saveStackSize;
 }
 /**
  * This method generates the code attribute bytecode
@@ -1346,41 +1357,57 @@
 	athrow();
 }
 public void generateConstant(Constant constant, int implicitConversionCode) {
-	int targetTypeID = implicitConversionCode >> 4;
-	switch (targetTypeID) {
-		case T_boolean :
-			generateInlinedValue(constant.booleanValue());
-			break;
-		case T_char :
-			generateInlinedValue(constant.charValue());
-			break;
-		case T_byte :
-			generateInlinedValue(constant.byteValue());
-			break;
-		case T_short :
-			generateInlinedValue(constant.shortValue());
-			break;
-		case T_int :
-			generateInlinedValue(constant.intValue());
-			break;
-		case T_long :
-			generateInlinedValue(constant.longValue());
-			break;
-		case T_float :
-			generateInlinedValue(constant.floatValue());
-			break;
-		case T_double :
-			generateInlinedValue(constant.doubleValue());
-			break;
-		default : //String or Object
-			ldc(constant.stringValue());
+	int targetTypeID = (implicitConversionCode & IMPLICIT_CONVERSION_MASK) >> 4;
+	if (targetTypeID != 0) {
+		switch (targetTypeID) {
+			case T_boolean :
+				generateInlinedValue(constant.booleanValue());
+				break;
+			case T_char :
+				generateInlinedValue(constant.charValue());
+				break;
+			case T_byte :
+				generateInlinedValue(constant.byteValue());
+				break;
+			case T_short :
+				generateInlinedValue(constant.shortValue());
+				break;
+			case T_int :
+				generateInlinedValue(constant.intValue());
+				break;
+			case T_long :
+				generateInlinedValue(constant.longValue());
+				break;
+			case T_float :
+				generateInlinedValue(constant.floatValue());
+				break;
+			case T_double :
+				generateInlinedValue(constant.doubleValue());
+				break;
+			case T_JavaLangString :
+				ldc(constant.stringValue());
+		}
+	} else {
+		ldc(constant.stringValue());
+	}
+	if ((implicitConversionCode & BOXING) != 0) {
+		// need boxing
+		generateBoxingConversion(targetTypeID);
 	}
 }
+
 /**
+ * Generates the sequence of instructions which will perform the conversion of the expression
+ * on the stack into a different type (e.g. long l = someInt; --> i2l must be inserted).
  * @param implicitConversionCode int
  */
 public void generateImplicitConversion(int implicitConversionCode) {
-	switch (implicitConversionCode) {
+	if ((implicitConversionCode & UNBOXING) != 0) {
+		final int typeId = implicitConversionCode & COMPILE_TYPE_MASK;
+		generateUnboxingConversion(typeId);
+		// unboxing can further involve base type conversions
+	}
+	switch (implicitConversionCode & IMPLICIT_CONVERSION_MASK) {
 		case Float2Char :
 			this.f2i();
 			this.i2c();
@@ -1477,6 +1504,11 @@
 		case Float2Long :
 			this.f2l();
 	}
+	if ((implicitConversionCode & BOXING) != 0) {
+		// need to unbox/box the constant
+		final int typeId = (implicitConversionCode & IMPLICIT_CONVERSION_MASK) >> 4;
+		generateBoxingConversion(typeId);
+	}
 }
 public void generateInlinedValue(byte inlinedValue) {
 	switch (inlinedValue) {
@@ -1699,27 +1731,27 @@
  * @param oper1 the first expression
  * @param oper2 the second expression
  */
-public void generateStringAppend(BlockScope blockScope, Expression oper1, Expression oper2) {
+public void generateStringConcatenationAppend(BlockScope blockScope, Expression oper1, Expression oper2) {
 	int pc;
 	if (oper1 == null) {
 		/* Operand is already on the stack, and maybe nil:
 		note type1 is always to  java.lang.String here.*/
-		this.newStringBuffer();
+		this.newStringContatenation();
 		this.dup_x1();
 		this.swap();
 		// If argument is reference type, need to transform it 
 		// into a string (handles null case)
-		this.invokeStringValueOf(T_Object);
-		this.invokeStringBufferStringConstructor();
+		this.invokeStringValueOf(T_JavaLangObject);
+		this.invokeStringConcatenationStringConstructor();
 	} else {
 		pc = position;
-		oper1.generateOptimizedStringBufferCreation(blockScope, this, oper1.implicitConversion & 0xF);
+		oper1.generateOptimizedStringConcatenationCreation(blockScope, this, oper1.implicitConversion & COMPILE_TYPE_MASK);
 		this.recordPositionsFrom(pc, oper1.sourceStart);
 	}
 	pc = position;
-	oper2.generateOptimizedStringBuffer(blockScope, this, oper2.implicitConversion & 0xF);
+	oper2.generateOptimizedStringConcatenation(blockScope, this, oper2.implicitConversion & COMPILE_TYPE_MASK);
 	this.recordPositionsFrom(pc, oper2.sourceStart);
-	this.invokeStringBufferToString();
+	this.invokeStringConcatenationToString();
 }
 /**
  * Code responsible to generate the suitable code to supply values for the synthetic enclosing
@@ -1795,7 +1827,7 @@
 /**
  * @param accessBinding the access method binding to generate
  */
-public void generateSyntheticBodyForConstructorAccess(SyntheticAccessMethodBinding accessBinding) {
+public void generateSyntheticBodyForConstructorAccess(SyntheticMethodBinding accessBinding) {
 
 	initializeMaxLocals(accessBinding);
 
@@ -1804,8 +1836,14 @@
 	int length = parameters.length;
 	int resolvedPosition = 1;
 	this.aload_0();
-	if (constructorBinding.declaringClass.isNestedType()) {
-		NestedTypeBinding nestedType = (NestedTypeBinding) constructorBinding.declaringClass;
+	// special name&ordinal argument generation for enum constructors
+	TypeBinding declaringClass = constructorBinding.declaringClass;
+	if (declaringClass.erasure().id == T_JavaLangEnum || declaringClass.isEnum()) {
+		this.aload_1(); // pass along name param as name arg
+		this.iload_2(); // pass along ordinal param as ordinal arg
+	}	
+	if (declaringClass.isNestedType()) {
+		NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;
 		SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticEnclosingInstances();
 		for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) {
 			TypeBinding type;
@@ -1824,8 +1862,8 @@
 			resolvedPosition++;
 	}
 	
-	if (constructorBinding.declaringClass.isNestedType()) {
-		NestedTypeBinding nestedType = (NestedTypeBinding) constructorBinding.declaringClass;
+	if (declaringClass.isNestedType()) {
+		NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;
 		SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticOuterLocalVariables();
 		for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) {
 			TypeBinding type;
@@ -1839,7 +1877,82 @@
 	this.invokespecial(constructorBinding);
 	this.return_();
 }
-public void generateSyntheticBodyForFieldReadAccess(SyntheticAccessMethodBinding accessBinding) {
+//static X[] values() {
+// X[] values;
+// int length;
+// X[] result;
+// System.arraycopy(values = $VALUES, 0, result = new X[length= values.length], 0, length)
+// return result;
+//}
+public void generateSyntheticBodyForEnumValues(SyntheticMethodBinding methodBinding) {
+	ClassScope scope = ((SourceTypeBinding)methodBinding.declaringClass).scope;
+	FieldBinding enumValuesSyntheticfield = scope.referenceContext.enumValuesSyntheticfield;
+	initializeMaxLocals(methodBinding);
+	TypeBinding enumArray = methodBinding.returnType;
+	
+	this.getstatic(enumValuesSyntheticfield);
+	this.dup();
+	this.astore_0();
+	this.iconst_0();
+	this.aload_0();
+	this.arraylength();
+	this.dup();
+	this.istore_1();
+	this.newArray((ArrayBinding) enumArray);
+	this.dup();
+	this.astore_2();
+	this.iconst_0();
+	this.iload_1();
+	this.invokeSystemArraycopy();
+	this.aload_2();
+	this.areturn();
+}
+//static X valueOf(String name) {
+// X[] values;
+// for (int i = (values = $VALUES).length; --i >= 0;) {
+// 		 X value;
+// 		 if (name.equals(value = values[i].name())) return value;
+// }
+// throw new IllegalArgumentException(name);
+//}		
+public void generateSyntheticBodyForEnumValueOf(SyntheticMethodBinding methodBinding) {
+	ClassScope scope = ((SourceTypeBinding)methodBinding.declaringClass).scope;
+	FieldBinding enumValuesSyntheticfield = scope.referenceContext.enumValuesSyntheticfield;
+	initializeMaxLocals(methodBinding);
+	Label loopCond = new Label(this);
+	Label loopStart = new Label(this);
+	Label wrongConstant = new Label(this);
+
+	this.getstatic(enumValuesSyntheticfield);
+	this.dup();
+	this.astore_1();
+	this.arraylength();
+	this.istore_2();
+	this.goto_(loopCond);
+	loopStart.place();
+	this.aload_0();
+	this.aload_1();
+	this.iload_2();
+	this.aaload();
+	this.dup();
+	this.astore_3();
+	this.invokeJavaLangEnumname(this.classFile.referenceBinding);
+	this.invokeStringEquals();
+	this.ifeq(wrongConstant);
+	this.aload_3();
+	this.areturn();
+	wrongConstant.place();
+	loopCond.place();
+	this.iinc(2, -1);		
+	this.iload_2();
+	this.ifge(loopStart);
+	this.newJavaLangIllegalArgumentException();
+	this.dup();
+	this.aload_0();
+	this.invokeJavaLangIllegalArgumentExceptionStringConstructor();
+	this.athrow();
+}
+public void generateSyntheticBodyForFieldReadAccess(SyntheticMethodBinding accessBinding) {
 	initializeMaxLocals(accessBinding);
 	FieldBinding fieldBinding = accessBinding.targetReadField;
 	TypeBinding type;
@@ -1866,7 +1979,7 @@
 	} else
 		this.areturn();
 }
-public void generateSyntheticBodyForFieldWriteAccess(SyntheticAccessMethodBinding accessBinding) {
+public void generateSyntheticBodyForFieldWriteAccess(SyntheticMethodBinding accessBinding) {
 	initializeMaxLocals(accessBinding);
 	FieldBinding fieldBinding = accessBinding.targetWriteField;
 	if (fieldBinding.isStatic()) {
@@ -1879,12 +1992,15 @@
 	}
 	this.return_();
 }
-public void generateSyntheticBodyForMethodAccess(SyntheticAccessMethodBinding accessBinding) {
+public void generateSyntheticBodyForMethodAccess(SyntheticMethodBinding accessBinding) {
 
 	initializeMaxLocals(accessBinding);
 	MethodBinding methodBinding = accessBinding.targetMethod;
 	TypeBinding[] parameters = methodBinding.parameters;
 	int length = parameters.length;
+	TypeBinding[] arguments = accessBinding.kind == SyntheticMethodBinding.BridgeMethod 
+													? accessBinding.parameters
+													: null;
 	int resolvedPosition;
 	if (methodBinding.isStatic())
 		resolvedPosition = 0;
@@ -1893,8 +2009,16 @@
 		resolvedPosition = 1;
 	}
 	for (int i = 0; i < length; i++) {
-		load(parameters[i], resolvedPosition);
-		if ((parameters[i] == DoubleBinding) || (parameters[i] == LongBinding))
+	    TypeBinding parameter = parameters[i];
+	    if (arguments != null) { // for bridge methods
+		    TypeBinding argument = arguments[i];
+			load(argument, resolvedPosition);
+			if (argument != parameter) 
+			    checkcast(parameter);
+	    } else {
+			load(parameter, resolvedPosition);
+		}
+		if ((parameter == DoubleBinding) || (parameter == LongBinding))
 			resolvedPosition += 2;
 		else
 			resolvedPosition++;
@@ -1906,10 +2030,10 @@
 		if (methodBinding.isConstructor()
 			|| methodBinding.isPrivate()
 			// qualified super "X.super.foo()" targets methods from superclass
-			|| accessBinding.accessType == SyntheticAccessMethodBinding.SuperMethodAccess){
+			|| accessBinding.kind == SyntheticMethodBinding.SuperMethodAccess){
 			this.invokespecial(methodBinding);
 		} else {
-			if (methodBinding.declaringClass.isInterface()){
+			if ((methodBinding.declaringClass.modifiers & AccInterface) != 0) { // interface or annotation type
 				this.invokeinterface(methodBinding);
 			} else {
 				this.invokevirtual(methodBinding);
@@ -1936,6 +2060,172 @@
 	else
 		this.areturn();
 }
+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); //$NON-NLS-1$
+			break;
+		case T_short :
+			// invokestatic: Short.valueOf(short)
+			this.invoke(
+				OPC_invokestatic,
+				1, // argCount
+				1, // return type size
+				ConstantPool.JavaLangShortConstantPoolName,
+				ConstantPool.ValueOf,
+				ConstantPool.shortShortSignature); //$NON-NLS-1$
+			break;
+		case T_char :
+			// invokestatic: Character.valueOf(char)
+			this.invoke(
+				OPC_invokestatic,
+				1, // argCount
+				1, // return type size
+				ConstantPool.JavaLangCharacterConstantPoolName,
+				ConstantPool.ValueOf,
+				ConstantPool.charCharacterSignature); //$NON-NLS-1$
+			break;
+		case T_int :
+			// invokestatic: Integer.valueOf(int)
+			this.invoke(
+				OPC_invokestatic,
+				1, // argCount
+				1, // return type size
+				ConstantPool.JavaLangIntegerConstantPoolName,
+				ConstantPool.ValueOf,
+				ConstantPool.IntIntegerSignature); //$NON-NLS-1$
+			break;
+		case T_long :
+			// invokestatic: Long.valueOf(long)
+			this.invoke(
+				OPC_invokestatic,
+				2, // argCount
+				1, // return type size
+				ConstantPool.JavaLangLongConstantPoolName,
+				ConstantPool.ValueOf,
+				ConstantPool.longLongSignature); //$NON-NLS-1$
+			break;
+		case T_float :
+			// invokestatic: Float.valueOf(float)
+			this.invoke(
+				OPC_invokestatic,
+				1, // argCount
+				1, // return type size
+				ConstantPool.JavaLangFloatConstantPoolName,
+				ConstantPool.ValueOf,
+				ConstantPool.floatFloatSignature); //$NON-NLS-1$
+			break;
+		case T_double :
+			// invokestatic: Double.valueOf(double)
+			this.invoke(
+				OPC_invokestatic,
+				2, // argCount
+				1, // return type size
+				ConstantPool.JavaLangDoubleConstantPoolName,
+				ConstantPool.ValueOf,
+				ConstantPool.doubleDoubleSignature); //$NON-NLS-1$
+			break;
+		case T_boolean :
+			// invokestatic: Boolean.valueOf(boolean)
+			this.invoke(
+				OPC_invokestatic,
+				1, // argCount
+				1, // return type size
+				ConstantPool.JavaLangBooleanConstantPoolName,
+				ConstantPool.ValueOf,
+				ConstantPool.booleanBooleanSignature); //$NON-NLS-1$
+	}
+}
+public void generateUnboxingConversion(int unboxedTypeID) {
+	switch (unboxedTypeID) {
+		case T_byte :
+			// invokevirtual: byteValue()
+			this.invoke(
+					OPC_invokevirtual,
+					0, // argCount
+					1, // return type size
+					ConstantPool.JavaLangByteConstantPoolName,
+					ConstantPool.BYTEVALUE_BYTE_METHOD_NAME,
+					ConstantPool.BYTEVALUE_BYTE_METHOD_SIGNATURE);
+			break;
+		case T_short :
+			// invokevirtual: shortValue()
+			this.invoke(
+					OPC_invokevirtual,
+					0, // argCount
+					1, // return type size
+					ConstantPool.JavaLangShortConstantPoolName,
+					ConstantPool.SHORTVALUE_SHORT_METHOD_NAME,
+					ConstantPool.SHORTVALUE_SHORT_METHOD_SIGNATURE);
+			break;
+		case T_char :
+			// invokevirtual: charValue()
+			this.invoke(
+					OPC_invokevirtual,
+					0, // argCount
+					1, // return type size
+					ConstantPool.JavaLangCharacterConstantPoolName,
+					ConstantPool.CHARVALUE_CHARACTER_METHOD_NAME,
+					ConstantPool.CHARVALUE_CHARACTER_METHOD_SIGNATURE);
+			break;
+		case T_int :
+			// invokevirtual: intValue()
+			this.invoke(
+					OPC_invokevirtual,
+					0, // argCount
+					1, // return type size
+					ConstantPool.JavaLangIntegerConstantPoolName,
+					ConstantPool.INTVALUE_INTEGER_METHOD_NAME,
+					ConstantPool.INTVALUE_INTEGER_METHOD_SIGNATURE);
+			break;
+		case T_long :
+			// invokevirtual: longValue()
+			this.invoke(
+					OPC_invokevirtual,
+					0, // argCount
+					2, // return type size
+					ConstantPool.JavaLangLongConstantPoolName,
+					ConstantPool.LONGVALUE_LONG_METHOD_NAME,
+					ConstantPool.LONGVALUE_LONG_METHOD_SIGNATURE);
+			break;
+		case T_float :
+			// invokevirtual: floatValue()
+			this.invoke(
+					OPC_invokevirtual,
+					0, // argCount
+					1, // return type size
+					ConstantPool.JavaLangFloatConstantPoolName,
+					ConstantPool.FLOATVALUE_FLOAT_METHOD_NAME,
+					ConstantPool.FLOATVALUE_FLOAT_METHOD_SIGNATURE);
+			break;
+		case T_double :
+			// invokevirtual: doubleValue()
+			this.invoke(
+					OPC_invokevirtual,
+					0, // argCount
+					2, // return type size
+					ConstantPool.JavaLangDoubleConstantPoolName,
+					ConstantPool.DOUBLEVALUE_DOUBLE_METHOD_NAME,
+					ConstantPool.DOUBLEVALUE_DOUBLE_METHOD_SIGNATURE);
+			break;
+		case T_boolean :
+			// invokevirtual: booleanValue()
+			this.invoke(
+					OPC_invokevirtual,
+					0, // argCount
+					1, // return type size
+					ConstantPool.JavaLangBooleanConstantPoolName,
+					ConstantPool.BOOLEANVALUE_BOOLEAN_METHOD_NAME,
+					ConstantPool.BOOLEANVALUE_BOOLEAN_METHOD_SIGNATURE);
+	}
+}
 final public byte[] getContents() {
 	byte[] contents;
 	System.arraycopy(bCodeStream, 0, contents = new byte[position], 0, position);
@@ -1943,88 +2233,161 @@
 }
 final public void getfield(FieldBinding fieldBinding) {
 	if (DEBUG) System.out.println(position + "\t\tgetfield:"+fieldBinding); //$NON-NLS-1$
-	countLabels = 0;
+	int returnTypeSize = 1;
 	if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) {
-		if (++stackDepth > stackMax)
-			stackMax = stackDepth;
+		returnTypeSize = 2;
+	}
+	generateFieldAccess(
+			OPC_getfield,
+			returnTypeSize,
+			fieldBinding.declaringClass.constantPoolName(),
+			fieldBinding.name,
+			fieldBinding.type.signature());
+}
+private void generateFieldAccess(byte opcode, int returnTypeSize, char[] declaringClass, char[] name, char[] signature) {
+	countLabels = 0;
+	switch(opcode) {
+		case OPC_getfield :
+			if (returnTypeSize == 2) {
+				stackDepth++;
+			}
+			break;
+		case OPC_getstatic :
+			if (returnTypeSize == 2) {
+				stackDepth += 2;
+			} else {
+				stackDepth++;
+			}
+			break;
+		case OPC_putfield :
+			if (returnTypeSize == 2) {
+				stackDepth -= 3;
+			} else {
+				stackDepth -= 2;
+			}
+			break;
+		case OPC_putstatic :
+			if (returnTypeSize == 2) {
+				stackDepth -= 2;
+			} else {
+				stackDepth--;
+			}
+	}
+	if (stackDepth > stackMax) {
+		stackMax = stackDepth;
 	}
 	if (classFileOffset + 2 >= bCodeStream.length) {
 		resizeByteArray();
 	}
 	position++;
-	bCodeStream[classFileOffset++] = OPC_getfield;
-	writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+	bCodeStream[classFileOffset++] = opcode;
+	writeUnsignedShort(constantPool.literalIndexForField(declaringClass, name, signature));
 }
 final public void getstatic(FieldBinding fieldBinding) {
 	if (DEBUG) System.out.println(position + "\t\tgetstatic:"+fieldBinding); //$NON-NLS-1$
-	countLabels = 0;
-	if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long))
-		stackDepth += 2;
-	else
-		stackDepth += 1;
-	if (stackDepth > stackMax)
-		stackMax = stackDepth;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
+	int returnTypeSize = 1;
+	if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) {
+		returnTypeSize = 2;
 	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_getstatic;
-	writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+	generateFieldAccess(
+			OPC_getstatic,
+			returnTypeSize,
+			fieldBinding.declaringClass.constantPoolName(),
+			fieldBinding.name,
+			fieldBinding.type.signature());
 }
 public void getTYPE(int baseTypeID) {
 	countLabels = 0;
-	if (++stackDepth > stackMax)
-		stackMax = stackDepth;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_getstatic;
 	switch (baseTypeID) {
 		case T_byte :
 			// getstatic: java.lang.Byte.TYPE			
 			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Byte.TYPE"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangByteTYPE());
+			generateFieldAccess(
+					OPC_getstatic,
+					1,
+					ConstantPool.JavaLangByteConstantPoolName,
+					ConstantPool.TYPE,
+					ConstantPool.JavaLangClassSignature);
 			break;
 		case T_short :
 			// getstatic: java.lang.Short.TYPE			
 			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Short.TYPE"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangShortTYPE());
+			generateFieldAccess(
+					OPC_getstatic,
+					1,
+					ConstantPool.JavaLangShortConstantPoolName,
+					ConstantPool.TYPE,
+					ConstantPool.JavaLangClassSignature);
 			break;
 		case T_char :
 			// getstatic: java.lang.Character.TYPE			
 			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Character.TYPE"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangCharacterTYPE());
+			generateFieldAccess(
+					OPC_getstatic,
+					1,
+					ConstantPool.JavaLangCharacterConstantPoolName,
+					ConstantPool.TYPE,
+					ConstantPool.JavaLangClassSignature);
 			break;
 		case T_int :
 			// getstatic: java.lang.Integer.TYPE			
 			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Integer.TYPE"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangIntegerTYPE());
+			generateFieldAccess(
+					OPC_getstatic,
+					1,
+					ConstantPool.JavaLangIntegerConstantPoolName,
+					ConstantPool.TYPE,
+					ConstantPool.JavaLangClassSignature);
 			break;
 		case T_long :
 			// getstatic: java.lang.Long.TYPE			
 			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Long.TYPE"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangLongTYPE());
+			generateFieldAccess(
+					OPC_getstatic,
+					1,
+					ConstantPool.JavaLangLongConstantPoolName,
+					ConstantPool.TYPE,
+					ConstantPool.JavaLangClassSignature);
 			break;
 		case T_float :
 			// getstatic: java.lang.Float.TYPE			
 			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Float.TYPE"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangFloatTYPE());
+			generateFieldAccess(
+					OPC_getstatic,
+					1,
+					ConstantPool.JavaLangFloatConstantPoolName,
+					ConstantPool.TYPE,
+					ConstantPool.JavaLangClassSignature);
 			break;
 		case T_double :
 			// getstatic: java.lang.Double.TYPE			
 			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Double.TYPE"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangDoubleTYPE());
+			generateFieldAccess(
+					OPC_getstatic,
+					1,
+					ConstantPool.JavaLangDoubleConstantPoolName,
+					ConstantPool.TYPE,
+					ConstantPool.JavaLangClassSignature);
 			break;
 		case T_boolean :
 			// getstatic: java.lang.Boolean.TYPE			
 			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Boolean.TYPE"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangBooleanTYPE());
+			generateFieldAccess(
+					OPC_getstatic,
+					1,
+					ConstantPool.JavaLangBooleanConstantPoolName,
+					ConstantPool.TYPE,
+					ConstantPool.JavaLangClassSignature);
 			break;
 		case T_void :
 			// getstatic: java.lang.Void.TYPE
 			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Void.TYPE"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangVoidTYPE());
+			generateFieldAccess(
+					OPC_getstatic,
+					1,
+					ConstantPool.JavaLangVoidConstantPoolName,
+					ConstantPool.TYPE,
+					ConstantPool.JavaLangClassSignature);
 			break;
 	}
 }
@@ -2691,7 +3054,8 @@
 		noExceptionHandlers = new ExceptionLabel[length];
 	}
 	System.arraycopy(noExceptionHandlers, 0, exceptionHandlers, 0, length);
-	exceptionHandlersNumber = 0;
+	exceptionHandlersIndex = 0;
+	exceptionHandlersCounter = 0;
 	
 	length = labels.length;
 	if (noLabels.length < length) {
@@ -2710,38 +3074,47 @@
  */
 public void initializeMaxLocals(MethodBinding methodBinding) {
 
-	maxLocals = (methodBinding == null || methodBinding.isStatic()) ? 0 : 1;
+	if (methodBinding == null) {
+		this.maxLocals = 0;
+		return;
+	}
+	
+	this.maxLocals = methodBinding.isStatic() ? 0 : 1;
+	
+	// take into account enum constructor synthetic name+ordinal
+	if (methodBinding.isConstructor() && methodBinding.declaringClass.isEnum()) {
+		this.maxLocals += 2; // String and int (enum constant name+ordinal)
+	}
+	
 	// take into account the synthetic parameters
-	if (methodBinding != null) {
-		if (methodBinding.isConstructor() && methodBinding.declaringClass.isNestedType()) {
-			ReferenceBinding enclosingInstanceTypes[];
-			if ((enclosingInstanceTypes = methodBinding.declaringClass.syntheticEnclosingInstanceTypes()) != null) {
-				for (int i = 0, max = enclosingInstanceTypes.length; i < max; i++) {
-					maxLocals++; // an enclosingInstanceType can only be a reference binding. It cannot be
-					// LongBinding or DoubleBinding
-				}
+	if (methodBinding.isConstructor() && methodBinding.declaringClass.isNestedType()) {
+		ReferenceBinding enclosingInstanceTypes[];
+		if ((enclosingInstanceTypes = methodBinding.declaringClass.syntheticEnclosingInstanceTypes()) != null) {
+			for (int i = 0, max = enclosingInstanceTypes.length; i < max; i++) {
+				this.maxLocals++; // an enclosingInstanceType can only be a reference binding. It cannot be
+				// LongBinding or DoubleBinding
 			}
-			SyntheticArgumentBinding syntheticArguments[];
-			if ((syntheticArguments = methodBinding.declaringClass.syntheticOuterLocalVariables()) != null) {
-				for (int i = 0, max = syntheticArguments.length; i < max; i++) {
-					TypeBinding argType;
-					if (((argType = syntheticArguments[i].type) == LongBinding) || (argType == DoubleBinding)) {
-						maxLocals += 2;
-					} else {
-						maxLocals++;
-					}
+		}
+		SyntheticArgumentBinding syntheticArguments[];
+		if ((syntheticArguments = methodBinding.declaringClass.syntheticOuterLocalVariables()) != null) {
+			for (int i = 0, max = syntheticArguments.length; i < max; i++) {
+				TypeBinding argType;
+				if (((argType = syntheticArguments[i].type) == LongBinding) || (argType == DoubleBinding)) {
+					this.maxLocals += 2;
+				} else {
+					this.maxLocals++;
 				}
 			}
 		}
-		TypeBinding[] arguments;
-		if ((arguments = methodBinding.parameters) != null) {
-			for (int i = 0, max = arguments.length; i < max; i++) {
-				TypeBinding argType;
-				if (((argType = arguments[i]) == LongBinding) || (argType == DoubleBinding)) {
-					maxLocals += 2;
-				} else {
-					maxLocals++;
-				}
+	}
+	TypeBinding[] arguments;
+	if ((arguments = methodBinding.parameters) != null) {
+		for (int i = 0, max = arguments.length; i < max; i++) {
+			TypeBinding argType;
+			if (((argType = arguments[i]) == LongBinding) || (argType == DoubleBinding)) {
+				this.maxLocals += 2;
+			} else {
+				this.maxLocals++;
 			}
 		}
 	}
@@ -2792,45 +3165,53 @@
 	}
 	position++;
 	bCodeStream[classFileOffset++] = OPC_instanceof;
-	writeUnsignedShort(constantPool.literalIndex(typeBinding));
+	writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName()));
 }
 public void invokeClassForName() {
 	// invokestatic: java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class;
 	if (DEBUG) System.out.println(position + "\t\tinvokestatic: java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class;"); //$NON-NLS-1$
-	countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_invokestatic;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangClassForName());
+	this.invoke(
+		OPC_invokestatic,
+		1, // argCount
+		1, // return type size
+		ConstantPool.JavaLangClassConstantPoolName,
+		ConstantPool.ForName,
+		ConstantPool.ForNameSignature);
 }
-
 public void invokeJavaLangClassDesiredAssertionStatus() {
 	// invokevirtual: java.lang.Class.desiredAssertionStatus()Z;
 	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Class.desiredAssertionStatus()Z;"); //$NON-NLS-1$
-	countLabels = 0;
-	stackDepth--;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_invokevirtual;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangClassDesiredAssertionStatus());
+	this.invoke(
+			OPC_invokevirtual,
+			0, // argCount
+			1, // return type size
+			ConstantPool.JavaLangClassConstantPoolName,
+			ConstantPool.DesiredAssertionStatus,
+			ConstantPool.DesiredAssertionStatusSignature);
 }
 
 public void invokeJavaLangClassGetComponentType() {
 	// invokevirtual: java.lang.Class.getComponentType()java.lang.Class;
 	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Class.getComponentType()java.lang.Class;"); //$NON-NLS-1$
-	countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_invokevirtual;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangClassGetComponentType());
+	this.invoke(
+			OPC_invokevirtual,
+			0, // argCount
+			1, // return type size
+			ConstantPool.JavaLangClassConstantPoolName,
+			ConstantPool.GetComponentType,
+			ConstantPool.GetComponentTypeSignature);
 }
-
+public void invokeEnumOrdinal(char[] enumTypeConstantPoolName) {
+	// invokevirtual: <enumConstantPoolName>.ordinal()
+	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: "+new String(enumTypeConstantPoolName)+".ordinal()"); //$NON-NLS-1$ //$NON-NLS-2$
+	this.invoke(
+			OPC_invokevirtual,
+			0, // argCount
+			1, // return type size
+			enumTypeConstantPoolName,
+			ConstantPool.Ordinal,
+			ConstantPool.OrdinalSignature);
+}
 final public void invokeinterface(MethodBinding methodBinding) {
 	// initialized to 1 to take into account this  immediately
 	if (DEBUG) System.out.println(position + "\t\tinvokeinterface: " + methodBinding); //$NON-NLS-1$
@@ -2868,37 +3249,35 @@
 public void invokeJavaLangErrorConstructor() {
 	// invokespecial: java.lang.Error<init>(Ljava.lang.String;)V
 	if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.Error<init>(Ljava.lang.String;)V"); //$NON-NLS-1$
-	countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_invokespecial;
-	stackDepth -= 2;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangErrorConstructor());
+	this.invoke(
+			OPC_invokespecial,
+			1, // argCount
+			0, // return type size
+			ConstantPool.JavaLangErrorConstantPoolName,
+			ConstantPool.Init,
+			ConstantPool.StringConstructorSignature);
 }
 public void invokeNoClassDefFoundErrorStringConstructor() {
 	// invokespecial: java.lang.NoClassDefFoundError.<init>(Ljava.lang.String;)V
 	if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.NoClassDefFoundError.<init>(Ljava.lang.String;)V"); //$NON-NLS-1$
-	countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_invokespecial;
-	stackDepth -= 2;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangNoClassDefFoundErrorStringConstructor());
+	this.invoke(
+			OPC_invokespecial,
+			1, // argCount
+			0, // return type size
+			ConstantPool.JavaLangNoClassDefFoundErrorConstantPoolName,
+			ConstantPool.Init,
+			ConstantPool.StringConstructorSignature);
 }
 public void invokeObjectGetClass() {
 	// invokevirtual: java.lang.Object.getClass()Ljava.lang.Class;
 	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Object.getClass()Ljava.lang.Class;"); //$NON-NLS-1$
-	countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_invokevirtual;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangObjectGetClass());
+	this.invoke(
+			OPC_invokevirtual,
+			0, // argCount
+			1, // return type size
+			ConstantPool.JavaLangObjectConstantPoolName,
+			ConstantPool.GetClass,
+			ConstantPool.GetClassSignature);
 }
 
 final public void invokespecial(MethodBinding methodBinding) {
@@ -2984,121 +3363,393 @@
  * The equivalent code performs a string conversion of the TOS
  * @param typeID <CODE>int</CODE>
  */
-public void invokeStringBufferAppendForType(int typeID) {
-	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.StringBuffer.append(...)"); //$NON-NLS-1$
-	countLabels = 0;
-	int usedTypeID;
-	if (typeID == T_null)
-		usedTypeID = T_String;
-	else
-		usedTypeID = typeID;
-	// invokevirtual
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
+public void invokeStringConcatenationAppendForType(int typeID) {
+	if (DEBUG) {
+		if (this.targetLevel >= JDK1_5) {
+			System.out.println(position + "\t\tinvokevirtual: java.lang.StringBuilder.append(...)"); //$NON-NLS-1$
+		} else {
+			System.out.println(position + "\t\tinvokevirtual: java.lang.StringBuffer.append(...)"); //$NON-NLS-1$
+		}
 	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_invokevirtual;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferAppend(typeID));
-	if ((usedTypeID == T_long) || (usedTypeID == T_double))
-		stackDepth -= 2;
-	else
-		stackDepth--;
+	int argCount = 1;
+	int returnType = 1;
+	char[] declarinClass = null;
+	char[] selector = ConstantPool.Append;
+	char[] signature = null;
+	switch (typeID) {
+		case T_int :
+		case T_byte :
+		case T_short :
+			if (this.targetLevel >= JDK1_5) {
+				declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+				signature = ConstantPool.StringBuilderAppendIntSignature;
+			} else {
+				declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+				signature = ConstantPool.StringBufferAppendIntSignature;
+			}
+			break;
+		case T_long :
+			if (this.targetLevel >= JDK1_5) {
+				declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+				signature = ConstantPool.StringBuilderAppendLongSignature;
+			} else {
+				declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+				signature = ConstantPool.StringBufferAppendLongSignature;
+			}
+			argCount = 2;
+			break;
+		case T_float :
+			if (this.targetLevel >= JDK1_5) {
+				declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+				signature = ConstantPool.StringBuilderAppendFloatSignature;
+			} else {
+				declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+				signature = ConstantPool.StringBufferAppendFloatSignature;
+			}
+			break;
+		case T_double :
+			if (this.targetLevel >= JDK1_5) {
+				declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+				signature = ConstantPool.StringBuilderAppendDoubleSignature;
+			} else {
+				declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+				signature = ConstantPool.StringBufferAppendDoubleSignature;
+			}
+			argCount = 2;
+			break;
+		case T_char :
+			if (this.targetLevel >= JDK1_5) {
+				declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+				signature = ConstantPool.StringBuilderAppendCharSignature;
+			} else {
+				declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+				signature = ConstantPool.StringBufferAppendCharSignature;
+			}
+			break;
+		case T_boolean :
+			if (this.targetLevel >= JDK1_5) {
+				declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+				signature = ConstantPool.StringBuilderAppendBooleanSignature;
+			} else {
+				declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+				signature = ConstantPool.StringBufferAppendBooleanSignature;
+			}
+			break;
+		case T_undefined :
+		case T_JavaLangObject :
+		case T_null :
+			if (this.targetLevel >= JDK1_5) {
+				declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+				signature = ConstantPool.StringBuilderAppendObjectSignature;
+			} else {
+				declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+				signature = ConstantPool.StringBufferAppendObjectSignature;
+			}
+			break;
+		case T_JavaLangString :
+			if (this.targetLevel >= JDK1_5) {
+				declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+				signature = ConstantPool.StringBuilderAppendStringSignature;
+			} else {
+				declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+				signature = ConstantPool.StringBufferAppendStringSignature;
+			}
+			break;
+	}
+	this.invoke(
+			OPC_invokevirtual,
+			argCount, // argCount
+			returnType, // return type size
+			declarinClass,
+			selector,
+			signature);
 }
 
 public void invokeJavaLangAssertionErrorConstructor(int typeBindingID) {
 	// invokespecial: java.lang.AssertionError.<init>(typeBindingID)V
 	if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.AssertionError.<init>(typeBindingID)V"); //$NON-NLS-1$
-	countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
+	int argCount = 1;
+	char[] signature = null;
+	switch (typeBindingID) {
+		case T_int :
+		case T_byte :
+		case T_short :
+			signature = ConstantPool.IntConstrSignature;
+			break;
+		case T_long :
+			signature = ConstantPool.LongConstrSignature;
+			argCount = 2;
+			break;
+		case T_float :
+			signature = ConstantPool.FloatConstrSignature;
+			break;
+		case T_double :
+			signature = ConstantPool.DoubleConstrSignature;
+			argCount = 2;
+			break;
+		case T_char :
+			signature = ConstantPool.CharConstrSignature;
+			break;
+		case T_boolean :
+			signature = ConstantPool.BooleanConstrSignature;
+			break;
+		case T_JavaLangObject :
+		case T_JavaLangString :
+		case T_null :
+			signature = ConstantPool.ObjectConstrSignature;
+			break;
 	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_invokespecial;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionErrorConstructor(typeBindingID));
-	stackDepth -= 2;
+	this.invoke(
+			OPC_invokespecial,
+			argCount, // argCount
+			0, // return type size
+			ConstantPool.JavaLangAssertionErrorConstantPoolName,
+			ConstantPool.Init,
+			signature);
 }
 
 public void invokeJavaLangAssertionErrorDefaultConstructor() {
 	// invokespecial: java.lang.AssertionError.<init>()V
 	if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.AssertionError.<init>()V"); //$NON-NLS-1$
-	countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_invokespecial;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionErrorDefaultConstructor());
-	stackDepth --;
+	this.invoke(
+			OPC_invokespecial,
+			0, // argCount
+			0, // return type size
+			ConstantPool.JavaLangAssertionErrorConstantPoolName,
+			ConstantPool.Init,
+			ConstantPool.DefaultConstructorSignature);
+}
+public void invokeJavaLangEnumname(TypeBinding typeBinding) {
+	// invokevirtual: java.lang.Enum.name()String
+	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Enum.name()Ljava/lang/String;"); //$NON-NLS-1$
+	this.invoke(
+			OPC_invokevirtual,
+			0,
+			1,
+			typeBinding.constantPoolName(),
+			ConstantPool.Name,
+			ConstantPool.NameSignature);
+}
+public void invokeJavaLangIllegalArgumentExceptionStringConstructor() {
+	// invokespecial: java.lang.IllegalArgumentException.<init>(String)V
+	if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.IllegalArgumentException.<init>(java.lang.String)V"); //$NON-NLS-1$
+	this.invoke(
+			OPC_invokespecial,
+			1, // argCount
+			0, // return type size
+			ConstantPool.JavaLangIllegalArgumentExceptionConstantPoolName,
+			ConstantPool.Init,
+			ConstantPool.StringConstructorSignature);
 }
 
-public void invokeStringBufferDefaultConstructor() {
+public void invokeJavaUtilIteratorHasNext() {
+	// invokeinterface java.util.Iterator.hasNext()Z
+	if (DEBUG) System.out.println(position + "\t\tinvokeinterface: java.util.Iterator.hasNext()Z"); //$NON-NLS-1$
+	this.invoke(
+			OPC_invokeinterface,
+			0, // argCount
+			1, // return type size
+			ConstantPool.JavaUtilIteratorConstantPoolName,
+			ConstantPool.HasNext,
+			ConstantPool.HasNextSignature);
+}
+public void invokeJavaUtilIteratorNext() {
+	// invokeinterface java.util.Iterator.next()java.lang.Object
+	if (DEBUG) System.out.println(position + "\t\tinvokeinterface: java.util.Iterator.next()java.lang.Object"); //$NON-NLS-1$
+	this.invoke(
+			OPC_invokeinterface,
+			0, // argCount
+			1, // return type size
+			ConstantPool.JavaUtilIteratorConstantPoolName,
+			ConstantPool.Next,
+			ConstantPool.NextSignature);
+}
+public void invokeStringConcatenationDefaultConstructor() {
 	// invokespecial: java.lang.StringBuffer.<init>()V
-	if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.StringBuffer.<init>()V"); //$NON-NLS-1$
-	countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
+	if (DEBUG) {
+		if (this.targetLevel >= JDK1_5) {
+			System.out.println(position + "\t\tinvokespecial: java.lang.StringBuilder.<init>()V"); //$NON-NLS-1$
+		} else {
+			System.out.println(position + "\t\tinvokespecial: java.lang.StringBuffer.<init>()V"); //$NON-NLS-1$
+		}
 	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_invokespecial;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferDefaultConstructor());
-	stackDepth--;
+	char[] declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+	if (this.targetLevel >= JDK1_5) {
+		declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+	}
+	this.invoke(
+			OPC_invokespecial,
+			0, // argCount
+			0, // return type size
+			declaringClass,
+			ConstantPool.Init,
+			ConstantPool.DefaultConstructorSignature);
 }
-public void invokeStringBufferStringConstructor() {
-	// invokespecial: java.lang.StringBuffer.<init>(Ljava.lang.String;)V
-	if (DEBUG) System.out.println(position + "\t\tjava.lang.StringBuffer.<init>(Ljava.lang.String;)V"); //$NON-NLS-1$
-	countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
+public void invokeStringConcatenationStringConstructor() {
+	if (DEBUG) {
+		if (this.targetLevel >= JDK1_5) {
+			System.out.println(position + "\t\tjava.lang.StringBuilder.<init>(Ljava.lang.String;)V"); //$NON-NLS-1$
+		} else {
+			System.out.println(position + "\t\tjava.lang.StringBuffer.<init>(Ljava.lang.String;)V"); //$NON-NLS-1$
+		}
 	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_invokespecial;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferConstructor());
-	stackDepth -= 2;
+	char[] declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+	if (this.targetLevel >= JDK1_5) {
+		declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+	}
+	this.invoke(
+			OPC_invokespecial,
+			1, // argCount
+			0, // return type size
+			declaringClass,
+			ConstantPool.Init,
+			ConstantPool.StringConstructorSignature);
 }
 
-public void invokeStringBufferToString() {
-	// invokevirtual: StringBuffer.toString()Ljava.lang.String;
-	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: StringBuffer.toString()Ljava.lang.String;"); //$NON-NLS-1$
-	countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
+public void invokeStringConcatenationToString() {
+	if (DEBUG) {
+		if (this.targetLevel >= JDK1_5) {
+			System.out.println(position + "\t\tinvokevirtual: StringBuilder.toString()Ljava.lang.String;"); //$NON-NLS-1$
+		} else {
+			System.out.println(position + "\t\tinvokevirtual: StringBuffer.toString()Ljava.lang.String;"); //$NON-NLS-1$
+		}
 	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_invokevirtual;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferToString());
+	char[] declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+	if (this.targetLevel >= JDK1_5) {
+		declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+	}
+	this.invoke(
+			OPC_invokevirtual,
+			0, // argCount
+			1, // return type size
+			declaringClass,
+			ConstantPool.ToString,
+			ConstantPool.ToStringSignature);
+}
+public void invokeStringEquals() {
+	// invokevirtual: java.lang.String.equals(java.lang.Object)
+	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.String.equals(...)"); //$NON-NLS-1$
+	this.invoke(
+			OPC_invokevirtual,
+			1, // argCount
+			1, // return type size
+			ConstantPool.JavaLangStringConstantPoolName,
+			ConstantPool.Equals,
+			ConstantPool.EqualsSignature);
 }
 public void invokeStringIntern() {
 	// invokevirtual: java.lang.String.intern()
 	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.String.intern()"); //$NON-NLS-1$
-	countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_invokevirtual;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangStringIntern());
+	this.invoke(
+			OPC_invokevirtual,
+			0, // argCount
+			1, // return type size
+			ConstantPool.JavaLangStringConstantPoolName,
+			ConstantPool.Intern,
+			ConstantPool.InternSignature);
 }
 public void invokeStringValueOf(int typeID) {
 	// invokestatic: java.lang.String.valueOf(argumentType)
 	if (DEBUG) System.out.println(position + "\t\tinvokestatic: java.lang.String.valueOf(...)"); //$NON-NLS-1$
-	countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
+	int argCount = 1;
+	char[] signature = null;
+	switch (typeID) {
+		case T_int :
+		case T_byte :
+		case T_short :
+			signature = ConstantPool.ValueOfIntSignature;
+			break;
+		case T_long :
+			signature = ConstantPool.ValueOfLongSignature;
+			argCount = 2;
+			break;
+		case T_float :
+			signature = ConstantPool.ValueOfFloatSignature;
+			break;
+		case T_double :
+			signature = ConstantPool.ValueOfDoubleSignature;
+			argCount = 2;
+			break;
+		case T_char :
+			signature = ConstantPool.ValueOfCharSignature;
+			break;
+		case T_boolean :
+			signature = ConstantPool.ValueOfBooleanSignature;
+			break;
+		case T_JavaLangObject :
+		case T_JavaLangString :
+		case T_null :
+		case T_undefined :
+			signature = ConstantPool.ValueOfObjectSignature;
+			break;
 	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_invokestatic;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangStringValueOf(typeID));
+	this.invoke(
+			OPC_invokestatic,
+			argCount, // argCount
+			1, // return type size
+			ConstantPool.JavaLangStringConstantPoolName,
+			ConstantPool.ValueOf,
+			signature);
+}
+public void invokeSystemArraycopy() {
+	// invokestatic #21 <Method java/lang/System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V>
+	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V"); //$NON-NLS-1$
+	this.invoke(
+			OPC_invokestatic,
+			5, // argCount
+			0, // return type size
+			ConstantPool.JavaLangSystemConstantPoolName,
+			ConstantPool.ArrayCopy,
+			ConstantPool.ArrayCopySignature);
 }
 public void invokeThrowableGetMessage() {
 	// invokevirtual: java.lang.Throwable.getMessage()Ljava.lang.String;
 	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Throwable.getMessage()Ljava.lang.String;"); //$NON-NLS-1$
+	this.invoke(
+			OPC_invokevirtual,
+			0, // argCount
+			1, // return type size
+			ConstantPool.JavaLangThrowableConstantPoolName,
+			ConstantPool.GetMessage,
+			ConstantPool.GetMessageSignature);
+}
+final public void invoke(int opcode, int argsSize, int returnTypeSize, char[] declaringClass, char[] selector, char[] signature) {
 	countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
+	int argCount = argsSize;
+	switch(opcode) {
+		case OPC_invokeinterface :
+			if (classFileOffset + 4 >= bCodeStream.length) {
+				resizeByteArray();
+			}
+			position +=3;
+			bCodeStream[classFileOffset++] = OPC_invokeinterface;
+			writeUnsignedShort(constantPool.literalIndexForMethod(declaringClass, selector, signature, true));
+			argCount++;
+			bCodeStream[classFileOffset++] = (byte) argCount;
+			bCodeStream[classFileOffset++] = 0;
+			break;
+		case OPC_invokevirtual :
+		case OPC_invokespecial :
+			if (classFileOffset + 2 >= bCodeStream.length) {
+				resizeByteArray();
+			}
+			position++;
+			bCodeStream[classFileOffset++] = (byte) opcode;
+			writeUnsignedShort(constantPool.literalIndexForMethod(declaringClass, selector, signature, false));
+			argCount++;
+			break;
+		case OPC_invokestatic :
+			if (classFileOffset + 2 >= bCodeStream.length) {
+				resizeByteArray();
+			}
+			position++;
+			bCodeStream[classFileOffset++] = OPC_invokestatic;
+			writeUnsignedShort(constantPool.literalIndexForMethod(declaringClass, selector, signature, false));
 	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_invokevirtual;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangThrowableGetMessage());
+	stackDepth += returnTypeSize - argCount;
+	if (stackDepth > stackMax) {
+		stackMax = stackDepth;
+	}
 }
 final public void invokevirtual(MethodBinding methodBinding) {
 	if (DEBUG) System.out.println(position + "\t\tinvokevirtual:"+methodBinding); //$NON-NLS-1$
@@ -3433,13 +4084,13 @@
 	bCodeStream[classFileOffset++] = OPC_lconst_1;
 }
 final public void ldc(float constant) {
-	if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
 	countLabels = 0;
 	int index = constantPool.literalIndex(constant);
 	stackDepth++;
 	if (stackDepth > stackMax)
 		stackMax = stackDepth;
 	if (index > 255) {
+		if (DEBUG) System.out.println(position + "\t\tldc_w:"+constant); //$NON-NLS-1$
 		// Generate a ldc_w
 		if (classFileOffset + 2 >= bCodeStream.length) {
 			resizeByteArray();
@@ -3448,6 +4099,7 @@
 		bCodeStream[classFileOffset++] = OPC_ldc_w;
 		writeUnsignedShort(index);
 	} else {
+		if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
 		// Generate a ldc
 		if (classFileOffset + 1 >= bCodeStream.length) {
 			resizeByteArray();
@@ -3458,13 +4110,13 @@
 	}
 }
 final public void ldc(int constant) {
-	if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
 	countLabels = 0;
 	int index = constantPool.literalIndex(constant);
 	stackDepth++;
 	if (stackDepth > stackMax)
 		stackMax = stackDepth;
 	if (index > 255) {
+		if (DEBUG) System.out.println(position + "\t\tldc_w:"+constant); //$NON-NLS-1$
 		// Generate a ldc_w
 		if (classFileOffset + 2 >= bCodeStream.length) {
 			resizeByteArray();
@@ -3473,6 +4125,7 @@
 		bCodeStream[classFileOffset++] = OPC_ldc_w;
 		writeUnsignedShort(index);
 	} else {
+		if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
 		// Generate a ldc
 		if (classFileOffset + 1 >= bCodeStream.length) {
 			resizeByteArray();
@@ -3483,7 +4136,6 @@
 	}
 }
 final public void ldc(String constant) {
-	if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
 	countLabels = 0;
 	int currentConstantPoolIndex = constantPool.currentIndex;
 	int currentConstantPoolOffset = constantPool.currentOffset;
@@ -3496,6 +4148,7 @@
 		if (stackDepth > stackMax)
 			stackMax = stackDepth;
 		if (index > 255) {
+			if (DEBUG) System.out.println(position + "\t\tldc_w:"+constant); //$NON-NLS-1$
 			// Generate a ldc_w
 			if (classFileOffset + 2 >= bCodeStream.length) {
 				resizeByteArray();
@@ -3504,6 +4157,7 @@
 			bCodeStream[classFileOffset++] = OPC_ldc_w;
 			writeUnsignedShort(index);
 		} else {
+			if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
 			// Generate a ldc
 			if (classFileOffset + 1 >= bCodeStream.length) {
 				resizeByteArray();
@@ -3554,7 +4208,7 @@
 		}
 		// check if all the string is encoded (PR 1PR2DWJ)
 		// the string is too big to be encoded in one pass
-		newStringBuffer();
+		newStringContatenation();
 		dup();
 		// write the first part
 		char[] subChars = new char[i];
@@ -3582,7 +4236,7 @@
 			bCodeStream[classFileOffset++] = (byte) index;
 		}
 		// write the remaining part
-		invokeStringBufferStringConstructor();
+		invokeStringConcatenationStringConstructor();
 		while (i < constantLength) {
 			length = 0;
 			utf8encoding = new byte[Math.min(constantLength - i + 100, 65535)];
@@ -3637,12 +4291,38 @@
 				bCodeStream[classFileOffset++] = (byte) index;
 			}
 			// now on the stack it should be a StringBuffer and a string.
-			invokeStringBufferAppendForType(T_String);
+			invokeStringConcatenationAppendForType(T_JavaLangString);
 		}
-		invokeStringBufferToString();
+		invokeStringConcatenationToString();
 		invokeStringIntern();
 	}
 }
+final public void ldc(TypeBinding typeBinding) {
+	countLabels = 0;
+	int index = constantPool.literalIndexForType(typeBinding.constantPoolName());
+	stackDepth++;
+	if (stackDepth > stackMax)
+		stackMax = stackDepth;
+	if (index > 255) {
+		if (DEBUG) System.out.println(position + "\t\tldc_w:"+ typeBinding); //$NON-NLS-1$
+		// Generate a ldc_w
+		if (classFileOffset + 2 >= bCodeStream.length) {
+			resizeByteArray();
+		}
+		position++;
+		bCodeStream[classFileOffset++] = OPC_ldc_w;
+		writeUnsignedShort(index);
+	} else {
+		if (DEBUG) System.out.println(position + "\t\tldw:"+ typeBinding); //$NON-NLS-1$
+		// Generate a ldc
+		if (classFileOffset + 1 >= bCodeStream.length) {
+			resizeByteArray();
+		}
+		position += 2;
+		bCodeStream[classFileOffset++] = OPC_ldc;
+		bCodeStream[classFileOffset++] = (byte) index;
+	}
+}
 final public void ldc2_w(double constant) {
 	if (DEBUG) System.out.println(position + "\t\tldc2_w:"+constant); //$NON-NLS-1$
 	countLabels = 0;
@@ -4287,14 +4967,14 @@
 	}
 	position += 2;
 	bCodeStream[classFileOffset++] = OPC_multianewarray;
-	writeUnsignedShort(constantPool.literalIndex(typeBinding));
+	writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName()));
 	bCodeStream[classFileOffset++] = (byte) dimensions;
 }
 /**
  * We didn't call it new, because there is a conflit with the new keyword
  */
 final public void new_(TypeBinding typeBinding) {
-	if (DEBUG) System.out.println(position + "\t\tnew:"+typeBinding); //$NON-NLS-1$
+	if (DEBUG) System.out.println(position + "\t\tnew:"+typeBinding.debugName()); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -4304,7 +4984,7 @@
 	}
 	position++;
 	bCodeStream[classFileOffset++] = OPC_new;
-	writeUnsignedShort(constantPool.literalIndex(typeBinding));
+	writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName()));
 }
 final public void newarray(int array_Type) {
 	if (DEBUG) System.out.println(position + "\t\tnewarray:"+array_Type); //$NON-NLS-1$
@@ -4316,32 +4996,32 @@
 	bCodeStream[classFileOffset++] = OPC_newarray;
 	bCodeStream[classFileOffset++] = (byte) array_Type;
 }
-public void newArray(Scope scope, ArrayBinding arrayBinding) {
-	TypeBinding component = arrayBinding.elementsType(scope);
+public void newArray(ArrayBinding arrayBinding) {
+	TypeBinding component = arrayBinding.elementsType();
 	switch (component.id) {
 		case T_int :
-			this.newarray(10);
+			this.newarray(INT_ARRAY);
 			break;
 		case T_byte :
-			this.newarray(8);
+			this.newarray(BYTE_ARRAY);
 			break;
 		case T_boolean :
-			this.newarray(4);
+			this.newarray(BOOLEAN_ARRAY);
 			break;
 		case T_short :
-			this.newarray(9);
+			this.newarray(SHORT_ARRAY);
 			break;
 		case T_char :
-			this.newarray(5);
+			this.newarray(CHAR_ARRAY);
 			break;
 		case T_long :
-			this.newarray(11);
+			this.newarray(LONG_ARRAY);
 			break;
 		case T_float :
-			this.newarray(6);
+			this.newarray(FLOAT_ARRAY);
 			break;
 		case T_double :
-			this.newarray(7);
+			this.newarray(DOUBLE_ARRAY);
 			break;
 		default :
 			this.anewarray(component);
@@ -4359,7 +5039,7 @@
 	}
 	position++;
 	bCodeStream[classFileOffset++] = OPC_new;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangError());
+	writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangErrorConstantPoolName));
 }
 
 public void newJavaLangAssertionError() {
@@ -4374,9 +5054,22 @@
 	}
 	position++;
 	bCodeStream[classFileOffset++] = OPC_new;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionError());
+	writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangAssertionErrorConstantPoolName));
 }
-
+public void newJavaLangIllegalArgumentException() {
+	// new: java.lang.IllegalArgumentException
+	if (DEBUG) System.out.println(position + "\t\tnew: java.lang.IllegalArgumentException"); //$NON-NLS-1$
+	countLabels = 0;
+	stackDepth++;
+	if (stackDepth > stackMax)
+		stackMax = stackDepth;
+	if (classFileOffset + 2 >= bCodeStream.length) {
+		resizeByteArray();
+	}
+	position++;
+	bCodeStream[classFileOffset++] = OPC_new;
+	writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangIllegalArgumentExceptionConstantPoolName));
+}
 public void newNoClassDefFoundError() {
 	// new: java.lang.NoClassDefFoundError
 	if (DEBUG) System.out.println(position + "\t\tnew: java.lang.NoClassDefFoundError"); //$NON-NLS-1$
@@ -4389,21 +5082,33 @@
 	}
 	position++;
 	bCodeStream[classFileOffset++] = OPC_new;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangNoClassDefFoundError());
+	writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangNoClassDefFoundErrorConstantPoolName));
 }
-public void newStringBuffer() {
+public void newStringContatenation() {
 	// new: java.lang.StringBuffer
-	if (DEBUG) System.out.println(position + "\t\tnew: java.lang.StringBuffer"); //$NON-NLS-1$
+	// new: java.lang.StringBuilder
+	if (DEBUG) {
+		if (this.targetLevel >= JDK1_5) {
+			System.out.println(position + "\t\tnew: java.lang.StringBuilder"); //$NON-NLS-1$
+		} else {
+			System.out.println(position + "\t\tnew: java.lang.StringBuffer"); //$NON-NLS-1$
+		}
+	}
 	countLabels = 0;
 	stackDepth++;
-	if (stackDepth > stackMax)
+	if (stackDepth > stackMax) {
 		stackMax = stackDepth;
+	}
 	if (classFileOffset + 2 >= bCodeStream.length) {
 		resizeByteArray();
 	}
 	position++;
 	bCodeStream[classFileOffset++] = OPC_new;
-	writeUnsignedShort(constantPool.literalIndexForJavaLangStringBuffer());
+	if (this.targetLevel >= JDK1_5) {
+		writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangStringBuilderConstantPoolName));
+	} else {
+		writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangStringBufferConstantPoolName));
+	}
 }
 public void newWrapperFor(int typeID) {
 	countLabels = 0;
@@ -4418,39 +5123,39 @@
 	switch (typeID) {
 		case T_int : // new: java.lang.Integer
 			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Integer"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangInteger());
+			writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangIntegerConstantPoolName));
 			break;
 		case T_boolean : // new: java.lang.Boolean
 			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Boolean"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangBoolean());
+			writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangBooleanConstantPoolName));
 			break;
 		case T_byte : // new: java.lang.Byte
 			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Byte"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangByte());
+			writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangByteConstantPoolName));
 			break;
 		case T_char : // new: java.lang.Character
 			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Character"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangCharacter());
+			writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangCharacterConstantPoolName));
 			break;
 		case T_float : // new: java.lang.Float
 			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Float"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangFloat());
+			writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangFloatConstantPoolName));
 			break;
 		case T_double : // new: java.lang.Double
 			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Double"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangDouble());
+			writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangDoubleConstantPoolName));
 			break;
 		case T_short : // new: java.lang.Short
 			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Short"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangShort());
+			writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangShortConstantPoolName));
 			break;
 		case T_long : // new: java.lang.Long
 			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Long"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangLong());
+			writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangLongConstantPoolName));
 			break;
 		case T_void : // new: java.lang.Void
 			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Void"); //$NON-NLS-1$
-			writeUnsignedShort(constantPool.literalIndexForJavaLangVoid());
+			writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangVoidConstantPoolName));
 	}
 }
 final public void nop() {
@@ -4484,37 +5189,29 @@
 }
 final public void putfield(FieldBinding fieldBinding) {
 	if (DEBUG) System.out.println(position + "\t\tputfield:"+fieldBinding); //$NON-NLS-1$
-	countLabels = 0;
-	int id;
-	if (((id = fieldBinding.type.id) == T_double) || (id == T_long))
-		stackDepth -= 3;
-	else
-		stackDepth -= 2;
-	if (stackDepth > stackMax)
-		stackMax = stackDepth;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
+	int returnTypeSize = 1;
+	if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) {
+		returnTypeSize = 2;
 	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_putfield;
-	writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+	generateFieldAccess(
+			OPC_putfield,
+			returnTypeSize,
+			fieldBinding.declaringClass.constantPoolName(),
+			fieldBinding.name,
+			fieldBinding.type.signature());
 }
 final public void putstatic(FieldBinding fieldBinding) {
 	if (DEBUG) System.out.println(position + "\t\tputstatic:"+fieldBinding); //$NON-NLS-1$
-	countLabels = 0;
-	int id;
-	if (((id = fieldBinding.type.id) == T_double) || (id == T_long))
-		stackDepth -= 2;
-	else
-		stackDepth -= 1;
-	if (stackDepth > stackMax)
-		stackMax = stackDepth;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
+	int returnTypeSize = 1;
+	if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) {
+		returnTypeSize = 2;
 	}
-	position++;
-	bCodeStream[classFileOffset++] = OPC_putstatic;
-	writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+	generateFieldAccess(
+			OPC_putstatic,
+			returnTypeSize,
+			fieldBinding.declaringClass.constantPoolName(),
+			fieldBinding.name,
+			fieldBinding.type.signature());
 }
 public void record(LocalVariableBinding local) {
 	if (!generateLocalVariableTableAttributes)
@@ -4574,15 +5271,14 @@
 					if (existingEntryIndex != -1) {
 						// widen existing entry
 						pcToSourceMap[existingEntryIndex] = startPC;
-					} else {
+					} else if (insertionIndex < 1 || pcToSourceMap[insertionIndex - 1] != newLine) {
 						// we have to add an entry that won't be sorted. So we sort the pcToSourceMap.
 						System.arraycopy(pcToSourceMap, insertionIndex, pcToSourceMap, insertionIndex + 2, pcToSourceMapSize - insertionIndex);
 						pcToSourceMap[insertionIndex++] = startPC;
 						pcToSourceMap[insertionIndex] = newLine;
 						pcToSourceMapSize += 2;
 					}
-				}
-				if (position != lastEntryPC) { // no bytecode since last entry pc
+				} else if (position != lastEntryPC) { // no bytecode since last entry pc
 					pcToSourceMap[pcToSourceMapSize++] = lastEntryPC;
 					pcToSourceMap[pcToSourceMapSize++] = newLine;
 				}
@@ -4630,12 +5326,22 @@
  */
 public void registerExceptionHandler(ExceptionLabel anExceptionLabel) {
 	int length;
-	if (exceptionHandlersNumber >= (length = exceptionHandlers.length)) {
+	if (exceptionHandlersIndex >= (length = exceptionHandlers.length)) {
 		// resize the exception handlers table
 		System.arraycopy(exceptionHandlers, 0, exceptionHandlers = new ExceptionLabel[length + LABELS_INCREMENT], 0, length);
 	}
 	// no need to resize. So just add the new exception label
-	exceptionHandlers[exceptionHandlersNumber++] = anExceptionLabel;
+	exceptionHandlers[exceptionHandlersIndex++] = anExceptionLabel;
+	exceptionHandlersCounter++;
+}
+public void removeExceptionHandler(ExceptionLabel exceptionLabel) {
+	for (int i = 0; i < exceptionHandlersIndex; i++) {
+		if (exceptionHandlers[i] == exceptionLabel) {
+			exceptionHandlers[i] = null;
+			exceptionHandlersCounter--;
+			return;
+		}
+	}
 }
 public final void removeNotDefinitelyAssignedVariables(Scope scope, int initStateIndex) {
 	// given some flow info, make sure we did not loose some variables initialization
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
index 66a2f72..a4a4509 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
@@ -10,12 +10,14 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.codegen;
 
-import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.internal.compiler.ClassFile;
-
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
 /**
  * This type is used to store all the constant pool entries.
  */
@@ -26,9 +28,7 @@
 	public static final int LONG_INITIAL_SIZE = 5;
 	public static final int UTF8_INITIAL_SIZE = 778;
 	public static final int STRING_INITIAL_SIZE = 761;
-	public static final int FIELD_INITIAL_SIZE = 156;
-	public static final int METHOD_INITIAL_SIZE = 236;
-	public static final int INTERFACE_INITIAL_SIZE = 50;
+	public static final int METHODS_AND_FIELDS_INITIAL_SIZE = 450;
 	public static final int CLASS_INITIAL_SIZE = 86;
 	public static final int NAMEANDTYPE_INITIAL_SIZE = 272;
 	public static final int CONSTANTPOOL_INITIAL_SIZE = 2000;
@@ -39,131 +39,200 @@
 	protected LongCache longCache;
 	public CharArrayCache UTF8Cache;
 	protected CharArrayCache stringCache;
-	protected ObjectCache fieldCache;
-	protected ObjectCache methodCache;
-	protected ObjectCache interfaceMethodCache;
-	protected ObjectCache classCache;
-	protected FieldNameAndTypeCache nameAndTypeCacheForFields;
-	protected MethodNameAndTypeCache nameAndTypeCacheForMethods;
-	int[] wellKnownTypes = new int[21];
-	int[] wellKnownMethods = new int[36];
-	int[] wellKnownFields = new int[10];
-	int[] wellKnownFieldNameAndTypes = new int[2];
-	int[] wellKnownMethodNameAndTypes = new int[33];
+	protected HashtableOfObject methodsAndFieldsCache;
+	protected CharArrayCache classCache;
+	protected HashtableOfObject nameAndTypeCacheForFieldsAndMethods;
 	public byte[] poolContent;
 	public int currentIndex = 1;
 	public int currentOffset;
-	// predefined constant index for well known types
-	final static int JAVA_LANG_BOOLEAN_TYPE = 0;
-	final static int JAVA_LANG_BYTE_TYPE = 1;
-	final static int JAVA_LANG_CHARACTER_TYPE = 2;
-	final static int JAVA_LANG_DOUBLE_TYPE = 3;
-	final static int JAVA_LANG_FLOAT_TYPE = 4;
-	final static int JAVA_LANG_INTEGER_TYPE = 5;
-	final static int JAVA_LANG_LONG_TYPE = 6;
-	final static int JAVA_LANG_SHORT_TYPE = 7;
-	final static int JAVA_LANG_VOID_TYPE = 8;
-	final static int JAVA_LANG_CLASS_TYPE = 9;
-	final static int JAVA_LANG_CLASSNOTFOUNDEXCEPTION_TYPE = 10;
-	final static int JAVA_LANG_NOCLASSDEFFOUNDERROR_TYPE = 11;
-	final static int JAVA_LANG_OBJECT_TYPE = 12;
-	final static int JAVA_LANG_STRING_TYPE = 13;
-	final static int JAVA_LANG_STRINGBUFFER_TYPE = 14;
-	final static int JAVA_LANG_SYSTEM_TYPE = 15;
-	final static int JAVA_LANG_THROWABLE_TYPE = 16;
-	final static int JAVA_LANG_ERROR_TYPE = 17;
-	final static int JAVA_LANG_EXCEPTION_TYPE = 18;
-	final static int JAVA_LANG_REFLECT_CONSTRUCTOR_TYPE = 19;
-	final static int JAVA_LANG_ASSERTIONERROR_TYPE = 20;
-	
-	// predefined constant index for well known fields  
-	final static int TYPE_BYTE_FIELD = 0;
-	final static int TYPE_SHORT_FIELD = 1;
-	final static int TYPE_CHARACTER_FIELD = 2;
-	final static int TYPE_INTEGER_FIELD = 3;
-	final static int TYPE_LONG_FIELD = 4;
-	final static int TYPE_FLOAT_FIELD = 5;
-	final static int TYPE_DOUBLE_FIELD = 6;
-	final static int TYPE_BOOLEAN_FIELD = 7;
-	final static int TYPE_VOID_FIELD = 8;
-	final static int OUT_SYSTEM_FIELD = 9;
-	// predefined constant index for well known methods 
-	final static int FORNAME_CLASS_METHOD = 0;
-	final static int NOCLASSDEFFOUNDERROR_CONSTR_METHOD = 1;
-	final static int APPEND_INT_METHOD = 2;
-	final static int APPEND_FLOAT_METHOD = 3;
-	final static int APPEND_LONG_METHOD = 4;
-	final static int APPEND_OBJECT_METHOD = 5;
-	final static int APPEND_CHAR_METHOD = 6;
-	final static int APPEND_STRING_METHOD = 7;
-	final static int APPEND_BOOLEAN_METHOD = 8;
-	final static int APPEND_DOUBLE_METHOD = 9;
-	final static int STRINGBUFFER_STRING_CONSTR_METHOD = 10;
-	final static int STRINGBUFFER_DEFAULT_CONSTR_METHOD = 11;
-	final static int STRINGBUFFER_TOSTRING_METHOD = 12;
-	final static int SYSTEM_EXIT_METHOD = 13;
-	final static int THROWABLE_GETMESSAGE_METHOD = 14;
-	final static int JAVALANGERROR_CONSTR_METHOD = 15;
-	final static int NEWINSTANCE_CONSTRUCTOR_METHOD = 16;
-	final static int STRING_INTERN_METHOD = 17;
-	final static int VALUEOF_INT_METHOD = 18;
-	final static int VALUEOF_FLOAT_METHOD = 19;
-	final static int VALUEOF_LONG_METHOD = 20;
-	final static int VALUEOF_OBJECT_METHOD = 21;
-	final static int VALUEOF_CHAR_METHOD = 22;
-	final static int VALUEOF_BOOLEAN_METHOD = 23;
-	final static int VALUEOF_DOUBLE_METHOD = 24;
-	final static int ASSERTIONERROR_CONSTR_OBJECT_METHOD = 25;
-	final static int ASSERTIONERROR_CONSTR_INT_METHOD = 26;
-	final static int ASSERTIONERROR_CONSTR_LONG_METHOD = 27;
-	final static int ASSERTIONERROR_CONSTR_FLOAT_METHOD = 28;
-	final static int ASSERTIONERROR_CONSTR_DOUBLE_METHOD = 29;
-	final static int ASSERTIONERROR_CONSTR_BOOLEAN_METHOD = 30;
-	final static int ASSERTIONERROR_CONSTR_CHAR_METHOD = 31;
-	final static int ASSERTIONERROR_DEFAULT_CONSTR_METHOD = 32;
-	final static int DESIREDASSERTIONSTATUS_CLASS_METHOD = 33;
-	final static int GETCLASS_OBJECT_METHOD = 34;
-	final static int GETCOMPONENTTYPE_CLASS_METHOD = 35;
-	
-	// predefined constant index for well known name and type for fields
-	final static int TYPE_JAVALANGCLASS_NAME_AND_TYPE = 0;
-	final static int OUT_SYSTEM_NAME_AND_TYPE = 1;
-	// predefined constant index for well known name and type for methods
-	final static int FORNAME_CLASS_METHOD_NAME_AND_TYPE = 0;
-	final static int CONSTR_STRING_METHOD_NAME_AND_TYPE = 1;
-	final static int DEFAULT_CONSTR_METHOD_NAME_AND_TYPE = 2;
-	final static int APPEND_INT_METHOD_NAME_AND_TYPE = 3;
-	final static int APPEND_FLOAT_METHOD_NAME_AND_TYPE = 4;
-	final static int APPEND_LONG_METHOD_NAME_AND_TYPE = 5;
-	final static int APPEND_OBJECT_METHOD_NAME_AND_TYPE = 6;
-	final static int APPEND_CHAR_METHOD_NAME_AND_TYPE = 7;
-	final static int APPEND_STRING_METHOD_NAME_AND_TYPE = 8;
-	final static int APPEND_BOOLEAN_METHOD_NAME_AND_TYPE = 9;
-	final static int APPEND_DOUBLE_METHOD_NAME_AND_TYPE = 10;
-	final static int TOSTRING_METHOD_NAME_AND_TYPE = 11;
-	final static int EXIT_METHOD_NAME_AND_TYPE = 12;
-	final static int GETMESSAGE_METHOD_NAME_AND_TYPE = 13;
-	final static int NEWINSTANCE_METHOD_NAME_AND_TYPE = 14;
-	final static int INTERN_METHOD_NAME_AND_TYPE = 15;
-	final static int VALUEOF_INT_METHOD_NAME_AND_TYPE = 16;
-	final static int VALUEOF_FLOAT_METHOD_NAME_AND_TYPE = 17;
-	final static int VALUEOF_LONG_METHOD_NAME_AND_TYPE = 18;
-	final static int VALUEOF_OBJECT_METHOD_NAME_AND_TYPE = 19;
-	final static int VALUEOF_CHAR_METHOD_NAME_AND_TYPE = 20;
-	final static int VALUEOF_BOOLEAN_METHOD_NAME_AND_TYPE = 21;
-	final static int VALUEOF_DOUBLE_METHOD_NAME_AND_TYPE = 22;
-	final static int CONSTR_INT_METHOD_NAME_AND_TYPE = 23;
-	final static int CONSTR_LONG_METHOD_NAME_AND_TYPE = 24;
-	final static int CONSTR_FLOAT_METHOD_NAME_AND_TYPE = 25;
-	final static int CONSTR_DOUBLE_METHOD_NAME_AND_TYPE = 26;
-	final static int CONSTR_OBJECT_METHOD_NAME_AND_TYPE = 27;
-	final static int CONSTR_CHAR_METHOD_NAME_AND_TYPE = 28;
-	final static int CONSTR_BOOLEAN_METHOD_NAME_AND_TYPE = 29;
-	final static int DESIREDASSERTIONSTATUS_METHOD_NAME_AND_TYPE = 30;
-	final static int GETCLASS_OBJECT_METHOD_NAME_AND_TYPE = 31;
-	final static int GETCOMPONENTTYPE_CLASS_METHOD_NAME_AND_TYPE = 32;
-	
+
 	public ClassFile classFile;
+	public static final char[] Append = "append".toCharArray(); //$NON-NLS-1$
+	public static final char[] ARRAY_NEWINSTANCE_NAME = "newInstance".toCharArray(); //$NON-NLS-1$
+	public static final char[] ARRAY_NEWINSTANCE_SIGNATURE = "(Ljava/lang/Class;[I)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
+	public static final char[] ArrayCopy = "arraycopy".toCharArray(); //$NON-NLS-1$
+	public static final char[] ArrayCopySignature = "(Ljava/lang/Object;ILjava/lang/Object;II)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] ArrayJavaLangClassConstantPoolName = "[Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
+	public static final char[] ArrayJavaLangObjectConstantPoolName = "[Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
+	public static final char[] booleanBooleanSignature = "(Z)Ljava/lang/Boolean;".toCharArray(); //$NON-NLS-1$
+	public static final char[] BooleanConstrSignature = "(Z)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] BOOLEANVALUE_BOOLEAN_METHOD_NAME = "booleanValue".toCharArray(); //$NON-NLS-1$
+	public static final char[] BOOLEANVALUE_BOOLEAN_METHOD_SIGNATURE = "()Z".toCharArray(); //$NON-NLS-1$
+	public static final char[] byteByteSignature = "(B)Ljava/lang/Byte;".toCharArray(); //$NON-NLS-1$
+	public static final char[] ByteConstrSignature = "(B)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] BYTEVALUE_BYTE_METHOD_NAME = "byteValue".toCharArray(); //$NON-NLS-1$
+	public static final char[] BYTEVALUE_BYTE_METHOD_SIGNATURE = "()B".toCharArray(); //$NON-NLS-1$
+	public static final char[] charCharacterSignature = "(C)Ljava/lang/Character;".toCharArray(); //$NON-NLS-1$
+	public static final char[] CharConstrSignature = "(C)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] CHARVALUE_CHARACTER_METHOD_NAME = "charValue".toCharArray(); //$NON-NLS-1$
+	public static final char[] CHARVALUE_CHARACTER_METHOD_SIGNATURE = "()C".toCharArray(); //$NON-NLS-1$
+	public static final char[] Clinit = "<clinit>".toCharArray(); //$NON-NLS-1$
+	public static final char[] DefaultConstructorSignature = "()V".toCharArray(); //$NON-NLS-1$
+	public static final char[] ClinitSignature = DefaultConstructorSignature;
+	public static final char[] DesiredAssertionStatus = "desiredAssertionStatus".toCharArray(); //$NON-NLS-1$
+	public static final char[] DesiredAssertionStatusSignature = "()Z".toCharArray(); //$NON-NLS-1$
+	public static final char[] DoubleConstrSignature = "(D)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] doubleDoubleSignature = "(D)Ljava/lang/Double;".toCharArray(); //$NON-NLS-1$
+	public static final char[] DOUBLEVALUE_DOUBLE_METHOD_NAME = "doubleValue".toCharArray(); //$NON-NLS-1$
+	public static final char[] DOUBLEVALUE_DOUBLE_METHOD_SIGNATURE = "()D".toCharArray(); //$NON-NLS-1$
+	public static final char[] Equals = "equals".toCharArray(); //$NON-NLS-1$
+	public static final char[] EqualsSignature = "(Ljava/lang/Object;)Z".toCharArray(); //$NON-NLS-1$
+	public static final char[] Exit = "exit".toCharArray(); //$NON-NLS-1$
+	public static final char[] ExitIntSignature = "(I)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] FloatConstrSignature = "(F)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] floatFloatSignature = "(F)Ljava/lang/Float;".toCharArray(); //$NON-NLS-1$
+	public static final char[] FLOATVALUE_FLOAT_METHOD_NAME = "floatValue".toCharArray(); //$NON-NLS-1$
+	public static final char[] FLOATVALUE_FLOAT_METHOD_SIGNATURE = "()F".toCharArray(); //$NON-NLS-1$
+	public static final char[] ForName = "forName".toCharArray(); //$NON-NLS-1$
+	public static final char[] ForNameSignature = "(Ljava/lang/String;)Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_BOOLEAN_METHOD_NAME = "getBoolean".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_BOOLEAN_METHOD_SIGNATURE = "(Ljava/lang/Object;)Z".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_BYTE_METHOD_NAME = "getByte".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_BYTE_METHOD_SIGNATURE = "(Ljava/lang/Object;)B".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_CHAR_METHOD_NAME = "getChar".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_CHAR_METHOD_SIGNATURE = "(Ljava/lang/Object;)C".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_DOUBLE_METHOD_NAME = "getDouble".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_DOUBLE_METHOD_SIGNATURE = "(Ljava/lang/Object;)D".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_FLOAT_METHOD_NAME = "getFloat".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_FLOAT_METHOD_SIGNATURE = "(Ljava/lang/Object;)F".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_INT_METHOD_NAME = "getInt".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_INT_METHOD_SIGNATURE = "(Ljava/lang/Object;)I".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_LONG_METHOD_NAME = "getLong".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_LONG_METHOD_SIGNATURE = "(Ljava/lang/Object;)J".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_OBJECT_METHOD_NAME = "get".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_OBJECT_METHOD_SIGNATURE = "(Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_SHORT_METHOD_NAME = "getShort".toCharArray(); //$NON-NLS-1$
+	public static final char[] GET_SHORT_METHOD_SIGNATURE = "(Ljava/lang/Object;)S".toCharArray(); //$NON-NLS-1$
+	public static final char[] GetClass = "getClass".toCharArray(); //$NON-NLS-1$
+	public static final char[] GetClassSignature = "()Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
+	public static final char[] GetComponentType = "getComponentType".toCharArray(); //$NON-NLS-1$
+	public static final char[] GetComponentTypeSignature = GetClassSignature;
+	public static final char[] GetConstructor = "getConstructor".toCharArray(); //$NON-NLS-1$
+	public static final char[] GetConstructorSignature = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;".toCharArray(); //$NON-NLS-1$
+	public static final char[] GETDECLAREDCONSTRUCTOR_NAME = "getDeclaredConstructor".toCharArray(); //$NON-NLS-1$
+	public static final char[] GETDECLAREDCONSTRUCTOR_SIGNATURE = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;".toCharArray(); //$NON-NLS-1$
+	// predefined methods constant names
+	public static final char[] GETDECLAREDFIELD_NAME = "getDeclaredField".toCharArray(); //$NON-NLS-1$
+	public static final char[] GETDECLAREDFIELD_SIGNATURE = "(Ljava/lang/String;)Ljava/lang/reflect/Field;".toCharArray(); //$NON-NLS-1$
+	public static final char[] GETDECLAREDMETHOD_NAME = "getDeclaredMethod".toCharArray(); //$NON-NLS-1$
+	public static final char[] GETDECLAREDMETHOD_SIGNATURE = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;".toCharArray(); //$NON-NLS-1$
+	public static final char[] GetMessage = "getMessage".toCharArray(); //$NON-NLS-1$
+	public static final char[] GetMessageSignature = "()Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+	public static final char[] HasNext = "hasNext".toCharArray();//$NON-NLS-1$
+	public static final char[] HasNextSignature = "()Z".toCharArray();//$NON-NLS-1$
+	public static final char[] Init = "<init>".toCharArray(); //$NON-NLS-1$
+	public static final char[] IntConstrSignature = "(I)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] Intern = "intern".toCharArray(); //$NON-NLS-1$
+	public static final char[] InternSignature = GetMessageSignature;
+	public static final char[] IntIntegerSignature = "(I)Ljava/lang/Integer;".toCharArray(); //$NON-NLS-1$
+	public static final char[] INTVALUE_INTEGER_METHOD_NAME = "intValue".toCharArray(); //$NON-NLS-1$
+	public static final char[] INTVALUE_INTEGER_METHOD_SIGNATURE = "()I".toCharArray(); //$NON-NLS-1$
+	public static final char[] INVOKE_METHOD_METHOD_NAME = "invoke".toCharArray(); //$NON-NLS-1$
+	public static final char[] INVOKE_METHOD_METHOD_SIGNATURE = "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
+	public static final char[][] JAVA_LANG_REFLECT_ACCESSIBLEOBJECT = new char[][] {TypeConstants.JAVA, TypeConstants.LANG, TypeConstants.REFLECT, "AccessibleObject".toCharArray()}; //$NON-NLS-1$
+	public static final char[][] JAVA_LANG_REFLECT_ARRAY = new char[][] {TypeConstants.JAVA, TypeConstants.LANG, TypeConstants.REFLECT, "Array".toCharArray()}; //$NON-NLS-1$
+	// predefined type constant names
+	public static final char[][] JAVA_LANG_REFLECT_FIELD = new char[][] {TypeConstants.JAVA, TypeConstants.LANG, TypeConstants.REFLECT, "Field".toCharArray()}; //$NON-NLS-1$
+	public static final char[][] JAVA_LANG_REFLECT_METHOD = new char[][] {TypeConstants.JAVA, TypeConstants.LANG, TypeConstants.REFLECT, "Method".toCharArray()}; //$NON-NLS-1$
+	public static final char[] JavaIoPrintStreamSignature = "Ljava/io/PrintStream;".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangAssertionErrorConstantPoolName = "java/lang/AssertionError".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangBooleanConstantPoolName = "java/lang/Boolean".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangByteConstantPoolName = "java/lang/Byte".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangCharacterConstantPoolName = "java/lang/Character".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangClassConstantPoolName = "java/lang/Class".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangClassNotFoundExceptionConstantPoolName = "java/lang/ClassNotFoundException".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangClassSignature = "Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangDoubleConstantPoolName = "java/lang/Double".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangErrorConstantPoolName = "java/lang/Error".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangExceptionConstantPoolName = "java/lang/Exception".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangFloatConstantPoolName = "java/lang/Float".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangIllegalArgumentExceptionConstantPoolName = "java/lang/IllegalArgumentException".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangIntegerConstantPoolName = "java/lang/Integer".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangLongConstantPoolName = "java/lang/Long".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangNoClassDefFoundErrorConstantPoolName = "java/lang/NoClassDefFoundError".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangObjectConstantPoolName = "java/lang/Object".toCharArray(); //$NON-NLS-1$
+	public static final char[] JAVALANGREFLECTACCESSIBLEOBJECT_CONSTANTPOOLNAME = "java/lang/reflect/AccessibleObject".toCharArray(); //$NON-NLS-1$
+	public static final char[] JAVALANGREFLECTARRAY_CONSTANTPOOLNAME = "java/lang/reflect/Array".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangReflectConstructor = "java/lang/reflect/Constructor".toCharArray();   //$NON-NLS-1$
+	public static final char[] JavaLangReflectConstructorNewInstanceSignature = "([Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
+	public static final char[] JAVALANGREFLECTFIELD_CONSTANTPOOLNAME = "java/lang/reflect/Field".toCharArray(); //$NON-NLS-1$
+	public static final char[] JAVALANGREFLECTMETHOD_CONSTANTPOOLNAME = "java/lang/reflect/Method".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangShortConstantPoolName = "java/lang/Short".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangStringBufferConstantPoolName = "java/lang/StringBuffer".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangStringBuilderConstantPoolName = "java/lang/StringBuilder".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangStringConstantPoolName = "java/lang/String".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangStringSignature = "Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangSystemConstantPoolName = "java/lang/System".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangThrowableConstantPoolName = "java/lang/Throwable".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaLangVoidConstantPoolName = "java/lang/Void".toCharArray(); //$NON-NLS-1$
+	public static final char[] JavaUtilIteratorConstantPoolName = "java/util/Iterator".toCharArray(); //$NON-NLS-1$
+	public static final char[] LongConstrSignature = "(J)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] longLongSignature = "(J)Ljava/lang/Long;".toCharArray(); //$NON-NLS-1$
+	public static final char[] LONGVALUE_LONG_METHOD_NAME = "longValue".toCharArray(); //$NON-NLS-1$
+	public static final char[] LONGVALUE_LONG_METHOD_SIGNATURE = "()J".toCharArray(); //$NON-NLS-1$
+	public static final char[] Name = "name".toCharArray(); //$NON-NLS-1$
+	public static final char[] NameSignature = "()Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+	public static final char[] NewInstance = "newInstance".toCharArray(); //$NON-NLS-1$
+	public static final char[] NewInstanceSignature = "(Ljava/lang/Class;[I)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
+	public static final char[] Next = "next".toCharArray();//$NON-NLS-1$
+	public static final char[] NextSignature = "()Ljava/lang/Object;".toCharArray();//$NON-NLS-1$
+	public static final char[] ObjectConstrSignature = "(Ljava/lang/Object;)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] Ordinal = "ordinal".toCharArray(); //$NON-NLS-1$
+	public static final char[] OrdinalSignature = "()I".toCharArray(); //$NON-NLS-1$
+	public static final char[] Out = "out".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_BOOLEAN_METHOD_NAME = "setBoolean".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_BOOLEAN_METHOD_SIGNATURE = "(Ljava/lang/Object;Z)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_BYTE_METHOD_NAME = "setByte".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_BYTE_METHOD_SIGNATURE = "(Ljava/lang/Object;B)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_CHAR_METHOD_NAME = "setChar".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_CHAR_METHOD_SIGNATURE = "(Ljava/lang/Object;C)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_DOUBLE_METHOD_NAME = "setDouble".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_DOUBLE_METHOD_SIGNATURE = "(Ljava/lang/Object;D)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_FLOAT_METHOD_NAME = "setFloat".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_FLOAT_METHOD_SIGNATURE = "(Ljava/lang/Object;F)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_INT_METHOD_NAME = "setInt".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_INT_METHOD_SIGNATURE = "(Ljava/lang/Object;I)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_LONG_METHOD_NAME = "setLong".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_LONG_METHOD_SIGNATURE = "(Ljava/lang/Object;J)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_OBJECT_METHOD_NAME = "set".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_OBJECT_METHOD_SIGNATURE = "(Ljava/lang/Object;Ljava/lang/Object;)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_SHORT_METHOD_NAME = "setShort".toCharArray(); //$NON-NLS-1$
+	public static final char[] SET_SHORT_METHOD_SIGNATURE = "(Ljava/lang/Object;S)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] SETACCESSIBLE_NAME = "setAccessible".toCharArray(); //$NON-NLS-1$
+	public static final char[] SETACCESSIBLE_SIGNATURE = "(Z)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] ShortConstrSignature = "(S)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] shortShortSignature = "(S)Ljava/lang/Short;".toCharArray(); //$NON-NLS-1$
+	public static final char[] SHORTVALUE_SHORT_METHOD_NAME = "shortValue".toCharArray(); //$NON-NLS-1$
+	public static final char[] SHORTVALUE_SHORT_METHOD_SIGNATURE = "()S".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringBufferAppendBooleanSignature = "(Z)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringBufferAppendCharSignature = "(C)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringBufferAppendDoubleSignature = "(D)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringBufferAppendFloatSignature = "(F)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringBufferAppendIntSignature = "(I)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringBufferAppendLongSignature = "(J)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringBufferAppendObjectSignature = "(Ljava/lang/Object;)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringBufferAppendStringSignature = "(Ljava/lang/String;)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringBuilderAppendBooleanSignature = "(Z)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringBuilderAppendCharSignature = "(C)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringBuilderAppendDoubleSignature = "(D)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringBuilderAppendFloatSignature = "(F)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringBuilderAppendIntSignature = "(I)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringBuilderAppendLongSignature = "(J)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringBuilderAppendObjectSignature = "(Ljava/lang/Object;)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringBuilderAppendStringSignature = "(Ljava/lang/String;)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
+	public static final char[] StringConstructorSignature = "(Ljava/lang/String;)V".toCharArray(); //$NON-NLS-1$
+	public static final char[] This = "this".toCharArray(); //$NON-NLS-1$
+	public static final char[] ToString = "toString".toCharArray(); //$NON-NLS-1$
+	public static final char[] ToStringSignature = GetMessageSignature;
+	public static final char[] TYPE = "TYPE".toCharArray(); //$NON-NLS-1$
+	public static final char[] ValueOf = "valueOf".toCharArray(); //$NON-NLS-1$
+	public static final char[] ValueOfBooleanSignature = "(Z)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+	public static final char[] ValueOfCharSignature = "(C)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+	public static final char[] ValueOfDoubleSignature = "(D)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+	public static final char[] ValueOfFloatSignature = "(F)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+	public static final char[] ValueOfIntSignature = "(I)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+	public static final char[] ValueOfLongSignature = "(J)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+	public static final char[] ValueOfObjectSignature = "(Ljava/lang/Object;)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
 
 /**
  * ConstantPool constructor comment.
@@ -171,12 +240,9 @@
 public ConstantPool(ClassFile classFile) {
 	this.UTF8Cache = new CharArrayCache(UTF8_INITIAL_SIZE);
 	this.stringCache = new CharArrayCache(STRING_INITIAL_SIZE);
-	this.fieldCache = new ObjectCache(FIELD_INITIAL_SIZE);
-	this.methodCache = new ObjectCache(METHOD_INITIAL_SIZE);
-	this.interfaceMethodCache = new ObjectCache(INTERFACE_INITIAL_SIZE);
-	this.classCache = new ObjectCache(CLASS_INITIAL_SIZE);
-	this.nameAndTypeCacheForMethods = new MethodNameAndTypeCache(NAMEANDTYPE_INITIAL_SIZE);
-	this.nameAndTypeCacheForFields = new FieldNameAndTypeCache(NAMEANDTYPE_INITIAL_SIZE);   
+	this.methodsAndFieldsCache = new HashtableOfObject(METHODS_AND_FIELDS_INITIAL_SIZE);
+	this.classCache = new CharArrayCache(CLASS_INITIAL_SIZE);
+	this.nameAndTypeCacheForFieldsAndMethods = new HashtableOfObject(NAMEANDTYPE_INITIAL_SIZE);
 	this.poolContent = classFile.header;
 	this.currentOffset = classFile.headerOffset;
 	// currentOffset is initialized to 0 by default
@@ -190,440 +256,23 @@
 	System.arraycopy(poolContent, 0, (poolContent = new byte[currentOffset]), 0, currentOffset);
 	return poolContent;
 }
-/**
- * Return the index of the @fieldBinding.
- *
- * Returns -1 if the @fieldBinding is not a predefined fieldBinding, 
- * the right index otherwise.
- *
- * @param fieldBinding org.eclipse.jdt.internal.compiler.lookup.FieldBinding
- * @return <CODE>int</CODE>
- */
-public int indexOfWellKnownFieldNameAndType(FieldBinding fieldBinding) {
-	if ((fieldBinding.type.id == T_JavaLangClass) && (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE)))
-		return TYPE_JAVALANGCLASS_NAME_AND_TYPE;
-	if ((fieldBinding.type.id == T_JavaIoPrintStream) && (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.Out)))
-		return OUT_SYSTEM_NAME_AND_TYPE;
-	return -1;
-}
-/**
- * Return the index of the @fieldBinding.
- *
- * Returns -1 if the @fieldBinding is not a predefined fieldBinding, 
- * the right index otherwise.
- *
- * @param fieldBinding org.eclipse.jdt.internal.compiler.lookup.FieldBinding
- * @return <CODE>int</CODE>
- */
-public int indexOfWellKnownFields(FieldBinding fieldBinding) {
-	switch (fieldBinding.declaringClass.id) {
-		case T_JavaLangByte :
-			if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
-				return TYPE_BYTE_FIELD;
-			break;
-		case T_JavaLangShort :
-			if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
-				return TYPE_SHORT_FIELD;
-			break;
-		case T_JavaLangCharacter :
-			if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
-				return TYPE_CHARACTER_FIELD;
-			break;
-		case T_JavaLangInteger :
-			if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
-				return TYPE_INTEGER_FIELD;
-			break;
-		case T_JavaLangLong :
-			if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
-				return TYPE_LONG_FIELD;
-			break;
-		case T_JavaLangFloat :
-			if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
-				return TYPE_FLOAT_FIELD;
-			break;
-		case T_JavaLangDouble :
-			if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
-				return TYPE_DOUBLE_FIELD;
-			break;
-		case T_JavaLangBoolean :
-			if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
-				return TYPE_BOOLEAN_FIELD;
-			break;
-		case T_JavaLangVoid :
-			if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
-				return TYPE_VOID_FIELD;
-			break;
-		case T_JavaLangSystem :
-			if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.Out))
-				return OUT_SYSTEM_FIELD;
+private int getFromCache(char[] declaringClass, char[] name, char[] signature) {
+	HashtableOfObject value = (HashtableOfObject) this.methodsAndFieldsCache.get(declaringClass);
+	if (value == null) {
+		return -1;
 	}
-	return -1;
-}
-/**
- * Return the index of the @methodBinding.
- *
- * Returns -1 if the @methodBinding is not a predefined methodBinding, 
- * the right index otherwise.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- * @return <CODE>int</CODE>
- */
-public int indexOfWellKnownMethodNameAndType(MethodBinding methodBinding) {
-	char firstChar = methodBinding.selector[0];
-	switch (firstChar) {
-		case 'f' :
-			if ((methodBinding.parameters.length == 1) && (methodBinding.parameters[0].id == T_JavaLangString) && (methodBinding.returnType.id == T_JavaLangClass) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.ForName))) {
-				// This method binding is forName(java.lang.String)
-				return FORNAME_CLASS_METHOD_NAME_AND_TYPE;
-			}
-			break;
-		case '<' :
-			if (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Init)) {
-				switch(methodBinding.parameters.length) {
-					case 1:
-						switch(methodBinding.parameters[0].id) {
-							case T_String :
-								if (CharOperation.equals(methodBinding.signature(), QualifiedNamesConstants.StringConstructorSignature)) {
-									return CONSTR_STRING_METHOD_NAME_AND_TYPE;	
-								} else {
-									return -1;
-								}
-							case T_Object :
-								if (CharOperation.equals(methodBinding.signature(), QualifiedNamesConstants.AssertionErrorObjectConstrSignature)) {
-									return CONSTR_OBJECT_METHOD_NAME_AND_TYPE;
-								} else {
-									return -1;
-								}
-							case T_int :
-								if (CharOperation.equals(methodBinding.signature(), QualifiedNamesConstants.AssertionErrorIntConstrSignature)) {
-									return CONSTR_INT_METHOD_NAME_AND_TYPE;
-								} else {
-									return -1;
-								}
-							case T_char :
-								if (CharOperation.equals(methodBinding.signature(), QualifiedNamesConstants.AssertionErrorCharConstrSignature)) {
-									return CONSTR_CHAR_METHOD_NAME_AND_TYPE;
-								} else {
-									return -1;
-								}
-							case T_boolean :
-								if (CharOperation.equals(methodBinding.signature(), QualifiedNamesConstants.AssertionErrorBooleanConstrSignature)) {
-									return CONSTR_BOOLEAN_METHOD_NAME_AND_TYPE;
-								} else {
-									return -1;
-								}
-							case T_float :
-								if (CharOperation.equals(methodBinding.signature(), QualifiedNamesConstants.AssertionErrorFloatConstrSignature)) {
-									return CONSTR_FLOAT_METHOD_NAME_AND_TYPE;
-								} else {
-									return -1;
-								}
-							case T_double :
-								if (CharOperation.equals(methodBinding.signature(), QualifiedNamesConstants.AssertionErrorDoubleConstrSignature)) {
-									return CONSTR_DOUBLE_METHOD_NAME_AND_TYPE;
-								} else {
-									return -1;
-								}
-							case T_long :
-								if (CharOperation.equals(methodBinding.signature(), QualifiedNamesConstants.AssertionErrorLongConstrSignature)) {
-									return CONSTR_LONG_METHOD_NAME_AND_TYPE;
-								} else {
-									return -1;
-								}
-						}
-					case 0:
-						if (methodBinding.signature().length == 3) {
-							return DEFAULT_CONSTR_METHOD_NAME_AND_TYPE;
-						}
-				}
-			}
-			break;
-		case 'a' :
-			if ((methodBinding.parameters.length == 1) && (methodBinding.returnType.id == T_JavaLangStringBuffer) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Append))) {
-				switch (methodBinding.parameters[0].id) {
-					case T_int :
-					case T_byte :
-					case T_short :
-						// This method binding is append(int)
-						return APPEND_INT_METHOD_NAME_AND_TYPE;
-					case T_float :
-						// This method binding is append(float)
-						return APPEND_FLOAT_METHOD_NAME_AND_TYPE;
-					case T_long :
-						// This method binding is append(long)
-						return APPEND_LONG_METHOD_NAME_AND_TYPE;
-					case T_JavaLangObject :
-						// This method binding is append(java.lang.Object)
-						return APPEND_OBJECT_METHOD_NAME_AND_TYPE;
-					case T_char :
-						// This method binding is append(char)
-						return APPEND_CHAR_METHOD_NAME_AND_TYPE;
-					case T_JavaLangString :
-						// This method binding is append(java.lang.String)
-						return APPEND_STRING_METHOD_NAME_AND_TYPE;
-					case T_boolean :
-						// This method binding is append(boolean)
-						return APPEND_BOOLEAN_METHOD_NAME_AND_TYPE;
-					case T_double :
-						// This method binding is append(double)
-						return APPEND_DOUBLE_METHOD_NAME_AND_TYPE;
-				}
-			}
-			break;
-		case 't' :
-			if ((methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.ToString))) {
-				// This method binding is toString()
-				return TOSTRING_METHOD_NAME_AND_TYPE;
-			}
-			break;
-		case 'v' :
-			if ((methodBinding.parameters.length == 1) && (methodBinding.returnType.id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.ValueOf))) {
-				switch(methodBinding.parameters[0].id) {
-					case T_Object:
-						return VALUEOF_OBJECT_METHOD_NAME_AND_TYPE;
-					case T_int:
-					case T_short:
-					case T_byte:
-						return VALUEOF_INT_METHOD_NAME_AND_TYPE;
-					case T_long:
-						return VALUEOF_LONG_METHOD_NAME_AND_TYPE;
-					case T_float:
-						return VALUEOF_FLOAT_METHOD_NAME_AND_TYPE;
-					case T_double:
-						return VALUEOF_DOUBLE_METHOD_NAME_AND_TYPE;
-					case T_boolean:
-						return VALUEOF_BOOLEAN_METHOD_NAME_AND_TYPE;
-					case T_char:
-						return VALUEOF_CHAR_METHOD_NAME_AND_TYPE;
-				}
-			}
-			break;
-		case 'e' :
-			if ((methodBinding.parameters.length == 1) && (methodBinding.parameters[0].id == T_int) && (methodBinding.returnType.id == T_void) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Exit))) {
-				// This method binding is exit(int)
-				return EXIT_METHOD_NAME_AND_TYPE;
-			}
-			break;
-		case 'g' :
-			if ((methodBinding.selector.length == 10)
-			    && (methodBinding.parameters.length == 0)
-			    && (methodBinding.returnType.id == T_JavaLangString)
-			    && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.GetMessage))) {
-				// This method binding is getMessage()
-				return GETMESSAGE_METHOD_NAME_AND_TYPE;
-			}
-			if (methodBinding.parameters.length == 0
-				&& methodBinding.returnType.id == T_JavaLangClass
-				&& CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.GetClass)) {
-					return GETCLASS_OBJECT_METHOD_NAME_AND_TYPE;
-			}
-			if (methodBinding.parameters.length == 0
-				&& methodBinding.returnType.id == T_JavaLangClass
-				&& CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.GetComponentType)) {
-					return GETCOMPONENTTYPE_CLASS_METHOD_NAME_AND_TYPE;
-			}
-			break;
-		case 'i' :
-			if ((methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Intern))) {
-				// This method binding is toString()
-				return INTERN_METHOD_NAME_AND_TYPE;
-			}       
+	CharArrayCache value2 = (CharArrayCache) value.get(name);
+	if (value2 == null) {
+		return -1;
 	}
-	return -1;
+	return value2.get(signature);
 }
-/**
- * Return the index of the @methodBinding.
- *
- * Returns -1 if the @methodBinding is not a predefined methodBinding, 
- * the right index otherwise.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- * @return <CODE>int</CODE>
- */
-public int indexOfWellKnownMethods(MethodBinding methodBinding) {
-	char firstChar = methodBinding.selector[0];
-	switch (methodBinding.declaringClass.id) {
-		case T_JavaLangClass :
-			if ((firstChar == 'f') && (methodBinding.isStatic()) && (methodBinding.parameters.length == 1) && (methodBinding.parameters[0].id == T_JavaLangString) && (methodBinding.returnType.id == T_JavaLangClass) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.ForName))) {
-				// This method binding is forName(java.lang.String)
-				return FORNAME_CLASS_METHOD;
-			} else if ((firstChar == 'd') && (methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_boolean) && CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.DesiredAssertionStatus)) {
-					return DESIREDASSERTIONSTATUS_CLASS_METHOD;
-			} else if ((firstChar == 'g') && (methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_JavaLangClass) && CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.GetComponentType)) {
-				return GETCOMPONENTTYPE_CLASS_METHOD;
-			}
-			break;
-		case T_JavaLangNoClassDefError :
-			if ((firstChar == '<') && (methodBinding.parameters.length == 1) && (methodBinding.parameters[0].id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Init))) {
-				// This method binding is NoClassDefFoundError(java.lang.String)
-				return NOCLASSDEFFOUNDERROR_CONSTR_METHOD;
-			}
-			break;
-		case T_JavaLangReflectConstructor :
-			if ((firstChar == 'n') && (methodBinding.parameters.length == 1) && (methodBinding.returnType.id == T_JavaLangObject) && CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.NewInstance) && CharOperation.equals(methodBinding.parameters[0].constantPoolName(), QualifiedNamesConstants.ArrayJavaLangObjectConstantPoolName)) {
-				return NEWINSTANCE_CONSTRUCTOR_METHOD;
-			}
-			break;
-		case T_JavaLangStringBuffer :
-			if ((firstChar == 'a') && (methodBinding.parameters.length == 1) && (methodBinding.returnType.id == T_JavaLangStringBuffer) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Append))) {
-				switch (methodBinding.parameters[0].id) {
-					case T_int :
-					case T_byte :
-					case T_short :
-						// This method binding is append(int)
-						return APPEND_INT_METHOD;
-					case T_float :
-						// This method binding is append(float)
-						return APPEND_FLOAT_METHOD;
-					case T_long :
-						// This method binding is append(long)
-						return APPEND_LONG_METHOD;
-					case T_JavaLangObject :
-						// This method binding is append(java.lang.Object)
-						return APPEND_OBJECT_METHOD;
-					case T_char :
-						// This method binding is append(char)
-						return APPEND_CHAR_METHOD;
-					case T_JavaLangString :
-						// This method binding is append(java.lang.String)
-						return APPEND_STRING_METHOD;
-					case T_boolean :
-						// This method binding is append(boolean)
-						return APPEND_BOOLEAN_METHOD;
-					case T_double :
-						// This method binding is append(double)
-						return APPEND_DOUBLE_METHOD;
-				}
-			} else
-				if ((firstChar == 't') && (methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.ToString))) {
-					// This method binding is toString()
-					return STRINGBUFFER_TOSTRING_METHOD;
-				} else
-					if ((firstChar == '<') && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Init))) {
-						if ((methodBinding.parameters.length == 1) && (methodBinding.parameters[0].id == T_JavaLangString)) {
-							// This method binding is <init>(String)                    
-							return STRINGBUFFER_STRING_CONSTR_METHOD;
-						} else {
-							if (methodBinding.parameters.length == 0) {
-								// This method binding is <init>()
-								return STRINGBUFFER_DEFAULT_CONSTR_METHOD;
-							}
-						}
-					}
-			break;
-		case T_JavaLangString :
-			if ((firstChar == 'v') && (methodBinding.parameters.length == 1) && (methodBinding.returnType.id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.ValueOf))) {
-				// This method binding is valueOf(java.lang.Object)
-				switch (methodBinding.parameters[0].id) {
-					case T_Object :
-						return VALUEOF_OBJECT_METHOD;
-					case T_int :
-					case T_short :
-					case T_byte :
-						return VALUEOF_INT_METHOD;
-					case T_long :
-						return VALUEOF_LONG_METHOD;
-					case T_float :
-						return VALUEOF_FLOAT_METHOD;
-					case T_double :
-						return VALUEOF_DOUBLE_METHOD;
-					case T_boolean :
-						return VALUEOF_BOOLEAN_METHOD;
-					case T_char :
-						return VALUEOF_CHAR_METHOD;
-				}
-			} else
-				if ((firstChar == 'i') && (methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Intern))) {
-					// This method binding is valueOf(java.lang.Object)
-					return STRING_INTERN_METHOD;
-				}
-			break;
-		case T_JavaLangSystem :
-			if ((firstChar == 'e') && (methodBinding.parameters.length == 1) && (methodBinding.parameters[0].id == T_int) && (methodBinding.returnType.id == T_void) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Exit))) {
-				// This method binding is exit(int)
-				return SYSTEM_EXIT_METHOD;
-			}
-			break;
-		case T_JavaLangThrowable :
-			if ((firstChar == 'g') && (methodBinding.selector.length == 10) && (methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.GetMessage))) {
-				// This method binding is getMessage()
-				return THROWABLE_GETMESSAGE_METHOD;
-			}
-			break;
-		case T_JavaLangError :
-			if ((firstChar == '<') && (methodBinding.parameters.length == 1) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Init)) && (methodBinding.parameters[0].id == T_String)) {
-				return JAVALANGERROR_CONSTR_METHOD;
-			}
-			break;
-		case T_JavaLangAssertionError :
-			if ((firstChar == '<') && CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Init)) {
-				switch (methodBinding.parameters.length) {
-					case 0:
-						return ASSERTIONERROR_DEFAULT_CONSTR_METHOD;
-					case 1:
-						switch(methodBinding.parameters[0].id) {
-							case T_boolean :
-								return ASSERTIONERROR_CONSTR_BOOLEAN_METHOD;
-							case T_char :
-								return ASSERTIONERROR_CONSTR_CHAR_METHOD;
-							case T_double :
-								return ASSERTIONERROR_CONSTR_DOUBLE_METHOD;
-							case T_int :
-							case T_byte :
-							case T_short :
-								return ASSERTIONERROR_CONSTR_INT_METHOD;
-							case T_float :
-								return ASSERTIONERROR_CONSTR_FLOAT_METHOD;
-							case T_long :
-								return ASSERTIONERROR_CONSTR_LONG_METHOD;
-							default:
-								return ASSERTIONERROR_CONSTR_OBJECT_METHOD;
-						}
-				}
-			}
-			break;
-		case T_JavaLangObject :
-			if (methodBinding.parameters.length == 0
-				&& CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.GetClass)) {
-					return GETCLASS_OBJECT_METHOD;
-			}			
+private int getFromNameAndTypeCache(char[] name, char[] signature) {
+	CharArrayCache value = (CharArrayCache) this.nameAndTypeCacheForFieldsAndMethods.get(name);
+	if (value == null) {
+		return -1;
 	}
-	return -1;
-}
-/**
- * Return the index of the @typeBinding
- *
- * Returns -1 if the @typeBinding is not a predefined binding, the right index 
- * otherwise.
- *
- * @param typeBinding org.eclipse.jdt.internal.compiler.lookup.TypeBinding
- * @return <CODE>int</CODE>
- */
-public int indexOfWellKnownTypes(TypeBinding typeBinding) {
-	switch(typeBinding.id) {
-		case T_JavaLangBoolean : return JAVA_LANG_BOOLEAN_TYPE;
-		case T_JavaLangByte : return JAVA_LANG_BYTE_TYPE;
-		case T_JavaLangCharacter : return JAVA_LANG_CHARACTER_TYPE;
-		case T_JavaLangDouble : return JAVA_LANG_DOUBLE_TYPE;
-		case T_JavaLangFloat : return JAVA_LANG_FLOAT_TYPE;
-		case T_JavaLangInteger : return JAVA_LANG_INTEGER_TYPE;
-		case T_JavaLangLong : return JAVA_LANG_LONG_TYPE;
-		case T_JavaLangShort : return JAVA_LANG_SHORT_TYPE;
-		case T_JavaLangVoid : return JAVA_LANG_VOID_TYPE;
-		case T_JavaLangClass : return JAVA_LANG_CLASS_TYPE;
-		case T_JavaLangClassNotFoundException : return JAVA_LANG_CLASSNOTFOUNDEXCEPTION_TYPE;
-		case T_JavaLangNoClassDefError : return JAVA_LANG_NOCLASSDEFFOUNDERROR_TYPE;
-		case T_JavaLangObject : return JAVA_LANG_OBJECT_TYPE;
-		case T_JavaLangString : return JAVA_LANG_STRING_TYPE;
-		case T_JavaLangStringBuffer : return JAVA_LANG_STRINGBUFFER_TYPE;
-		case T_JavaLangSystem : return JAVA_LANG_SYSTEM_TYPE;
-		case T_JavaLangThrowable : return JAVA_LANG_THROWABLE_TYPE;
-		case T_JavaLangError : return JAVA_LANG_ERROR_TYPE;
-		case T_JavaLangException : return JAVA_LANG_EXCEPTION_TYPE;
-		case T_JavaLangReflectConstructor : return JAVA_LANG_REFLECT_CONSTRUCTOR_TYPE;
-		case T_JavaLangAssertionError : return JAVA_LANG_ASSERTIONERROR_TYPE;
-	}
-	return -1;
+	return value.get(signature);
 }
 public int literalIndex(byte[] utf8encoding, char[] stringCharArray) {
 	int index;
@@ -908,35 +557,20 @@
  */
 public int literalIndex(FieldBinding aFieldBinding) {
 	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	int indexWellKnownField;
-	if ((indexWellKnownField = indexOfWellKnownFields(aFieldBinding)) == -1) {
-		if ((index = fieldCache.get(aFieldBinding)) < 0) {
-			// The entry doesn't exit yet
-			classIndex = literalIndex(aFieldBinding.declaringClass);
-			nameAndTypeIndex = literalIndexForFields(literalIndex(aFieldBinding.name), literalIndex(aFieldBinding.type.signature()), aFieldBinding);
-			index = fieldCache.put(aFieldBinding, currentIndex++);
-			if (index > 0xFFFF){
-				this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-			}
-			writeU1(FieldRefTag);
-			writeU2(classIndex);
-			writeU2(nameAndTypeIndex);
+	final char[] name = aFieldBinding.name;
+	final char[] signature = aFieldBinding.type.signature();
+	final char[] declaringClassConstantPoolName = aFieldBinding.declaringClass.constantPoolName();
+	if ((index = getFromCache(declaringClassConstantPoolName, name, signature)) < 0) {
+		// The entry doesn't exit yet
+		int classIndex = literalIndexForType(declaringClassConstantPoolName);
+		int nameAndTypeIndex = literalIndexForFields(literalIndex(name), literalIndex(signature), name, signature);
+		index = putInCache(declaringClassConstantPoolName, name, signature, currentIndex++);
+		if (index > 0xFFFF){
+			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
 		}
-	} else {
-		if ((index = wellKnownFields[indexWellKnownField]) == 0) {
-			// that field need to be inserted
-			classIndex = literalIndex(aFieldBinding.declaringClass);
-			nameAndTypeIndex = literalIndexForFields(literalIndex(aFieldBinding.name), literalIndex(aFieldBinding.type.signature()), aFieldBinding);
-			index = wellKnownFields[indexWellKnownField] = currentIndex++;
-			if (index > 0xFFFF){
-				this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-			}
-			writeU1(FieldRefTag);
-			writeU2(classIndex);
-			writeU2(nameAndTypeIndex);
-		}
+		writeU1(FieldRefTag);
+		writeU2(classIndex);
+		writeU2(nameAndTypeIndex);
 	}
 	return index;
 }
@@ -951,99 +585,54 @@
  */
 public int literalIndex(MethodBinding aMethodBinding) {
 	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	int indexWellKnownMethod;
-	if ((indexWellKnownMethod = indexOfWellKnownMethods(aMethodBinding)) == -1) {
-		if (aMethodBinding.constantPoolDeclaringClass().isInterface()) {
-			// Lookinf into the interface method ref table
-			if ((index = interfaceMethodCache.get(aMethodBinding)) < 0) {
-				classIndex = literalIndex(aMethodBinding.constantPoolDeclaringClass());
-				nameAndTypeIndex = literalIndexForMethods(literalIndex(aMethodBinding.constantPoolName()), literalIndex(aMethodBinding.signature()), aMethodBinding);
-				index = interfaceMethodCache.put(aMethodBinding, currentIndex++);
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the interface method ref constant into the constant pool
-				// First add the tag
-				writeU1(InterfaceMethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-		} else {
-			// Lookinf into the method ref table
-			if ((index = methodCache.get(aMethodBinding)) < 0) {
-				classIndex = literalIndex(aMethodBinding.constantPoolDeclaringClass());
-				nameAndTypeIndex = literalIndexForMethods(literalIndex(aMethodBinding.constantPoolName()), literalIndex(aMethodBinding.signature()), aMethodBinding);
-				index = methodCache.put(aMethodBinding, currentIndex++);
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
+	final TypeBinding constantPoolDeclaringClass = aMethodBinding.constantPoolDeclaringClass();
+	final char[] declaringClassConstantPoolName = constantPoolDeclaringClass.constantPoolName();
+	final char[] selector = aMethodBinding.selector;
+	final char[] signature = aMethodBinding.signature();
+	if ((index = getFromCache(declaringClassConstantPoolName, selector, signature)) < 0) {
+		int classIndex = literalIndexForType(constantPoolDeclaringClass.constantPoolName());
+		int nameAndTypeIndex = literalIndexForMethods(literalIndex(selector), literalIndex(signature), selector, signature);
+		index = putInCache(declaringClassConstantPoolName, selector, signature, currentIndex++);
+		if (index > 0xFFFF){
+			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
 		}
-	} else {
-		// This is a well known method
-		if ((index = wellKnownMethods[indexWellKnownMethod]) == 0) {
-			// this methods was not inserted yet
-			if (aMethodBinding.constantPoolDeclaringClass().isInterface()) {
-				// Lookinf into the interface method ref table
-				classIndex = literalIndex(aMethodBinding.constantPoolDeclaringClass());
-				nameAndTypeIndex = literalIndexForMethods(literalIndex(aMethodBinding.constantPoolName()), literalIndex(aMethodBinding.signature()), aMethodBinding);
-				index = wellKnownMethods[indexWellKnownMethod] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the interface method ref constant into the constant pool
-				// First add the tag
-				writeU1(InterfaceMethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			} else {
-				// Lookinf into the method ref table
-				classIndex = literalIndex(aMethodBinding.constantPoolDeclaringClass());
-				nameAndTypeIndex = literalIndexForMethods(literalIndex(aMethodBinding.constantPoolName()), literalIndex(aMethodBinding.signature()), aMethodBinding);
-				index = wellKnownMethods[indexWellKnownMethod] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-		}
+		// Write the interface method ref constant into the constant pool
+		// First add the tag
+		writeU1(constantPoolDeclaringClass.isInterface() || constantPoolDeclaringClass.isAnnotationType() ? InterfaceMethodRefTag : MethodRefTag);
+		// Then write the class index
+		writeU2(classIndex);
+		// The write the nameAndType index
+		writeU2(nameAndTypeIndex);
 	}
 	return index;
 }
 /**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @param aTypeBinding TypeBinding
- * @return <CODE>int</CODE>
+ * This method returns the index into the constantPool corresponding to the type descriptor 
+ * corresponding to a type constant pool name.
  */
-public int literalIndex(TypeBinding aTypeBinding) {
+public int literalIndexForType(final char[] constantPoolName) {
 	int index;
-	int nameIndex;
-	int indexWellKnownType;
-	if ((indexWellKnownType = indexOfWellKnownTypes(aTypeBinding)) == -1) {
-		if ((index = classCache.get(aTypeBinding)) < 0) {
+	if ((index = classCache.get(constantPoolName)) < 0) {
+		// The entry doesn't exit yet
+		int nameIndex = literalIndex(constantPoolName);
+		index = classCache.put(constantPoolName, currentIndex++);
+		if (index > 0xFFFF){
+			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+		}
+		writeU1(ClassTag);
+		// Then add the 8 bytes representing the long
+		writeU2(nameIndex);
+	}
+	return index;
+}
+public int literalIndexForMethod(char[] declaringClass, char[] selector, char[] signature, boolean isInterface) {
+	int index = getFromCache(declaringClass, selector, signature);
+	if (index == -1) {
+		int classIndex;
+		if ((classIndex = classCache.get(declaringClass)) < 0) {
 			// The entry doesn't exit yet
-			nameIndex = literalIndex(aTypeBinding.constantPoolName());
-			index = classCache.put(aTypeBinding, currentIndex++);
+			int nameIndex = literalIndex(declaringClass);
+			classIndex = classCache.put(declaringClass, this.currentIndex++);
 			if (index > 0xFFFF){
 				this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
 			}
@@ -1051,11 +640,61 @@
 			// Then add the 8 bytes representing the long
 			writeU2(nameIndex);
 		}
-	} else {
-		if ((index = wellKnownTypes[indexWellKnownType]) == 0) {
-			// Need to insert that binding
-			nameIndex = literalIndex(aTypeBinding.constantPoolName());
-			index = wellKnownTypes[indexWellKnownType] = currentIndex++;
+		int nameAndTypeIndex = literalIndexForMethod(selector, signature);
+		index = putInCache(declaringClass, selector, signature, currentIndex++);
+		if (index > 0xFFFF){
+			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+		}
+		// Write the interface method ref constant into the constant pool
+		// First add the tag
+		writeU1(isInterface ? InterfaceMethodRefTag : MethodRefTag);
+		// Then write the class index
+		writeU2(classIndex);
+		// The write the nameAndType index
+		writeU2(nameAndTypeIndex);		
+	}
+	return index;
+}
+private int literalIndexForField(char[] name, char[] signature) {
+	int index = getFromNameAndTypeCache(name, signature);
+	if (index == -1) {
+		// The entry doesn't exit yet
+		int nameIndex = literalIndex(name);
+		int typeIndex = literalIndex(signature);
+		index = putInNameAndTypeCache(name, signature, currentIndex++);
+		if (index > 0xFFFF){
+			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+		}
+		writeU1(NameAndTypeTag);
+		writeU2(nameIndex);
+		writeU2(typeIndex);
+	}
+	return index;
+}
+public int literalIndexForMethod(char[] selector, char[] signature) {
+	int index = getFromNameAndTypeCache(selector, signature);
+	if (index == -1) {
+		// The entry doesn't exit yet
+		int nameIndex = literalIndex(selector);
+		int typeIndex = literalIndex(signature);
+		index = putInNameAndTypeCache(selector, signature, currentIndex++);
+		if (index > 0xFFFF){
+			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+		}
+		writeU1(NameAndTypeTag);
+		writeU2(nameIndex);
+		writeU2(typeIndex);
+	}
+	return index;
+}
+public int literalIndexForField(char[] declaringClass, char[] name, char[] signature) {
+	int index = getFromCache(declaringClass, name, signature);
+	if (index == -1) {
+		int classIndex;
+		if ((classIndex = classCache.get(declaringClass)) < 0) {
+			// The entry doesn't exit yet
+			int nameIndex = literalIndex(declaringClass);
+			classIndex = classCache.put(declaringClass, this.currentIndex++);
 			if (index > 0xFFFF){
 				this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
 			}
@@ -1063,6 +702,18 @@
 			// Then add the 8 bytes representing the long
 			writeU2(nameIndex);
 		}
+		int nameAndTypeIndex = literalIndexForField(name, signature);
+		index = putInCache(declaringClass, name, signature, currentIndex++);
+		if (index > 0xFFFF){
+			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+		}
+		// Write the interface method ref constant into the constant pool
+		// First add the tag
+		writeU1(FieldRefTag);
+		// Then write the class index
+		writeU2(classIndex);
+		// The write the nameAndType index
+		writeU2(nameAndTypeIndex);		
 	}
 	return index;
 }
@@ -1070,1821 +721,24 @@
  * This method returns the index into the constantPool corresponding 
  * nameAndType constant with nameIndex, typeIndex.
  *
- * @param nameIndex int
- * @param typeIndex int
- * @param key org.eclipse.jdt.internal.compiler.lookup.FieldBinding
- * @return <CODE>int</CODE>
+ * @param nameIndex the given name index
+ * @param typeIndex the given type index
+ * @param name the given field name
+ * @param signature the given field signature
+ * @return the index into the constantPool corresponding 
+ * nameAndType constant with nameIndex, typeInde
  */
-public int literalIndexForFields(int nameIndex, int typeIndex, FieldBinding key) {
+private int literalIndexForFields(int nameIndex, int typeIndex, char[] name, char[] signature) {
 	int index;
-	int indexOfWellKnownFieldNameAndType;
-	if ((indexOfWellKnownFieldNameAndType = indexOfWellKnownFieldNameAndType(key)) == -1) {
-		// check if the entry already exists
-		if ((index = nameAndTypeCacheForFields.get(key)) == -1) {
-			// The entry doesn't exit yet
-			index = nameAndTypeCacheForFields.put(key, currentIndex++);
-			if (index > 0xFFFF){
-				this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-			}
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-	} else {
-		if ((index = wellKnownFieldNameAndTypes[indexOfWellKnownFieldNameAndType]) == 0) {
-			index = wellKnownFieldNameAndTypes[indexOfWellKnownFieldNameAndType] = currentIndex++;
-			if (index > 0xFFFF){
-				this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-			}
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangBoolean() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_BOOLEAN_TYPE]) == 0) {
-		int nameIndex;
+	if ((index = getFromNameAndTypeCache(name, signature)) == -1) {
 		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangBooleanConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_BOOLEAN_TYPE] = currentIndex++;
+		index = putInNameAndTypeCache(name, signature, currentIndex++);
 		if (index > 0xFFFF){
 			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
 		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
+		writeU1(NameAndTypeTag);
 		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool 
- * corresponding to the field binding aFieldBinding.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangBooleanTYPE() {
-	int index;
-	if ((index = wellKnownFields[TYPE_BOOLEAN_FIELD]) == 0) {
-		int nameAndTypeIndex;
-		int classIndex;
-		// The entry doesn't exit yet
-		classIndex = literalIndexForJavaLangBoolean();
-		if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
-			int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
-			nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownFields[TYPE_BOOLEAN_FIELD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(FieldRefTag);
-		writeU2(classIndex);
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangByte() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_BYTE_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangByteConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_BYTE_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool 
- * corresponding to the field binding aFieldBinding.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangByteTYPE() {
-	int index;
-	if ((index = wellKnownFields[TYPE_BYTE_FIELD]) == 0) {
-		int nameAndTypeIndex;
-		int classIndex;
-		// The entry doesn't exit yet
-		classIndex = literalIndexForJavaLangByte();
-		if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
-			int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
-			nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownFields[TYPE_BYTE_FIELD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(FieldRefTag);
-		writeU2(classIndex);
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangCharacter() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_CHARACTER_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangCharacterConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_CHARACTER_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool 
- * corresponding to the field binding aFieldBinding.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangCharacterTYPE() {
-	int index;
-	if ((index = wellKnownFields[TYPE_CHARACTER_FIELD]) == 0) {
-		int nameAndTypeIndex;
-		int classIndex;
-		// The entry doesn't exit yet
-		classIndex = literalIndexForJavaLangCharacter();
-		if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
-			int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
-			nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownFields[TYPE_CHARACTER_FIELD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(FieldRefTag);
-		writeU2(classIndex);
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangClass() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_CLASS_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangClassConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_CLASS_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangClassForName() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = wellKnownMethods[FORNAME_CLASS_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangClass();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[FORNAME_CLASS_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.ForName);
-			int typeIndex = literalIndex(QualifiedNamesConstants.ForNameSignature);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[FORNAME_CLASS_METHOD_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownMethods[FORNAME_CLASS_METHOD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangClassDesiredAssertionStatus() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = wellKnownMethods[DESIREDASSERTIONSTATUS_CLASS_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangClass();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[DESIREDASSERTIONSTATUS_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.DesiredAssertionStatus);
-			int typeIndex = literalIndex(QualifiedNamesConstants.DesiredAssertionStatusSignature);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[DESIREDASSERTIONSTATUS_METHOD_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownMethods[DESIREDASSERTIONSTATUS_CLASS_METHOD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangClassGetComponentType() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = wellKnownMethods[GETCOMPONENTTYPE_CLASS_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangClass();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[GETCOMPONENTTYPE_CLASS_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.GetComponentType);
-			int typeIndex = literalIndex(QualifiedNamesConstants.GetComponentTypeSignature);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[GETCOMPONENTTYPE_CLASS_METHOD_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownMethods[GETCOMPONENTTYPE_CLASS_METHOD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangClassNotFoundException() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_CLASSNOTFOUNDEXCEPTION_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangClassNotFoundExceptionConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_CLASSNOTFOUNDEXCEPTION_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangDouble() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_DOUBLE_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangDoubleConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_DOUBLE_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool 
- * corresponding to the field binding aFieldBinding.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangDoubleTYPE() {
-	int index;
-	if ((index = wellKnownFields[TYPE_DOUBLE_FIELD]) == 0) {
-		int nameAndTypeIndex;
-		int classIndex;
-		// The entry doesn't exit yet
-		classIndex = literalIndexForJavaLangDouble();
-		if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
-			int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
-			nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownFields[TYPE_DOUBLE_FIELD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(FieldRefTag);
-		writeU2(classIndex);
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangError() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_ERROR_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangErrorConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_ERROR_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangErrorConstructor() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = wellKnownMethods[JAVALANGERROR_CONSTR_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangError();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.Init);
-			int typeIndex = literalIndex(QualifiedNamesConstants.StringConstructorSignature);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownMethods[JAVALANGERROR_CONSTR_METHOD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-public int literalIndexForJavaLangException() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_EXCEPTION_TYPE]) == 0) {
-		// The entry doesn't exit yet
-		int nameIndex = literalIndex(QualifiedNamesConstants.JavaLangExceptionConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_EXCEPTION_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangFloat() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_FLOAT_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangFloatConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_FLOAT_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool 
- * corresponding to the field binding aFieldBinding.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangFloatTYPE() {
-	int index;
-	if ((index = wellKnownFields[TYPE_FLOAT_FIELD]) == 0) {
-		int nameAndTypeIndex;
-		int classIndex;
-		// The entry doesn't exit yet
-		classIndex = literalIndexForJavaLangFloat();
-		if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
-			int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
-			nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownFields[TYPE_FLOAT_FIELD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(FieldRefTag);
-		writeU2(classIndex);
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangInteger() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_INTEGER_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangIntegerConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_INTEGER_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool 
- * corresponding to the field binding aFieldBinding.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangIntegerTYPE() {
-	int index;
-	if ((index = wellKnownFields[TYPE_INTEGER_FIELD]) == 0) {
-		int nameAndTypeIndex;
-		int classIndex;
-		// The entry doesn't exit yet
-		classIndex = literalIndexForJavaLangInteger();
-		if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
-			int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
-			nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownFields[TYPE_INTEGER_FIELD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(FieldRefTag);
-		writeU2(classIndex);
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangLong() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_LONG_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangLongConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_LONG_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool 
- * corresponding to the field binding aFieldBinding.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangLongTYPE() {
-	int index;
-	if ((index = wellKnownFields[TYPE_LONG_FIELD]) == 0) {
-		int nameAndTypeIndex;
-		int classIndex;
-		// The entry doesn't exit yet
-		classIndex = literalIndexForJavaLangLong();
-		if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
-			int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
-			nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownFields[TYPE_LONG_FIELD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(FieldRefTag);
-		writeU2(classIndex);
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangNoClassDefFoundError() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_NOCLASSDEFFOUNDERROR_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangNoClassDefFoundErrorConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_NOCLASSDEFFOUNDERROR_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangAssertionError() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_ASSERTIONERROR_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangAssertionErrorConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_ASSERTIONERROR_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @param typeBindingID int
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangAssertionErrorConstructor(int typeBindingID) {
-	int index = 0;
-	int nameAndTypeIndex = 0;
-	int classIndex = 0;
-	switch (typeBindingID) {
-		case T_int :
-		case T_byte :
-		case T_short :
-			if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_INT_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangAssertionError();
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_INT_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.Init);
-					int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorIntConstrSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_INT_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[ASSERTIONERROR_CONSTR_INT_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_long :
-			if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_LONG_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangAssertionError();
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_LONG_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.Init);
-					int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorLongConstrSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_LONG_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[ASSERTIONERROR_CONSTR_LONG_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_float :
-			if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_FLOAT_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangAssertionError();
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_FLOAT_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.Init);
-					int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorFloatConstrSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_FLOAT_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[ASSERTIONERROR_CONSTR_FLOAT_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_double :
-			if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_DOUBLE_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangAssertionError();
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_DOUBLE_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.Init);
-					int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorDoubleConstrSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_DOUBLE_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[ASSERTIONERROR_CONSTR_DOUBLE_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_char :
-			if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_CHAR_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangAssertionError();
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_CHAR_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.Init);
-					int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorCharConstrSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_CHAR_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[ASSERTIONERROR_CONSTR_CHAR_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_boolean :
-			if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_BOOLEAN_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangAssertionError();
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_BOOLEAN_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.Init);
-					int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorBooleanConstrSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_BOOLEAN_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[ASSERTIONERROR_CONSTR_BOOLEAN_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		//case T_Object :
-		//case T_String :
-		//case T_null :
-		default : 
-			if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_OBJECT_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangAssertionError();
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_OBJECT_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.Init);
-					int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorObjectConstrSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[ASSERTIONERROR_CONSTR_OBJECT_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-	}
-	return index;
-}
-
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangAssertionErrorDefaultConstructor() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = wellKnownMethods[ASSERTIONERROR_DEFAULT_CONSTR_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangAssertionError();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[DEFAULT_CONSTR_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.Init);
-			int typeIndex = literalIndex(QualifiedNamesConstants.DefaultConstructorSignature);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[DEFAULT_CONSTR_METHOD_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownMethods[ASSERTIONERROR_DEFAULT_CONSTR_METHOD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-
-
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangNoClassDefFoundErrorStringConstructor() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = wellKnownMethods[NOCLASSDEFFOUNDERROR_CONSTR_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangNoClassDefFoundError();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.Init);
-			int typeIndex = literalIndex(QualifiedNamesConstants.StringConstructorSignature);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownMethods[NOCLASSDEFFOUNDERROR_CONSTR_METHOD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangObject() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_OBJECT_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangObjectConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_OBJECT_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangReflectConstructor() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_REFLECT_CONSTRUCTOR_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangReflectConstructor);
-		index = wellKnownTypes[JAVA_LANG_REFLECT_CONSTRUCTOR_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-public int literalIndexForJavaLangReflectConstructorNewInstance() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = wellKnownMethods[NEWINSTANCE_CONSTRUCTOR_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangReflectConstructor();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[NEWINSTANCE_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.NewInstance);
-			int typeIndex = literalIndex(QualifiedNamesConstants.NewInstanceSignature);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[NEWINSTANCE_METHOD_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownMethods[NEWINSTANCE_CONSTRUCTOR_METHOD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangShort() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_SHORT_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangShortConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_SHORT_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool 
- * corresponding to the field binding aFieldBinding.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangShortTYPE() {
-	int index;
-	if ((index = wellKnownFields[TYPE_SHORT_FIELD]) == 0) {
-		int nameAndTypeIndex;
-		int classIndex;
-		// The entry doesn't exit yet
-		classIndex = literalIndexForJavaLangShort();
-		if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
-			int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
-			nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownFields[TYPE_SHORT_FIELD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(FieldRefTag);
-		writeU2(classIndex);
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangString() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_STRING_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangStringConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_STRING_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangStringBuffer() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_STRINGBUFFER_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangStringBufferConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_STRINGBUFFER_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangStringBufferAppend(int typeID) {
-	int index = 0;
-	int nameAndTypeIndex = 0;
-	int classIndex = 0;
-	switch (typeID) {
-		case T_int :
-		case T_byte :
-		case T_short :
-			if ((index = wellKnownMethods[APPEND_INT_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangStringBuffer();
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_INT_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.Append);
-					int typeIndex = literalIndex(QualifiedNamesConstants.AppendIntSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_INT_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[APPEND_INT_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_long :
-			if ((index = wellKnownMethods[APPEND_LONG_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangStringBuffer();
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_LONG_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.Append);
-					int typeIndex = literalIndex(QualifiedNamesConstants.AppendLongSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_LONG_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[APPEND_LONG_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_float :
-			if ((index = wellKnownMethods[APPEND_FLOAT_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangStringBuffer();
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_FLOAT_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.Append);
-					int typeIndex = literalIndex(QualifiedNamesConstants.AppendFloatSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_FLOAT_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[APPEND_FLOAT_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_double :
-			if ((index = wellKnownMethods[APPEND_DOUBLE_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangStringBuffer();
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_DOUBLE_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.Append);
-					int typeIndex = literalIndex(QualifiedNamesConstants.AppendDoubleSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_DOUBLE_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[APPEND_DOUBLE_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_char :
-			if ((index = wellKnownMethods[APPEND_CHAR_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangStringBuffer();
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_CHAR_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.Append);
-					int typeIndex = literalIndex(QualifiedNamesConstants.AppendCharSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_CHAR_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[APPEND_CHAR_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_boolean :
-			if ((index = wellKnownMethods[APPEND_BOOLEAN_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangStringBuffer();
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_BOOLEAN_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.Append);
-					int typeIndex = literalIndex(QualifiedNamesConstants.AppendBooleanSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_BOOLEAN_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[APPEND_BOOLEAN_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_Object :
-			if ((index = wellKnownMethods[APPEND_OBJECT_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangStringBuffer();
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_OBJECT_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.Append);
-					int typeIndex = literalIndex(QualifiedNamesConstants.AppendObjectSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[APPEND_OBJECT_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_String :
-		case T_null :
-			if ((index = wellKnownMethods[APPEND_STRING_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangStringBuffer();
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_STRING_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.Append);
-					int typeIndex = literalIndex(QualifiedNamesConstants.AppendStringSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_STRING_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[APPEND_STRING_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangStringBufferConstructor() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = wellKnownMethods[STRINGBUFFER_STRING_CONSTR_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangStringBuffer();
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.Init);
-					int typeIndex = literalIndex(QualifiedNamesConstants.StringConstructorSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-		index = wellKnownMethods[STRINGBUFFER_STRING_CONSTR_METHOD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangStringBufferDefaultConstructor() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = wellKnownMethods[STRINGBUFFER_DEFAULT_CONSTR_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangStringBuffer();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[DEFAULT_CONSTR_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.Init);
-			int typeIndex = literalIndex(QualifiedNamesConstants.DefaultConstructorSignature);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[DEFAULT_CONSTR_METHOD_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownMethods[STRINGBUFFER_DEFAULT_CONSTR_METHOD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangStringBufferToString() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = wellKnownMethods[STRINGBUFFER_TOSTRING_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangStringBuffer();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[TOSTRING_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.ToString);
-			int typeIndex = literalIndex(QualifiedNamesConstants.ToStringSignature);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[TOSTRING_METHOD_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownMethods[STRINGBUFFER_TOSTRING_METHOD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangStringIntern() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = wellKnownMethods[STRING_INTERN_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangString();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[INTERN_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.Intern);
-			int typeIndex = literalIndex(QualifiedNamesConstants.InternSignature);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[INTERN_METHOD_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownMethods[STRING_INTERN_METHOD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangStringValueOf(int typeID) {
-	int index = 0;
-	int nameAndTypeIndex = 0;
-	int classIndex = literalIndexForJavaLangString();
-	switch (typeID) {
-		case T_int :
-		case T_byte :
-		case T_short :
-			if ((index = wellKnownMethods[VALUEOF_INT_METHOD]) == 0) {
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_INT_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
-					int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfIntSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_INT_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[VALUEOF_INT_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_long :
-			if ((index = wellKnownMethods[VALUEOF_LONG_METHOD]) == 0) {
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_LONG_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
-					int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfLongSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_LONG_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[VALUEOF_LONG_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_float :
-			if ((index = wellKnownMethods[VALUEOF_FLOAT_METHOD]) == 0) {
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_FLOAT_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
-					int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfFloatSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_FLOAT_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[VALUEOF_FLOAT_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_double :
-			if ((index = wellKnownMethods[VALUEOF_DOUBLE_METHOD]) == 0) {
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_DOUBLE_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
-					int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfDoubleSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_DOUBLE_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[VALUEOF_DOUBLE_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_char :
-			if ((index = wellKnownMethods[VALUEOF_CHAR_METHOD]) == 0) {
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_CHAR_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
-					int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfCharSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_CHAR_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[VALUEOF_CHAR_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_boolean :
-			if ((index = wellKnownMethods[VALUEOF_BOOLEAN_METHOD]) == 0) {
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_BOOLEAN_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
-					int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfBooleanSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_BOOLEAN_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[VALUEOF_BOOLEAN_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_Object :
-			if ((index = wellKnownMethods[VALUEOF_OBJECT_METHOD]) == 0) {
-				if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_OBJECT_METHOD_NAME_AND_TYPE]) == 0) {
-					int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
-					int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfObjectSignature);
-					nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = wellKnownMethods[VALUEOF_OBJECT_METHOD] = currentIndex++;
-				if (index > 0xFFFF){
-					this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-				}
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangSystem() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_SYSTEM_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangSystemConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_SYSTEM_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangSystemExitInt() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = wellKnownMethods[SYSTEM_EXIT_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangSystem();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[EXIT_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.Exit);
-			int typeIndex = literalIndex(QualifiedNamesConstants.ExitIntSignature);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[EXIT_METHOD_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownMethods[SYSTEM_EXIT_METHOD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool 
- * corresponding to the field binding aFieldBinding.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangSystemOut() {
-	int index;
-	if ((index = wellKnownFields[OUT_SYSTEM_FIELD]) == 0) {
-		int nameAndTypeIndex;
-		int classIndex;
-		// The entry doesn't exit yet
-		classIndex = literalIndexForJavaLangSystem();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[OUT_SYSTEM_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.Out);
-			int typeIndex = literalIndex(QualifiedNamesConstants.JavaIoPrintStreamSignature);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[OUT_SYSTEM_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownFields[OUT_SYSTEM_FIELD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(FieldRefTag);
-		writeU2(classIndex);
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangThrowable() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_THROWABLE_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangThrowableConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_THROWABLE_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangThrowableGetMessage() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = wellKnownMethods[THROWABLE_GETMESSAGE_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangThrowable();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[GETMESSAGE_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.GetMessage);
-			int typeIndex = literalIndex(QualifiedNamesConstants.GetMessageSignature);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[GETMESSAGE_METHOD_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownMethods[THROWABLE_GETMESSAGE_METHOD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangVoid() {
-	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_VOID_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(QualifiedNamesConstants.JavaLangVoidConstantPoolName);
-		index = wellKnownTypes[JAVA_LANG_VOID_TYPE] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool 
- * corresponding to the field binding aFieldBinding.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangVoidTYPE() {
-	int index;
-	if ((index = wellKnownFields[TYPE_VOID_FIELD]) == 0) {
-		int nameAndTypeIndex;
-		int classIndex;
-		// The entry doesn't exit yet
-		classIndex = literalIndexForJavaLangVoid();
-		if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
-			int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
-			nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = wellKnownFields[TYPE_VOID_FIELD] = currentIndex++;
-		if (index > 0xFFFF){
-			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-		}
-		writeU1(FieldRefTag);
-		writeU2(classIndex);
-		writeU2(nameAndTypeIndex);
+		writeU2(typeIndex);
 	}
 	return index;
 }
@@ -2961,69 +815,61 @@
  * This method returns the index into the constantPool corresponding 
  * nameAndType constant with nameIndex, typeIndex.
  *
- * @param nameIndex int
- * @param typeIndex int
- * @param key org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+ * @param nameIndex the given name index
+ * @param typeIndex the given type index
+ * @param selector the given method selector
+ * @param signature the given method signature
  * @return <CODE>int</CODE>
  */
-public int literalIndexForMethods(int nameIndex, int typeIndex, MethodBinding key) {
+public int literalIndexForMethods(int nameIndex, int typeIndex, char[] selector, char[] signature) {
 	int index;
-	int indexOfWellKnownMethodNameAndType;
-	if ((indexOfWellKnownMethodNameAndType = indexOfWellKnownMethodNameAndType(key)) == -1) {
-		// check if the entry exists
-		if ((index = nameAndTypeCacheForMethods.get(key)) == -1) {
-			// The entry doesn't exit yet
-			index = nameAndTypeCacheForMethods.put(key, currentIndex++);
-			if (index > 0xFFFF){
-				this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-			}
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
+	if ((index = getFromNameAndTypeCache(selector, signature)) == -1) {
+		// The entry doesn't exit yet
+		index = putInNameAndTypeCache(selector, signature, currentIndex++);
+		if (index > 0xFFFF){
+			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
 		}
+		writeU1(NameAndTypeTag);
+		writeU2(nameIndex);
+		writeU2(typeIndex);
+	}
+	return index;
+}
+private int putInNameAndTypeCache(final char[] key1, final char[] key2, int index) {
+	CharArrayCache value = (CharArrayCache) this.nameAndTypeCacheForFieldsAndMethods.get(key1);
+	if (value == null) {
+		CharArrayCache charArrayCache = new CharArrayCache();
+		charArrayCache.put(key2, index);
+		this.nameAndTypeCacheForFieldsAndMethods.put(key1, charArrayCache);
 	} else {
-		if ((index = wellKnownMethodNameAndTypes[indexOfWellKnownMethodNameAndType]) == 0) {
-			index = wellKnownMethodNameAndTypes[indexOfWellKnownMethodNameAndType] = currentIndex++;
-			if (index > 0xFFFF){
-				this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-			}
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
+		value.put(key2, index);
 	}
 	return index;
 }
 /**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
+ * @param key1
+ * @param key2
+ * @param key3
+ * @param index
+ * @return the given index
  */
-public int literalIndexForJavaLangObjectGetClass() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = wellKnownMethods[GETCLASS_OBJECT_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangObject();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(QualifiedNamesConstants.GetClass);
-			int typeIndex = literalIndex(QualifiedNamesConstants.GetClassSignature);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
+private int putInCache(final char[] key1, final char[] key2, final char[] key3, int index) {
+	HashtableOfObject value = (HashtableOfObject) this.methodsAndFieldsCache.get(key1);
+	if (value == null) {
+		value = new HashtableOfObject();
+		this.methodsAndFieldsCache.put(key1, value);
+		CharArrayCache charArrayCache = new CharArrayCache();
+		charArrayCache.put(key3, index);
+		value.put(key2, charArrayCache);
+	} else {
+		CharArrayCache charArrayCache = (CharArrayCache) value.get(key2);
+		if (charArrayCache == null) {
+			charArrayCache = new CharArrayCache();
+			charArrayCache.put(key3, index);
+			value.put(key2, charArrayCache);
+		} else {
+			charArrayCache.put(key3, index);			
 		}
-		index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++;
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
 	}
 	return index;
 }
@@ -3039,11 +885,11 @@
 	if (UTF8Cache.get(AttributeNamesConstants.CodeName) >= constantPoolIndex) {
 		UTF8Cache.remove(AttributeNamesConstants.CodeName);
 	}
-	if (UTF8Cache.get(QualifiedNamesConstants.ClinitSignature) >= constantPoolIndex) {
-		UTF8Cache.remove(QualifiedNamesConstants.ClinitSignature);
+	if (UTF8Cache.get(ConstantPool.ClinitSignature) >= constantPoolIndex) {
+		UTF8Cache.remove(ConstantPool.ClinitSignature);
 	}
-	if (UTF8Cache.get(QualifiedNamesConstants.Clinit) >= constantPoolIndex) {
-		UTF8Cache.remove(QualifiedNamesConstants.Clinit);
+	if (UTF8Cache.get(ConstantPool.Clinit) >= constantPoolIndex) {
+		UTF8Cache.remove(ConstantPool.Clinit);
 	}
 }
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/QualifiedNamesConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/QualifiedNamesConstants.java
deleted file mode 100644
index aff4cb8..0000000
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/QualifiedNamesConstants.java
+++ /dev/null
@@ -1,93 +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 Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.compiler.codegen;
-
-public interface QualifiedNamesConstants {
-	char[] JavaLangObjectConstantPoolName = "java/lang/Object".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangStringConstantPoolName = "java/lang/String".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangStringBufferConstantPoolName = "java/lang/StringBuffer".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangClassConstantPoolName = "java/lang/Class".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangThrowableConstantPoolName = "java/lang/Throwable".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangClassNotFoundExceptionConstantPoolName = "java/lang/ClassNotFoundException".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangNoClassDefFoundErrorConstantPoolName = "java/lang/NoClassDefFoundError".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangIntegerConstantPoolName = "java/lang/Integer".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangFloatConstantPoolName = "java/lang/Float".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangDoubleConstantPoolName = "java/lang/Double".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangLongConstantPoolName = "java/lang/Long".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangShortConstantPoolName = "java/lang/Short".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangByteConstantPoolName = "java/lang/Byte".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangCharacterConstantPoolName = "java/lang/Character".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangVoidConstantPoolName = "java/lang/Void".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangBooleanConstantPoolName = "java/lang/Boolean".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangSystemConstantPoolName = "java/lang/System".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangErrorConstantPoolName = "java/lang/Error".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangExceptionConstantPoolName = "java/lang/Exception".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangReflectConstructor = "java/lang/reflect/Constructor".toCharArray();   //$NON-NLS-1$
-	char[] Append = new char[] {'a', 'p', 'p', 'e', 'n', 'd'};
-	char[] ToString = new char[] {'t', 'o', 'S', 't', 'r', 'i', 'n', 'g'};
-	char[] Init = new char[] {'<', 'i', 'n', 'i', 't', '>'};
-	char[] Clinit = new char[] {'<', 'c', 'l', 'i', 'n', 'i', 't', '>'};
-	char[] ValueOf = new char[] {'v', 'a', 'l', 'u', 'e', 'O', 'f'};
-	char[] ForName = new char[] {'f', 'o', 'r', 'N', 'a', 'm', 'e'};
-	char[] GetMessage = new char[] {'g', 'e', 't', 'M', 'e', 's', 's', 'a', 'g', 'e'};
-	char[] NewInstance = "newInstance".toCharArray(); //$NON-NLS-1$
-	char[] GetConstructor = "getConstructor".toCharArray(); //$NON-NLS-1$
-	char[] Exit = new char[] {'e', 'x', 'i', 't'};
-	char[] Intern = "intern".toCharArray(); //$NON-NLS-1$
-	char[] Out = new char[] {'o', 'u', 't'};
-	char[] TYPE = new char[] {'T', 'Y', 'P', 'E'};
-	char[] This = new char[] {'t', 'h', 'i', 's'};
-	char[] JavaLangClassSignature = new char[] {'L', 'j', 'a', 'v', 'a', '/', 'l', 'a', 'n', 'g', '/', 'C', 'l', 'a', 's', 's', ';'};
-	char[] ForNameSignature = "(Ljava/lang/String;)Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
-	char[] GetMessageSignature = "()Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
-	char[] GetConstructorSignature = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;".toCharArray(); //$NON-NLS-1$
-	char[] StringConstructorSignature = "(Ljava/lang/String;)V".toCharArray(); //$NON-NLS-1$
-	char[] NewInstanceSignature = "([Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
-	char[] DefaultConstructorSignature = {'(', ')', 'V'};
-	char[] ClinitSignature = DefaultConstructorSignature;
-	char[] ToStringSignature = GetMessageSignature;
-	char[] InternSignature = GetMessageSignature;
-	char[] AppendIntSignature = "(I)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
-	char[] AppendLongSignature = "(J)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
-	char[] AppendFloatSignature = "(F)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
-	char[] AppendDoubleSignature = "(D)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
-	char[] AppendCharSignature = "(C)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
-	char[] AppendBooleanSignature = "(Z)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
-	char[] AppendObjectSignature = "(Ljava/lang/Object;)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
-	char[] AppendStringSignature = "(Ljava/lang/String;)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
-	char[] ValueOfObjectSignature = "(Ljava/lang/Object;)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
-	char[] ValueOfIntSignature = "(I)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
-	char[] ValueOfLongSignature = "(J)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
-	char[] ValueOfCharSignature = "(C)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
-	char[] ValueOfBooleanSignature = "(Z)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
-	char[] ValueOfDoubleSignature = "(D)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
-	char[] ValueOfFloatSignature = "(F)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
-	char[] JavaIoPrintStreamSignature = "Ljava/io/PrintStream;".toCharArray(); //$NON-NLS-1$
-	char[] ExitIntSignature = new char[] {'(', 'I', ')', 'V'};
-	char[] ArrayJavaLangObjectConstantPoolName = "[Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
-	char[] ArrayJavaLangClassConstantPoolName = "[Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
-	char[] JavaLangAssertionErrorConstantPoolName = "java/lang/AssertionError".toCharArray(); //$NON-NLS-1$
-	char[] AssertionErrorIntConstrSignature = "(I)V".toCharArray(); //$NON-NLS-1$
-	char[] AssertionErrorLongConstrSignature = "(J)V".toCharArray(); //$NON-NLS-1$
-	char[] AssertionErrorFloatConstrSignature = "(F)V".toCharArray(); //$NON-NLS-1$
-	char[] AssertionErrorDoubleConstrSignature = "(D)V".toCharArray(); //$NON-NLS-1$
-	char[] AssertionErrorCharConstrSignature = "(C)V".toCharArray(); //$NON-NLS-1$
-	char[] AssertionErrorBooleanConstrSignature = "(Z)V".toCharArray(); //$NON-NLS-1$
-	char[] AssertionErrorObjectConstrSignature = "(Ljava/lang/Object;)V".toCharArray(); //$NON-NLS-1$
-	char[] DesiredAssertionStatus = "desiredAssertionStatus".toCharArray(); //$NON-NLS-1$
-	char[] DesiredAssertionStatusSignature = "()Z".toCharArray(); //$NON-NLS-1$
-	char[] ShortConstrSignature = "(S)V".toCharArray(); //$NON-NLS-1$
-	char[] ByteConstrSignature = "(B)V".toCharArray(); //$NON-NLS-1$
-	char[] GetClass = "getClass".toCharArray(); //$NON-NLS-1$
-	char[] GetClassSignature = "()Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
-	char[] GetComponentType = "getComponentType".toCharArray(); //$NON-NLS-1$
-	char[] GetComponentTypeSignature = GetClassSignature;
-}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/AccessRestriction.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/AccessRestriction.java
new file mode 100644
index 0000000..1ed5061
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/AccessRestriction.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.env;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+/**
+ * Definition of an access restriction rule used to flag forbidden references to non API code.
+ * A restriction can chain to further ones, the first violated restriction taking precedence.
+ */
+public class AccessRestriction {
+
+	private char[][] inclusionPatterns;
+	private char[][] exclusionPatterns;
+	protected String messageTemplate;
+	AccessRestriction furtherRestriction; // subsequent restriction
+	
+	
+	public AccessRestriction(String messageTemplate, char[][] inclusionPatterns, char[][] exclusionPatterns, AccessRestriction furtherRestriction) {
+		this.messageTemplate = messageTemplate;
+		this.inclusionPatterns = inclusionPatterns;
+		this.exclusionPatterns = exclusionPatterns;
+		this.furtherRestriction = furtherRestriction;
+	}
+	/**
+	 * @see java.lang.Object#equals(java.lang.Object)
+	 */
+	public boolean equals(Object object) {
+		if (this == object) 
+			return true;
+		if (!(object instanceof AccessRestriction))
+			return false;
+		AccessRestriction otherRestriction = (AccessRestriction) object;
+		if (!this.messageTemplate.equals(otherRestriction.messageTemplate)) 
+			return false;
+		if (this.inclusionPatterns != otherRestriction.inclusionPatterns) {
+			int length = this.inclusionPatterns == null ? 0 : this.inclusionPatterns.length;
+			int otherLength = otherRestriction.inclusionPatterns == null ? 0 : otherRestriction.inclusionPatterns.length;
+			if (length != otherLength)
+				return false;
+			for (int i = 0; i < length; i++) {
+				if (!CharOperation.equals(this.inclusionPatterns[i], otherRestriction.inclusionPatterns[i]))
+						return false;
+			}
+		}
+		if (this.exclusionPatterns != otherRestriction.exclusionPatterns) {
+			int length = this.exclusionPatterns == null ? 0 : this.exclusionPatterns.length;
+			int otherLength = otherRestriction.exclusionPatterns == null ? 0 : otherRestriction.exclusionPatterns.length;
+			if (length != otherLength)
+				return false;
+			for (int i = 0; i < length; i++) {
+				if (!CharOperation.equals(this.exclusionPatterns[i], otherRestriction.exclusionPatterns[i]))
+						return false;
+			}
+		}
+		if (this.furtherRestriction != otherRestriction.furtherRestriction) {
+			if (this.furtherRestriction == null || otherRestriction.furtherRestriction == null) 
+				return false;
+			if (!this.furtherRestriction.equals(otherRestriction.furtherRestriction))
+				return false;
+		}
+		return true;
+	}
+	/**
+	 * Select the first restriction which is violated when accessing a given type, or null if no restriction applies.
+	 * Type name is formed as: "java/lang/Object".
+	 */
+	public AccessRestriction getViolatedRestriction(char[] targetTypeName, char[] referringTypeName) {
+		
+		// check local inclusion/exclusion rules
+		if (this.inclusionPatterns != null || this.exclusionPatterns != null) {
+			if (Util.isExcluded(targetTypeName, this.inclusionPatterns, this.exclusionPatterns, false)) {
+				return this;
+			}
+		}		
+	// then check further restrictions
+		return this.furtherRestriction != null 
+						? this.furtherRestriction.getViolatedRestriction(targetTypeName, referringTypeName)
+						: null;
+	}
+	public char[][] getExclusionPatterns() {
+			return this.exclusionPatterns;
+	}
+	public char[][] getInclusionPatterns() {
+			return this.inclusionPatterns;
+	}
+	/**
+	 * Returns readable description for problem reporting, 
+	 * message is expected to contain room for restricted type name
+	 * e.g. "{0} has restricted access"
+	 */
+	public String getMessageTemplate() {
+			return this.messageTemplate;
+	}
+	
+	public String toString() {
+		StringBuffer buffer = new StringBuffer(20);
+		buffer
+			.append("AccessRestriction [includes:\"") //$NON-NLS-1$
+			.append(CharOperation.concatWith(this.inclusionPatterns,'/'))
+			.append("\"][excludes:\"") //$NON-NLS-1$
+			.append(CharOperation.concatWith(this.exclusionPatterns,'/'))
+			.append("\"][template:\"") //$NON-NLS-1$
+			.append(this.messageTemplate)
+			.append("\"]"); //$NON-NLS-1$
+		if (this.furtherRestriction != null) {
+			buffer.append('\n').append(this.furtherRestriction);
+		}
+		return buffer.toString();
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryField.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryField.java
index d928f82..28211a1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryField.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryField.java
@@ -30,4 +30,14 @@
  */
 
 char[] getTypeName();
+
+/**
+ * Answer the receiver's signature which describes the parameter &
+ * return types as specified in section 4.4.4 of the Java 2 VM spec.
+ */
+char[] getGenericSignature();
+/**
+ * Answer the tagbits set according to the bits for annotations.
+ */
+long getTagBits();
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java
index 75435bc..9f2ecd0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java
@@ -29,7 +29,7 @@
 
 /**
  * Answer the receiver's method descriptor which describes the parameter &
- * return types as specified in section 4.3.3 of the Java 2 VM spec.
+ * return types as specified in section 4.4.3 of the Java 2 VM spec.
  *
  * For example:
  *   - int foo(String) is (Ljava/lang/String;)I
@@ -38,6 +38,17 @@
 char[] getMethodDescriptor();
 
 /**
+ * Answer the receiver's signature which describes the parameter &
+ * return types as specified in section 4.4.4 of the Java 2 VM spec.
+ */
+char[] getGenericSignature();
+
+/**
+ * Answer the tagbits set according to the bits for annotations.
+ */
+long getTagBits();
+
+/**
  * Answer whether the receiver represents a class initializer method.
  */
 boolean isClinit();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
index aacda73..f693287 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
@@ -65,6 +65,16 @@
  */
 
 char[] getName();
+
+/**
+ * Answer the receiver's signature which describes the parameter &
+ * return types as specified in section 4.4.4 of the Java 2 VM spec 3rd edition.
+ * Returns null if none.
+ * 
+ * @return the receiver's signature, null if none
+ */
+char[] getGenericSignature();
+
 /**
  * Answer the resolved name of the receiver's superclass in the
  * class file format as specified in section 4.2 of the Java 2 VM spec
@@ -74,7 +84,10 @@
  */
 
 char[] getSuperclassName();
-
+/**
+ * Answer the tagbits set according to the bits for annotations.
+ */
+long getTagBits();
 /**
  * Answer true if the receiver is an anonymous class.
  * false otherwise
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IConstants.java
index 4f3bfa1..c6cb0ac 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IConstants.java
@@ -10,40 +10,44 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.env;
 
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+
 /**
- * This interface defines constants for use by the builder / compiler interface.
+ * This interface defines constants for use by the builder / compiler
+ * interface.
  */
 public interface IConstants {
-
 	int AccDefault = 0;
-
-	/**
+	/*
 	 * Modifiers
 	 */
-	int AccPublic = 0x0001;
-	int AccPrivate = 0x0002;
-	int AccProtected = 0x0004;
-	int AccStatic = 0x0008;
-	int AccFinal = 0x0010;
+	int AccPublic       = 0x0001;
+	int AccPrivate      = 0x0002;
+	int AccProtected    = 0x0004;
+	int AccStatic       = 0x0008;
+	int AccFinal        = 0x0010;
 	int AccSynchronized = 0x0020;
-	int AccVolatile = 0x0040;
-	int AccBridge = 0x0040;
-	int AccTransient = 0x0080;
-	int AccVarargs = 0x0080;
-	int AccNative = 0x0100;
-	int AccInterface = 0x0200;
-	int AccAbstract = 0x0400;
-	int AccStrictfp = 0x0800;
-	int AccSynthetic = 0x1000;
+	int AccVolatile     = 0x0040;
+	int AccBridge       = 0x0040;
+	int AccTransient    = 0x0080;
+	int AccVarargs      = 0x0080;
+	int AccNative       = 0x0100;
+	int AccInterface    = 0x0200;
+	int AccAbstract     = 0x0400;
+	int AccStrictfp     = 0x0800;
+	int AccSynthetic    = 0x1000;
+	int AccAnnotation   = 0x2000;
+	int AccEnum         = 0x4000;
 
 	/**
 	 * Other VM flags.
 	 */
 	int AccSuper = 0x0020;
-
 	/**
 	 * Extra flags for types and members attributes.
 	 */
-	int AccDeprecated = 0x100000;
+	int AccAnnotationDefault = ASTNode.Bit18; // indicate presence of an attribute  "DefaultValue" (annotation method)
+	int AccDeprecated = ASTNode.Bit21; // indicate presence of an attribute "Deprecated"
+	
 	
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IDependent.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IDependent.java
index bf645ec..91b5b4a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IDependent.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IDependent.java
@@ -18,15 +18,26 @@
  * when file dependencies are collected.
  */
 public interface IDependent {
+	char JAR_FILE_ENTRY_SEPARATOR = '|';
 /**
  * Answer the file name which defines the type.
  *
  * The path part (optional) must be separated from the actual
- * file proper name by a java.io.File.separator.
+ * file proper name by a separator suitable for the type (java.io.File.separator for example),
+ * e.g.
+ *  "c:\\source\\com\\p\\X.java" or
+ *  "/com/p/Y.java".
+ * 
+ * The path to the zip or jar file (optional) must be separated
+ * from the actual path part by JAR_FILE_ENTRY_SEPARATOR,
+ * e.g.
+ *  "c:\\lib\\some.jar|/com/p/X.class" or
+ *  "/lib/some.zip|/com/q/Y.class".
  *
  * The proper file name includes the suffix extension (e.g.&nbsp;".java")
- *
- * e.g.&nbsp;"c:/com/ibm/compiler/java/api/Compiler.java" 
+ * e.g.&nbsp;"c:/org/eclipse/jdt/internal/compileri/env/IDependent.java" 
+ * 
+ * Return null if no file defines the type.
  */
 
 char[] getFileName();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IGenericType.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IGenericType.java
index cca5c60..414d190 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IGenericType.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IGenericType.java
@@ -11,15 +11,24 @@
 package org.eclipse.jdt.internal.compiler.env;
 
 public interface IGenericType extends IDependent {
+
+	// Type decl kinds
+	int CLASS_DECL = 1;
+	int INTERFACE_DECL = 2;
+	int ENUM_DECL = 3;	
+	int ANNOTATION_TYPE_DECL = 4;
+	
+/**
+ * Returns the kind of this type CLASS, INTERFACE, ENUM, ANNOTATION_TYPE
+ */
+int getKind();
+
 /**
  * Answer an int whose bits are set according the access constants
  * defined by the VM spec.
+ * NOTE 1: We have added AccDeprecated & AccSynthetic.
+ * NOTE 2: If the receiver represents a member type, the modifiers are extracted from its inner class attributes.
  */
-
-// We have added AccDeprecated & AccSynthetic.
-
-// NOTE: If the receiver represents a member type, the modifiers are extracted from its inner class attributes.
-
 int getModifiers();
 /**
  * Answer whether the receiver contains the resolved binary form
@@ -27,6 +36,4 @@
  */
 
 boolean isBinaryType();
-boolean isClass();
-boolean isInterface();
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceMethod.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceMethod.java
index fc08366..8eba3ab 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceMethod.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceMethod.java
@@ -59,4 +59,14 @@
  */
 
 char[] getReturnTypeName();
+/**
+ * Answer the names of the receiver's type parameters
+ * or null if the array is empty.
+ */
+char[][] getTypeParameterNames();
+/**
+ * Answer the array of bound names of the receiver's type parameters
+ * or null if the array is empty.
+ */
+char[][][] getTypeParameterBounds();
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceType.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceType.java
index 594d718..3464fe8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceType.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceType.java
@@ -29,14 +29,14 @@
 ISourceType getEnclosingType();
 
 /**
- * Answer the receiver's fields or null if the array is empty.
+ * Answer the receiver's fields.
  *
  * NOTE: Multiple fields with the same name can exist in the result.
  */
 ISourceField[] getFields();
 
 /**
- * Answer the receiver's imports or null if the array is empty.
+ * Answer the receiver's imports.
  *
  * An import is a qualified, dot separated name.
  * For example, java.util.Hashtable or java.lang.*.
@@ -55,13 +55,12 @@
 char[][] getInterfaceNames();
 
 /**
- * Answer the receiver's member types
- * or null if the array is empty.
+ * Answer the receiver's member types.
  */
 ISourceType[] getMemberTypes();
 
 /**
- * Answer the receiver's methods or null if the array is empty.
+ * Answer the receiver's methods.
  *
  * NOTE: Multiple methods with the same name & parameter types can exist in the result.
  */
@@ -98,4 +97,12 @@
  * For example, Hashtable or java.util.Hashtable.
  */
 char[] getSuperclassName();
+/**
+ * Answer the array of bound names of the receiver's type parameters.
+ */
+char[][][] getTypeParameterBounds();
+/**
+ * Answer the names of the receiver's type parameters.
+ */
+char[][] getTypeParameterNames();
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
index b7ab4e6..1f015d5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
@@ -16,19 +16,28 @@
 	IBinaryType binaryType;
 	ICompilationUnit compilationUnit;
 	ISourceType[] sourceTypes;
+	AccessRestriction accessRestriction;
 	
-	public NameEnvironmentAnswer(IBinaryType binaryType) {
+	public NameEnvironmentAnswer(IBinaryType binaryType, AccessRestriction accessRestriction) {
 		this.binaryType = binaryType;
+		this.accessRestriction = accessRestriction;
 	}
 
-	public NameEnvironmentAnswer(ICompilationUnit compilationUnit) {
+	public NameEnvironmentAnswer(ICompilationUnit compilationUnit, AccessRestriction accessRestriction) {
 		this.compilationUnit = compilationUnit;
+		this.accessRestriction = accessRestriction;
 	}
 
-	public NameEnvironmentAnswer(ISourceType[] sourceTypes) {
+	public NameEnvironmentAnswer(ISourceType[] sourceTypes, AccessRestriction accessRestriction) {
 		this.sourceTypes = sourceTypes;
+		this.accessRestriction = accessRestriction;
 	}
-
+	/**
+	 * Returns the associated access restriction, or null if none.
+	 */
+	public AccessRestriction getAccessRestriction() {
+		return this.accessRestriction;
+	}
 	/**
 	 * Answer the resolved binary form for the type or null if the
 	 * receiver represents a compilation unit or source type.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java
index 115979e..d7dc642 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java
@@ -83,6 +83,42 @@
 				&& initsWhenFalse.isDefinitelyAssigned(local);
 	}
 	
+	/**
+	 * Check status of definite non-null assignment for a field.
+	 */
+	public boolean isDefinitelyNonNull(FieldBinding field) {
+		
+		return initsWhenTrue.isDefinitelyNonNull(field) 
+				&& initsWhenFalse.isDefinitelyNonNull(field);
+	}
+
+	/**
+	 * Check status of definite non-null assignment for a local variable.
+	 */
+	public boolean isDefinitelyNonNull(LocalVariableBinding local) {
+		
+		return initsWhenTrue.isDefinitelyNonNull(local) 
+				&& initsWhenFalse.isDefinitelyNonNull(local);
+	}
+	
+	/**
+	 * Check status of definite null assignment for a field.
+	 */
+	public boolean isDefinitelyNull(FieldBinding field) {
+		
+		return initsWhenTrue.isDefinitelyNull(field) 
+				&& initsWhenFalse.isDefinitelyNull(field);
+	}
+
+	/**
+	 * Check status of definite null assignment for a local variable.
+	 */
+	public boolean isDefinitelyNull(LocalVariableBinding local) {
+		
+		return initsWhenTrue.isDefinitelyNull(local) 
+				&& initsWhenFalse.isDefinitelyNull(local);
+	}
+
 	public int reachMode(){
 		return unconditionalInits().reachMode();
 	}
@@ -130,6 +166,42 @@
 	}
 	
 	/**
+	 * Record a field got definitely assigned to non-null value.
+	 */
+	public void markAsDefinitelyNonNull(FieldBinding field) {
+		
+		initsWhenTrue.markAsDefinitelyNonNull(field);
+		initsWhenFalse.markAsDefinitelyNonNull(field);	
+	}
+	
+	/**
+	 * Record a field got definitely assigned to non-null value
+	 */
+	public void markAsDefinitelyNonNull(LocalVariableBinding local) {
+		
+		initsWhenTrue.markAsDefinitelyNonNull(local);
+		initsWhenFalse.markAsDefinitelyNonNull(local);	
+	}
+
+	/**
+	 * Record a field got definitely assigned to null.
+	 */
+	public void markAsDefinitelyNull(FieldBinding field) {
+		
+		initsWhenTrue.markAsDefinitelyNull(field);
+		initsWhenFalse.markAsDefinitelyNull(field);	
+	}
+	
+	/**
+	 * Record a field got definitely assigned to null.
+	 */
+	public void markAsDefinitelyNull(LocalVariableBinding local) {
+		
+		initsWhenTrue.markAsDefinitelyNull(local);
+		initsWhenFalse.markAsDefinitelyNull(local);	
+	}
+
+	/**
 	 * Clear the initialization info for a field
 	 */
 	public void markAsDefinitelyNotAssigned(FieldBinding field) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
index d17ab89..0069d50 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.compiler.flow;
 
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
 import org.eclipse.jdt.internal.compiler.ast.Reference;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
@@ -23,9 +24,13 @@
  */
 public class FinallyFlowContext extends FlowContext {
 	
-	Reference finalAssignments[];
-	VariableBinding finalVariables[];
+	Reference[] finalAssignments;
+	VariableBinding[] finalVariables;
 	int assignCount;
+
+	Expression[] nullReferences;
+	int[] nullStatus;
+	int nullCount;
 	
 	public FinallyFlowContext(FlowContext parent, ASTNode associatedNode) {
 		super(parent, associatedNode);
@@ -36,9 +41,9 @@
 	 * code will check that the subroutine context does not also initialize a final variable potentially set
 	 * redundantly.
 	 */
-	public void complainOnRedundantFinalAssignments(
-		FlowInfo flowInfo,
-		BlockScope scope) {
+	public void complainOnDeferredChecks(FlowInfo flowInfo, BlockScope scope) {
+		
+		// check redundant final assignments
 		for (int i = 0; i < assignCount; i++) {
 			VariableBinding variable = finalVariables[i];
 			if (variable == null) continue;
@@ -71,20 +76,43 @@
 				}
 			}
 		}
+		
+		// check inconsistent null checks
+		for (int i = 0; i < nullCount; i++) {
+			Expression expression = nullReferences[i];
+			if (expression == null) continue;
+			// final local variable
+			LocalVariableBinding local = expression.localVariableBinding();
+			switch (nullStatus[i]) {
+				case FlowInfo.NULL :
+					if (flowInfo.isDefinitelyNull(local)) {
+						nullReferences[i] = null;
+						this.parent.recordUsingNullReference(scope, local, expression, nullStatus[i], flowInfo);
+					}
+					break;
+				case FlowInfo.NON_NULL :
+					if (flowInfo.isDefinitelyNonNull(local)) {
+						nullReferences[i] = null;
+						this.parent.recordUsingNullReference(scope, local, expression, nullStatus[i], flowInfo);
+					}
+					break;
+			}
+		}
 	}
-
+	
 	public String individualToString() {
 		
 		StringBuffer buffer = new StringBuffer("Finally flow context"); //$NON-NLS-1$
-		buffer.append("[finalAssignments count -").append(assignCount).append(']'); //$NON-NLS-1$
+		buffer.append("[finalAssignments count - ").append(assignCount).append(']'); //$NON-NLS-1$
+		buffer.append("[nullReferences count - ").append(nullCount).append(']'); //$NON-NLS-1$
 		return buffer.toString();
 	}
 	
 	public boolean isSubRoutine() {
 		return true;
 	}
-
-	boolean recordFinalAssignment(
+	
+	protected boolean recordFinalAssignment(
 		VariableBinding binding,
 		Reference finalAssignment) {
 		if (assignCount == 0) {
@@ -119,4 +147,19 @@
 			}
 		}
 	}
+
+	protected boolean recordNullReference(Expression expression, int status) {
+		if (nullCount == 0) {
+			nullReferences = new Expression[5];
+			nullStatus = new int[5];
+		} else {
+			if (nullCount == nullReferences.length) {
+				System.arraycopy(nullReferences, 0, nullReferences = new Expression[nullCount * 2], 0, nullCount);
+				System.arraycopy(nullStatus, 0, nullStatus = new int[nullCount * 2], 0, nullCount);
+			}
+		}
+		nullReferences[nullCount] = expression;
+		nullStatus[nullCount++] = status;
+		return true;
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
index 340781f..46b46a5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
@@ -13,11 +13,13 @@
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
 import org.eclipse.jdt.internal.compiler.ast.Reference;
 import org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement;
 import org.eclipse.jdt.internal.compiler.ast.TryStatement;
 import org.eclipse.jdt.internal.compiler.codegen.Label;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.Scope;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
@@ -167,7 +169,8 @@
 				
 			traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
 			if (traversedContext.associatedNode instanceof TryStatement){
-				flowInfo = flowInfo.copy().addInitializationsFrom(((TryStatement) traversedContext.associatedNode).subRoutineInits);
+				TryStatement tryStatement = (TryStatement) traversedContext.associatedNode;
+				flowInfo = flowInfo.copy().addInitializationsFrom(tryStatement.subRoutineInits);
 			}
 			traversedContext = traversedContext.parent;
 		}
@@ -265,7 +268,8 @@
 
 			traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
 			if (traversedContext.associatedNode instanceof TryStatement){
-				flowInfo = flowInfo.copy().addInitializationsFrom(((TryStatement) traversedContext.associatedNode).subRoutineInits);
+				TryStatement tryStatement = (TryStatement) traversedContext.associatedNode;
+				flowInfo = flowInfo.copy().addInitializationsFrom(tryStatement.subRoutineInits);
 			}
 			traversedContext = traversedContext.parent;
 		}
@@ -427,13 +431,18 @@
 		// default implementation: do nothing
 	}
 
-	boolean recordFinalAssignment(
+	protected boolean recordFinalAssignment(
 		VariableBinding variable,
 		Reference finalReference) {
 
 		return true; // keep going
 	}
 
+	protected boolean recordNullReference(Expression expression, int status) {
+
+		return false; // keep going
+	}
+	
 	public void recordReturnFrom(FlowInfo flowInfo) {
 		// default implementation: do nothing
 	}
@@ -455,6 +464,38 @@
 		}
 	}
 
+	public void recordUsingNullReference(Scope scope, LocalVariableBinding local, Expression reference, int status, FlowInfo flowInfo) {
+
+		if (!flowInfo.isReachable()) return;
+
+		switch (status) {
+			case FlowInfo.NULL :
+				if (flowInfo.isDefinitelyNull(local)) {
+					scope.problemReporter().localVariableCanOnlyBeNull(local, reference);
+					return;
+				} else if (flowInfo.isDefinitelyNonNull(local)) {
+					scope.problemReporter().localVariableCannotBeNull(local, reference);				
+					return;
+				}
+				break;
+			case FlowInfo.NON_NULL :
+				if (flowInfo.isDefinitelyNull(local)) {
+					scope.problemReporter().localVariableCanOnlyBeNull(local, reference);				
+					return;
+				}
+				break;
+		}
+		
+		// for initialization inside looping statement that effectively loops
+		FlowContext context = this;
+		while (context != null) {
+			if (context.recordNullReference(reference, status)) {
+				return; // no need to keep going
+			}
+			context = context.parent;
+		}
+	}
+	
 	void removeFinalAssignmentIfAny(Reference reference) {
 		// default implementation: do nothing
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
index 1736a5c..3219a62 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
@@ -16,7 +16,11 @@
 public abstract class FlowInfo {
 
 	public final static int REACHABLE = 0;
-	public final static int UNREACHABLE = 1; 
+	public final static int UNREACHABLE = 1;
+	
+	public final static int UNKNOWN = 0;
+	public final static int NULL = 1;
+	public final static int NON_NULL = -1;
 	
 	public static final UnconditionalFlowInfo DEAD_END; // Represents a dead branch status of initialization
 	static {
@@ -60,7 +64,25 @@
 	 */
 	public abstract boolean isDefinitelyAssigned(LocalVariableBinding local);
 
-	//abstract public int reachMode(); 
+	/**
+	 * Check status of definite null assignment for a field.
+	 */
+	 abstract public boolean isDefinitelyNonNull(FieldBinding field);   
+
+	/**
+	 * Check status of definite null assignment for a local.
+	 */
+	public abstract boolean isDefinitelyNonNull(LocalVariableBinding local);
+
+	/**
+	 * Check status of definite null assignment for a field.
+	 */
+	 abstract public boolean isDefinitelyNull(FieldBinding field);   
+
+	/**
+	 * Check status of definite null assignment for a local.
+	 */
+	public abstract boolean isDefinitelyNull(LocalVariableBinding local);
 
 	/**
 	 * Check status of potential assignment for a field.
@@ -81,6 +103,26 @@
 	abstract public void markAsDefinitelyAssigned(FieldBinding field);
 
 	/**
+	 * Record a local got definitely assigned to a non-null value.
+	 */
+	abstract public void markAsDefinitelyNonNull(LocalVariableBinding local);
+
+	/**
+	 * Record a field got definitely assigned to a non-null value.
+	 */
+	abstract public void markAsDefinitelyNonNull(FieldBinding field);
+
+	/**
+	 * Record a local got definitely assigned to null.
+	 */
+	abstract public void markAsDefinitelyNull(LocalVariableBinding local);
+
+	/**
+	 * Record a field got definitely assigned.
+	 */
+	abstract public void markAsDefinitelyNull(FieldBinding field);
+
+	/**
 	 * Record a local got definitely assigned.
 	 */
 	abstract public void markAsDefinitelyAssigned(LocalVariableBinding local);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
index 450bdff..9f1ed05 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.compiler.flow;
 
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
 import org.eclipse.jdt.internal.compiler.ast.Reference;
 import org.eclipse.jdt.internal.compiler.codegen.Label;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
@@ -30,6 +31,11 @@
 	Reference finalAssignments[];
 	VariableBinding finalVariables[];
 	int assignCount = 0;
+	
+	Expression[] nullReferences;
+	int[] nullStatus;
+	int nullCount;
+	
 	Scope associatedScope;
 	
 	public LoopingFlowContext(
@@ -43,9 +49,9 @@
 		this.associatedScope = associatedScope;
 	}
 	
-	public void complainOnFinalAssignmentsInLoop(
-		BlockScope scope,
-		FlowInfo flowInfo) {
+	public void complainOnDeferredChecks(BlockScope scope, FlowInfo flowInfo) {
+		
+		// complain on final assignments in loops
 		for (int i = 0; i < assignCount; i++) {
 			VariableBinding variable = finalVariables[i];
 			if (variable == null) continue;
@@ -75,6 +81,27 @@
 				}
 			}
 		}
+		// check inconsistent null checks
+		for (int i = 0; i < nullCount; i++) {
+			Expression expression = nullReferences[i];
+			if (expression == null) continue;
+			// final local variable
+			LocalVariableBinding local = expression.localVariableBinding();
+			switch (nullStatus[i]) {
+				case FlowInfo.NULL :
+					if (flowInfo.isDefinitelyNull(local)) {
+						nullReferences[i] = null;
+						this.parent.recordUsingNullReference(scope, local, expression, nullStatus[i], flowInfo);
+					}
+					break;
+				case FlowInfo.NON_NULL :
+					if (flowInfo.isDefinitelyNonNull(local)) {
+						nullReferences[i] = null;
+						this.parent.recordUsingNullReference(scope, local, expression, nullStatus[i], flowInfo);
+					}
+					break;
+			}
+		}		
 	}
 
 	public Label continueLabel() {
@@ -83,8 +110,10 @@
 
 	public String individualToString() {
 		StringBuffer buffer = new StringBuffer("Looping flow context"); //$NON-NLS-1$
-		buffer.append("[initsOnBreak -").append(initsOnBreak.toString()).append(']'); //$NON-NLS-1$
-		buffer.append("[initsOnContinue -").append(initsOnContinue.toString()).append(']'); //$NON-NLS-1$
+		buffer.append("[initsOnBreak - ").append(initsOnBreak.toString()).append(']'); //$NON-NLS-1$
+		buffer.append("[initsOnContinue - ").append(initsOnContinue.toString()).append(']'); //$NON-NLS-1$
+		buffer.append("[finalAssignments count - ").append(assignCount).append(']'); //$NON-NLS-1$
+		buffer.append("[nullReferences count - ").append(nullCount).append(']'); //$NON-NLS-1$
 		return buffer.toString();
 	}
 
@@ -106,7 +135,7 @@
 		}
 	}
 
-	boolean recordFinalAssignment(
+	protected boolean recordFinalAssignment(
 		VariableBinding binding,
 		Reference finalAssignment) {
 
@@ -141,6 +170,21 @@
 		return true;
 	}
 
+	protected boolean recordNullReference(Expression expression, int status) {
+		if (nullCount == 0) {
+			nullReferences = new Expression[5];
+			nullStatus = new int[5];
+		} else {
+			if (nullCount == nullReferences.length) {
+				System.arraycopy(nullReferences, 0, nullReferences = new Expression[nullCount * 2], 0, nullCount);
+				System.arraycopy(nullStatus, 0, nullStatus = new int[nullCount * 2], 0, nullCount);
+			}
+		}
+		nullReferences[nullCount] = expression;
+		nullStatus[nullCount++] = status;
+		return true;
+	}	
+	
 	void removeFinalAssignmentIfAny(Reference reference) {
 		for (int i = 0; i < assignCount; i++) {
 			if (finalAssignments[i] == reference) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
index 4ae4c52..88cd296 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
@@ -10,7 +10,6 @@
  *******************************************************************************/
 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;
@@ -28,6 +27,11 @@
 	public long extraDefiniteInits[];
 	public long extraPotentialInits[];
 	
+	public long definiteNulls;
+	public long definiteNonNulls;
+	public long extraDefiniteNulls[];
+	public long extraDefiniteNonNulls[];
+
 	public int reachMode; // by default
 
 	public int maxFieldCount;
@@ -54,6 +58,12 @@
 		// union of potentially set ones
 		potentialInits |= otherInits.potentialInits;
 	
+		// union of definitely null variables, 
+		definiteNulls = (definiteNulls | otherInits.definiteNulls) & ~otherInits.definiteNonNulls;
+		// union of definitely non null variables,
+		definiteNonNulls = (definiteNonNulls | otherInits.definiteNonNulls) & ~otherInits.definiteNulls;
+		// fix-up null/non-null infos since cannot overlap: <defN1:0,defNoN1:1>  + <defN2:1,defNoN2:0>  --> <defN:0,defNon:0>
+
 		// treating extra storage
 		if (extraDefiniteInits != null) {
 			if (otherInits.extraDefiniteInits != null) {
@@ -63,21 +73,28 @@
 					// current storage is shorter -> grow current (could maybe reuse otherInits extra storage?)
 					System.arraycopy(extraDefiniteInits, 0, (extraDefiniteInits = new long[otherLength]), 0, length);
 					System.arraycopy(extraPotentialInits, 0, (extraPotentialInits = new long[otherLength]), 0, length);
-					while (i < length) {
+					for (; i < length; i++) {
 						extraDefiniteInits[i] |= otherInits.extraDefiniteInits[i];
-						extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+						extraPotentialInits[i] |= otherInits.extraPotentialInits[i];
+						extraDefiniteNulls[i] = (extraDefiniteNulls[i] | otherInits.extraDefiniteNulls[i]) & ~otherInits.extraDefiniteNonNulls[i];
+						extraDefiniteNonNulls[i] = (extraDefiniteNonNulls[i] | otherInits.extraDefiniteNonNulls[i]) & ~otherInits.extraDefiniteNulls[i];
 					}
-					while (i < otherLength) {
-						extraPotentialInits[i] = otherInits.extraPotentialInits[i++];
+					for (; i < otherLength; i++) {
+						extraPotentialInits[i] = otherInits.extraPotentialInits[i];
 					}
 				} else {
 					// current storage is longer
-					while (i < otherLength) {
+					for (; i < otherLength; i++) {
 						extraDefiniteInits[i] |= otherInits.extraDefiniteInits[i];
-						extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+						extraPotentialInits[i] |= otherInits.extraPotentialInits[i];
+						extraDefiniteNulls[i] = (extraDefiniteNulls[i] | otherInits.extraDefiniteNulls[i]) & ~otherInits.extraDefiniteNonNulls[i];
+						extraDefiniteNonNulls[i] = (extraDefiniteNonNulls[i] | otherInits.extraDefiniteNonNulls[i]) & ~otherInits.extraDefiniteNulls[i];
 					}
-					while (i < length)
-						extraDefiniteInits[i++] = 0;
+					for (; i < length; i++) {
+						extraDefiniteInits[i] = 0;
+						extraDefiniteNulls[i] = 0;
+						extraDefiniteNonNulls[i] = 0;
+					}
 				}
 			} else {
 				// no extra storage on otherInits
@@ -88,6 +105,8 @@
 				int otherLength;
 				System.arraycopy(otherInits.extraDefiniteInits, 0, (extraDefiniteInits = new long[otherLength = otherInits.extraDefiniteInits.length]), 0, otherLength);			
 				System.arraycopy(otherInits.extraPotentialInits, 0, (extraPotentialInits = new long[otherLength]), 0, otherLength);
+				System.arraycopy(otherInits.extraDefiniteNulls, 0, (extraDefiniteNulls = new long[otherLength]), 0, otherLength);			
+				System.arraycopy(otherInits.extraDefiniteNonNulls, 0, (extraDefiniteNonNulls = new long[otherLength]), 0, otherLength);			
 			}
 		return this;
 	}
@@ -104,27 +123,38 @@
 			return this;
 		}
 		// union of potentially set ones
-		potentialInits |= otherInits.potentialInits;
+		this.potentialInits |= otherInits.potentialInits;
+		// also merge null check information (affected by potential inits)
+		this.definiteNulls &= otherInits.definiteNulls;
+		this.definiteNonNulls &= otherInits.definiteNonNulls;
 	
 		// treating extra storage
-		if (extraDefiniteInits != null) {
+		if (this.extraDefiniteInits != null) {
 			if (otherInits.extraDefiniteInits != null) {
 				// both sides have extra storage
 				int i = 0, length, otherLength;
-				if ((length = extraDefiniteInits.length) < (otherLength = otherInits.extraDefiniteInits.length)) {
+				if ((length = this.extraDefiniteInits.length) < (otherLength = otherInits.extraDefiniteInits.length)) {
 					// current storage is shorter -> grow current (could maybe reuse otherInits extra storage?)
-					System.arraycopy(extraDefiniteInits, 0, (extraDefiniteInits = new long[otherLength]), 0, length);
-					System.arraycopy(extraPotentialInits, 0, (extraPotentialInits = new long[otherLength]), 0, length);
+					System.arraycopy(this.extraDefiniteInits, 0, (this.extraDefiniteInits = new long[otherLength]), 0, length);
+					System.arraycopy(this.extraPotentialInits, 0, (this.extraPotentialInits = new long[otherLength]), 0, length);
+					System.arraycopy(this.extraDefiniteNulls, 0, (this.extraDefiniteNulls = new long[otherLength]), 0, length);
+					System.arraycopy(this.extraDefiniteNonNulls, 0, (this.extraDefiniteNonNulls = new long[otherLength]), 0, length);
 					while (i < length) {
-						extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+						this.extraPotentialInits[i] |= otherInits.extraPotentialInits[i];
+						this.extraDefiniteNulls[i] &= otherInits.extraDefiniteNulls[i];
+						this.extraDefiniteNonNulls[i] &= otherInits.extraDefiniteNonNulls[i++];
 					}
 					while (i < otherLength) {
-						extraPotentialInits[i] = otherInits.extraPotentialInits[i++];
+						this.extraPotentialInits[i] = otherInits.extraPotentialInits[i];
+						this.extraDefiniteNulls[i] &= otherInits.extraDefiniteNulls[i];
+						this.extraDefiniteNonNulls[i] &= otherInits.extraDefiniteNonNulls[i++];
 					}
 				} else {
 					// current storage is longer
 					while (i < otherLength) {
-						extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+						this.extraPotentialInits[i] |= otherInits.extraPotentialInits[i];
+						this.extraDefiniteNulls[i] &= otherInits.extraDefiniteNulls[i];
+						this.extraDefiniteNonNulls[i] &= otherInits.extraDefiniteNonNulls[i++];
 					}
 				}
 			}
@@ -132,8 +162,10 @@
 			if (otherInits.extraDefiniteInits != null) {
 				// no storage here, but other has extra storage.
 				int otherLength;
-				extraDefiniteInits = new long[otherLength = otherInits.extraDefiniteInits.length];			
-				System.arraycopy(otherInits.extraPotentialInits, 0, (extraPotentialInits = new long[otherLength]), 0, otherLength);
+				this.extraDefiniteInits = new long[otherLength = otherInits.extraDefiniteInits.length];			
+				System.arraycopy(otherInits.extraPotentialInits, 0, (this.extraPotentialInits = new long[otherLength]), 0, otherLength);
+				this.extraDefiniteNulls = new long[otherLength];			
+				this.extraDefiniteNonNulls = new long[otherLength];			
 			}
 		return this;
 	}
@@ -153,13 +185,17 @@
 		// copy slots
 		copy.definiteInits = this.definiteInits;
 		copy.potentialInits = this.potentialInits;
+		copy.definiteNulls = this.definiteNulls;
+		copy.definiteNonNulls = this.definiteNonNulls;
 		copy.reachMode = this.reachMode;
 		copy.maxFieldCount = this.maxFieldCount;
 		
 		if (this.extraDefiniteInits != null) {
 			int length;
-			System.arraycopy(this.extraDefiniteInits, 0, (copy.extraDefiniteInits = new long[ (length = extraDefiniteInits.length)]), 0, length);
+			System.arraycopy(this.extraDefiniteInits, 0, (copy.extraDefiniteInits = new long[length = extraDefiniteInits.length]), 0, length);
 			System.arraycopy(this.extraPotentialInits, 0, (copy.extraPotentialInits = new long[length]), 0, length);
+			System.arraycopy(this.extraDefiniteNulls, 0, (copy.extraDefiniteNulls = new long[length]), 0, length);
+			System.arraycopy(this.extraDefiniteNonNulls, 0, (copy.extraDefiniteNonNulls = new long[length]), 0, length);
 		}
 		return copy;
 	}
@@ -172,12 +208,16 @@
 			long mask = (1L << limit)-1;
 			this.definiteInits &= ~mask;
 			this.potentialInits &= ~mask;
+			this.definiteNulls &= ~mask;
+			this.definiteNonNulls &= ~mask;
 			return this;
 		} 
 
 		this.definiteInits = 0;
 		this.potentialInits = 0;
-
+		this.definiteNulls = 0;
+		this.definiteNonNulls = 0;
+		
 		// use extra vector
 		if (extraDefiniteInits == null) {
 			return this; // if vector not yet allocated, then not initialized
@@ -189,10 +229,14 @@
 		for (int i = 0; i < vectorIndex; i++) {
 			this.extraDefiniteInits[i] = 0L;
 			this.extraPotentialInits[i] = 0L;
+			this.extraDefiniteNulls[i] = 0L;
+			this.extraDefiniteNonNulls[i] = 0L;
 		}
 		long mask = (1L << (limit % BitCacheSize))-1;
 		this.extraDefiniteInits[vectorIndex] &= ~mask;
 		this.extraPotentialInits[vectorIndex] &= ~mask;
+		this.extraDefiniteNulls[vectorIndex] &= ~mask;
+		this.extraDefiniteNonNulls[vectorIndex] &= ~mask;
 		return this;
 	}
 
@@ -204,6 +248,8 @@
 			long mask = (1L << limit)-1;
 			this.definiteInits &= mask;
 			this.potentialInits &= mask;
+			this.definiteNulls &= mask;
+			this.definiteNonNulls &= mask;
 			return this;
 		} 
 		// use extra vector
@@ -217,13 +263,30 @@
 		long mask = (1L << (limit % BitCacheSize))-1;
 		this.extraDefiniteInits[vectorIndex] &= mask;
 		this.extraPotentialInits[vectorIndex] &= mask;
+		this.extraDefiniteNulls[vectorIndex] &= mask;
+		this.extraDefiniteNonNulls[vectorIndex] &= mask;
 		for (int i = vectorIndex+1; i < length; i++) {
 			this.extraDefiniteInits[i] = 0L;
 			this.extraPotentialInits[i] = 0L;
+			this.extraDefiniteNulls[i] = 0L;
+			this.extraDefiniteNonNulls[i] = 0L;
 		}
 		return this;
 	}
 	
+	public UnconditionalFlowInfo discardNullRelatedInitializations(){
+		
+		this.definiteNulls = 0;
+		this.definiteNonNulls = 0;
+		
+		int length = this.extraDefiniteInits == null ? 0 : this.extraDefiniteInits.length;
+		for (int i = 0; i < length; i++) {
+			this.extraDefiniteNulls[i] = 0L;
+			this.extraDefiniteNonNulls[i] = 0L;
+		}
+		return this;
+	}
+
 	public FlowInfo initsWhenFalse() {
 		
 		return this;
@@ -256,6 +319,48 @@
 	}
 	
 	/**
+	 * Check status of definite non-null assignment at a given position.
+	 * It deals with the dual representation of the InitializationInfo2:
+	 * bits for the first 64 entries, then an array of booleans.
+	 */
+	final private boolean isDefinitelyNonNull(int position) {
+		
+		// Dependant of CodeStream.isDefinitelyAssigned(..)
+		// id is zero-based
+		if (position < BitCacheSize) {
+			return (definiteNonNulls & (1L << position)) != 0; // use bits
+		}
+		// use extra vector
+		if (extraDefiniteNonNulls == null)
+			return false; // if vector not yet allocated, then not initialized
+		int vectorIndex;
+		if ((vectorIndex = (position / BitCacheSize) - 1) >= extraDefiniteNonNulls.length)
+			return false; // if not enough room in vector, then not initialized 
+		return ((extraDefiniteNonNulls[vectorIndex]) & (1L << (position % BitCacheSize))) != 0;
+	}
+
+	/**
+	 * Check status of definite null assignment at a given position.
+	 * It deals with the dual representation of the InitializationInfo2:
+	 * bits for the first 64 entries, then an array of booleans.
+	 */
+	final private boolean isDefinitelyNull(int position) {
+		
+		// Dependant of CodeStream.isDefinitelyAssigned(..)
+		// id is zero-based
+		if (position < BitCacheSize) {
+			return (definiteNulls & (1L << position)) != 0; // use bits
+		}
+		// use extra vector
+		if (extraDefiniteNulls == null)
+			return false; // if vector not yet allocated, then not initialized
+		int vectorIndex;
+		if ((vectorIndex = (position / BitCacheSize) - 1) >= extraDefiniteNulls.length)
+			return false; // if not enough room in vector, then not initialized 
+		return ((extraDefiniteNulls[vectorIndex]) & (1L << (position % BitCacheSize))) != 0;
+	}
+
+	/**
 	 * Check status of definite assignment for a field.
 	 */
 	final public boolean isDefinitelyAssigned(FieldBinding field) {
@@ -276,16 +381,66 @@
 		// We do not want to complain in unreachable code
 		if ((this.reachMode & UNREACHABLE) != 0)
 			return true;
-		if (local.isArgument) {
-			return true;
-		}
+
 		// final constants are inlined, and thus considered as always initialized
-		if (local.constant != Constant.NotAConstant) {
+		if (local.isConstantValue()) {
 			return true;
 		}
 		return isDefinitelyAssigned(local.id + maxFieldCount);
 	}
 	
+	/**
+	 * Check status of definite non-null assignment for a field.
+	 */
+	final public boolean isDefinitelyNonNull(FieldBinding field) {
+		
+		// Dependant of CodeStream.isDefinitelyAssigned(..)
+		// We do not want to complain in unreachable code
+		if ((this.reachMode & UNREACHABLE) != 0)  
+			return false;
+		return isDefinitelyNonNull(field.id); 
+	}
+	
+	/**
+	 * Check status of definite non-null assignment for a local.
+	 */
+	final public boolean isDefinitelyNonNull(LocalVariableBinding local) {
+		
+		// Dependant of CodeStream.isDefinitelyAssigned(..)
+		// We do not want to complain in unreachable code
+		if ((this.reachMode & UNREACHABLE) != 0)
+			return false;
+		// final constants are inlined, and thus considered as always initialized
+		if (local.isConstantValue()) {
+			return true;
+		}
+		return isDefinitelyNonNull(local.id + maxFieldCount);
+	}
+
+	/**
+	 * Check status of definite null assignment for a field.
+	 */
+	final public boolean isDefinitelyNull(FieldBinding field) {
+		
+		// Dependant of CodeStream.isDefinitelyAssigned(..)
+		// We do not want to complain in unreachable code
+		if ((this.reachMode & UNREACHABLE) != 0)  
+			return false;
+		return isDefinitelyNull(field.id); 
+	}
+	
+	/**
+	 * Check status of definite null assignment for a local.
+	 */
+	final public boolean isDefinitelyNull(LocalVariableBinding local) {
+		
+		// Dependant of CodeStream.isDefinitelyAssigned(..)
+		// We do not want to complain in unreachable code
+		if ((this.reachMode & UNREACHABLE) != 0)
+			return false;
+		return isDefinitelyNull(local.id + maxFieldCount);
+	}
+
 	public boolean isReachable() {
 		
 		return this.reachMode == REACHABLE;
@@ -325,11 +480,8 @@
 	 */
 	final public boolean isPotentiallyAssigned(LocalVariableBinding local) {
 		
-		if (local.isArgument) {
-			return true;
-		}
 		// final constants are inlined, and thus considered as always initialized
-		if (local.constant != Constant.NotAConstant) {
+		if (local.isConstantValue()) {
 			return true;
 		}
 		return isPotentiallyAssigned(local.id + maxFieldCount);
@@ -350,6 +502,8 @@
 				long mask;
 				definiteInits |= (mask = 1L << position);
 				potentialInits |= mask;
+				definiteNulls &= ~mask;
+				definiteNonNulls &= ~mask;
 			} else {
 				// use extra vector
 				int vectorIndex = (position / BitCacheSize) - 1;
@@ -357,16 +511,22 @@
 					int length;
 					extraDefiniteInits = new long[length = vectorIndex + 1];
 					extraPotentialInits = new long[length];
+					extraDefiniteNulls = new long[length];
+					extraDefiniteNonNulls = new long[length];
 				} else {
 					int oldLength; // might need to grow the arrays
 					if (vectorIndex >= (oldLength = extraDefiniteInits.length)) {
 						System.arraycopy(extraDefiniteInits, 0, (extraDefiniteInits = new long[vectorIndex + 1]), 0, oldLength);
 						System.arraycopy(extraPotentialInits, 0, (extraPotentialInits = new long[vectorIndex + 1]), 0, oldLength);
+						System.arraycopy(extraDefiniteNulls, 0, (extraDefiniteNulls = new long[vectorIndex + 1]), 0, oldLength);
+						System.arraycopy(extraDefiniteNonNulls, 0, (extraDefiniteNonNulls = new long[vectorIndex + 1]), 0, oldLength);
 					}
 				}
 				long mask;
 				extraDefiniteInits[vectorIndex] |= (mask = 1L << (position % BitCacheSize));
 				extraPotentialInits[vectorIndex] |= mask;
+				extraDefiniteNulls[vectorIndex] &= ~mask;
+				extraDefiniteNonNulls[vectorIndex] &= ~mask;
 			}
 		}
 	}
@@ -386,6 +546,88 @@
 		if (this != DEAD_END)
 			markAsDefinitelyAssigned(local.id + maxFieldCount);
 	}
+
+	/**
+	 * Record a definite non-null assignment at a given position.
+	 * It deals with the dual representation of the InitializationInfo2:
+	 * bits for the first 64 entries, then an array of booleans.
+	 */
+	final private void markAsDefinitelyNonNull(int position) {
+		
+		if (this != DEAD_END) {
+	
+			// position is zero-based
+			if (position < BitCacheSize) {
+				// use bits
+				long mask;
+				definiteNonNulls |= (mask = 1L << position);
+				definiteNulls &= ~mask;
+			} else {
+				// use extra vector
+				int vectorIndex = (position / BitCacheSize) - 1;
+				long mask;
+				extraDefiniteNonNulls[vectorIndex] |= (mask = 1L << (position % BitCacheSize));
+				extraDefiniteNulls[vectorIndex] &= ~mask;
+			}
+		}
+	}
+
+	/**
+	 * Record a field got definitely assigned to non-null value.
+	 */
+	public void markAsDefinitelyNonNull(FieldBinding field) {
+		if (this != DEAD_END)
+			markAsDefinitelyNonNull(field.id);
+	}
+	
+	/**
+	 * Record a local got definitely assigned to non-null value.
+	 */
+	public void markAsDefinitelyNonNull(LocalVariableBinding local) {
+		if (this != DEAD_END)
+			markAsDefinitelyNonNull(local.id + maxFieldCount);
+	}
+
+	/**
+	 * Record a definite null assignment at a given position.
+	 * It deals with the dual representation of the InitializationInfo2:
+	 * bits for the first 64 entries, then an array of booleans.
+	 */
+	final private void markAsDefinitelyNull(int position) {
+		
+		if (this != DEAD_END) {
+	
+			// position is zero-based
+			if (position < BitCacheSize) {
+				// use bits
+				long mask;
+				definiteNulls |= (mask = 1L << position);
+				definiteNonNulls &= ~mask;
+			} else {
+				// use extra vector
+				int vectorIndex = (position / BitCacheSize) - 1;
+				long mask;
+				extraDefiniteNulls[vectorIndex] |= (mask = 1L << (position % BitCacheSize));
+				extraDefiniteNonNulls[vectorIndex] &= ~mask;
+			}
+		}
+	}
+
+	/**
+	 * Record a field got definitely assigned to null.
+	 */
+	public void markAsDefinitelyNull(FieldBinding field) {
+		if (this != DEAD_END)
+			markAsDefinitelyAssigned(field.id);
+	}
+	
+	/**
+	 * Record a local got definitely assigned to null.
+	 */
+	public void markAsDefinitelyNull(LocalVariableBinding local) {
+		if (this != DEAD_END)
+			markAsDefinitelyNull(local.id + maxFieldCount);
+	}
 	
 	/**
 	 * Clear initialization information at a given position.
@@ -401,6 +643,8 @@
 				long mask;
 				definiteInits &= ~(mask = 1L << position);
 				potentialInits &= ~mask;
+				definiteNulls &= ~mask;
+				definiteNonNulls &= ~mask;
 			} else {
 				// use extra vector
 				int vectorIndex = (position / BitCacheSize) - 1;
@@ -414,6 +658,8 @@
 				long mask;
 				extraDefiniteInits[vectorIndex] &= ~(mask = 1L << (position % BitCacheSize));
 				extraPotentialInits[vectorIndex] &= ~mask;
+				extraDefiniteNulls[vectorIndex] &= ~mask;
+				extraDefiniteNonNulls[vectorIndex] &= ~mask;
 			}
 		}
 	}
@@ -462,6 +708,10 @@
 		this.definiteInits &= otherInits.definiteInits;
 		// union of potentially set ones
 		this.potentialInits |= otherInits.potentialInits;
+		// intersection of definitely null variables, 
+		this.definiteNulls &= otherInits.definiteNulls;
+		// intersection of definitely non-null variables, 
+		this.definiteNonNulls &= otherInits.definiteNonNulls;
 	
 		// treating extra storage
 		if (this.extraDefiniteInits != null) {
@@ -472,9 +722,13 @@
 					// current storage is shorter -> grow current (could maybe reuse otherInits extra storage?)
 					System.arraycopy(this.extraDefiniteInits, 0, (this.extraDefiniteInits = new long[otherLength]), 0, length);
 					System.arraycopy(this.extraPotentialInits, 0, (this.extraPotentialInits = new long[otherLength]), 0, length);
+					System.arraycopy(this.extraDefiniteNulls, 0, (this.extraDefiniteNulls = new long[otherLength]), 0, length);
+					System.arraycopy(this.extraDefiniteNonNulls, 0, (this.extraDefiniteNonNulls = new long[otherLength]), 0, length);
 					while (i < length) {
 						this.extraDefiniteInits[i] &= otherInits.extraDefiniteInits[i];
-						this.extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+						this.extraPotentialInits[i] |= otherInits.extraPotentialInits[i];
+						this.extraDefiniteNulls[i] &= otherInits.extraDefiniteNulls[i];
+						this.extraDefiniteNonNulls[i] &= otherInits.extraDefiniteNonNulls[i++];
 					}
 					while (i < otherLength) {
 						this.extraPotentialInits[i] = otherInits.extraPotentialInits[i++];
@@ -483,16 +737,24 @@
 					// current storage is longer
 					while (i < otherLength) {
 						this.extraDefiniteInits[i] &= otherInits.extraDefiniteInits[i];
-						this.extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+						this.extraPotentialInits[i] |= otherInits.extraPotentialInits[i];
+						this.extraDefiniteNulls[i] &= otherInits.extraDefiniteNulls[i];
+						this.extraDefiniteNonNulls[i] &= otherInits.extraDefiniteNonNulls[i++];
 					}
-					while (i < length)
-						this.extraDefiniteInits[i++] = 0;
+					while (i < length) {
+						this.extraDefiniteInits[i] = 0;
+						this.extraDefiniteNulls[i] = 0;
+						this.extraDefiniteNonNulls[i++] = 0;
+					}
 				}
 			} else {
 				// no extra storage on otherInits
 				int i = 0, length = this.extraDefiniteInits.length;
-				while (i < length)
-					this.extraDefiniteInits[i++] = 0;
+				while (i < length) {
+					this.extraDefiniteInits[i] = 0;
+					this.extraDefiniteNulls[i] = 0;
+					this.extraDefiniteNonNulls[i++] = 0;
+				}
 			}
 		} else
 			if (otherInits.extraDefiniteInits != null) {
@@ -500,6 +762,8 @@
 				int otherLength;
 				this.extraDefiniteInits = new long[otherLength = otherInits.extraDefiniteInits.length];
 				System.arraycopy(otherInits.extraPotentialInits, 0, (this.extraPotentialInits = new long[otherLength]), 0, otherLength);
+				this.extraDefiniteNulls = new long[otherLength];
+				this.extraDefiniteNonNulls = new long[otherLength];
 			}
 		return this;
 	}
@@ -548,6 +812,8 @@
 		return "FlowInfo<def: "+ this.definiteInits //$NON-NLS-1$
 			+", pot: " + this.potentialInits  //$NON-NLS-1$
 			+ ", reachable:" + ((this.reachMode & UNREACHABLE) == 0) //$NON-NLS-1$
+			+", defNull: " + this.definiteNulls  //$NON-NLS-1$
+			+", defNonNull: " + this.definiteNonNulls  //$NON-NLS-1$
 			+">"; //$NON-NLS-1$
 	}
 	
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
index 0d729a4..f7f22e3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
@@ -55,6 +55,7 @@
 	public static final String OPTION_ReportUnusedPrivateMember = "org.eclipse.jdt.core.compiler.problem.unusedPrivateMember"; //$NON-NLS-1$
 	public static final String OPTION_ReportNoImplicitStringConversion = "org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion"; //$NON-NLS-1$
 	public static final String OPTION_ReportAssertIdentifier = "org.eclipse.jdt.core.compiler.problem.assertIdentifier"; //$NON-NLS-1$
+	public static final String OPTION_ReportEnumIdentifier = "org.eclipse.jdt.core.compiler.problem.enumIdentifier"; //$NON-NLS-1$
 	public static final String OPTION_ReportNonStaticAccessToStatic = "org.eclipse.jdt.core.compiler.problem.staticAccessReceiver"; //$NON-NLS-1$
 	public static final String OPTION_ReportIndirectStaticAccess = "org.eclipse.jdt.core.compiler.problem.indirectStaticAccess"; //$NON-NLS-1$
 	public static final String OPTION_ReportEmptyStatement = "org.eclipse.jdt.core.compiler.problem.emptyStatement"; //$NON-NLS-1$
@@ -63,6 +64,8 @@
 	public static final String OPTION_ReportUndocumentedEmptyBlock = "org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock"; //$NON-NLS-1$
 	public static final String OPTION_ReportInvalidJavadoc = "org.eclipse.jdt.core.compiler.problem.invalidJavadoc"; //$NON-NLS-1$
 	public static final String OPTION_ReportInvalidJavadocTags = "org.eclipse.jdt.core.compiler.problem.invalidJavadocTags"; //$NON-NLS-1$
+	public static final String OPTION_ReportInvalidJavadocTagsDeprecatedRef = "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef"; //$NON-NLS-1$
+	public static final String OPTION_ReportInvalidJavadocTagsNotVisibleRef = "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef"; //$NON-NLS-1$
 	public static final String OPTION_ReportInvalidJavadocTagsVisibility = "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility"; //$NON-NLS-1$
 	public static final String OPTION_ReportMissingJavadocTags = "org.eclipse.jdt.core.compiler.problem.missingJavadocTags"; //$NON-NLS-1$
 	public static final String OPTION_ReportMissingJavadocTagsVisibility = "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility"; //$NON-NLS-1$
@@ -74,6 +77,10 @@
 	public static final String OPTION_ReportUnusedDeclaredThrownException = "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException"; //$NON-NLS-1$
 	public static final String OPTION_ReportUnusedDeclaredThrownExceptionWhenOverriding = "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding"; //$NON-NLS-1$
 	public static final String OPTION_ReportUnqualifiedFieldAccess = "org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess"; //$NON-NLS-1$
+	public static final String OPTION_ReportUncheckedTypeOperation = "org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation"; //$NON-NLS-1$
+	public static final String OPTION_ReportFinalParameterBound = "org.eclipse.jdt.core.compiler.problem.finalParameterBound"; //$NON-NLS-1$
+	public static final String OPTION_ReportMissingSerialVersion = "org.eclipse.jdt.core.compiler.problem.missingSerialVersion"; //$NON-NLS-1$
+	public static final String OPTION_ReportVarargsArgumentNeedCast = "org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast"; //$NON-NLS-1$
 	public static final String OPTION_Source = "org.eclipse.jdt.core.compiler.source"; //$NON-NLS-1$
 	public static final String OPTION_TargetPlatform = "org.eclipse.jdt.core.compiler.codegen.targetPlatform"; //$NON-NLS-1$
 	public static final String OPTION_Compliance = "org.eclipse.jdt.core.compiler.compliance"; //$NON-NLS-1$
@@ -83,6 +90,13 @@
 	public static final String OPTION_TaskPriorities = "org.eclipse.jdt.core.compiler.taskPriorities"; //$NON-NLS-1$
 	public static final String OPTION_TaskCaseSensitive = "org.eclipse.jdt.core.compiler.taskCaseSensitive"; //$NON-NLS-1$
 	public static final String OPTION_InlineJsr = "org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode"; //$NON-NLS-1$
+	public static final String OPTION_ReportNullReference = "org.eclipse.jdt.core.compiler.problem.nullReference"; //$NON-NLS-1$
+	public static final String OPTION_ReportAutoboxing = "org.eclipse.jdt.core.compiler.problem.autoboxing"; //$NON-NLS-1$
+	public static final String OPTION_ReportForbiddenReference =  "org.eclipse.jdt.core.compiler.problem.forbiddenReference"; //$NON-NLS-1$
+	public static final String OPTION_ImportRestrictionInclude = "org.eclipse.jdt.core.compiler.accessRestriction.import.include"; //$NON-NLS-1$
+	public static final String OPTION_ImportRestrictionExclude = "org.eclipse.jdt.core.compiler.accessRestriction.import.exclude"; //$NON-NLS-1$
+	public static final String OPTION_ExportRestrictionInclude = "org.eclipse.jdt.core.compiler.accessRestriction.export.include"; //$NON-NLS-1$
+	public static final String OPTION_ExportRestrictionExclude = "org.eclipse.jdt.core.compiler.accessRestriction.export.exclude"; //$NON-NLS-1$
 	
 	// Backward compatibility
 	public static final String OPTION_ReportInvalidAnnotation = "org.eclipse.jdt.core.compiler.problem.invalidAnnotation"; //$NON-NLS-1$
@@ -147,6 +161,14 @@
 	public static final long UndocumentedEmptyBlock = ASTNode.Bit28;
 	public static final long IndirectStaticAccess = ASTNode.Bit29;
 	public static final long UnnecessaryElse  = ASTNode.Bit30;
+	public static final long UncheckedTypeOperation = ASTNode.Bit31;
+	public static final long FinalParameterBound = ASTNode.Bit32L;
+	public static final long MissingSerialVersion = ASTNode.Bit33L;
+	public static final long EnumUsedAsAnIdentifier = ASTNode.Bit34L;	
+	public static final long ForbiddenReference = ASTNode.Bit35L;
+	public static final long VarargsArgumentNeedCast = ASTNode.Bit36L;
+	public static final long NullReference = ASTNode.Bit37L;
+	public static final long Autoboxing = ASTNode.Bit38L;
 
 	// Default severity level for handlers
 	public long errorThreshold = 0;
@@ -162,7 +184,13 @@
 		| IncompatibleNonInheritedInterfaceMethod
 		| NoImplicitStringConversion
 		| FinallyBlockNotCompleting
-		| AssertUsedAsAnIdentifier;
+		| AssertUsedAsAnIdentifier
+		| EnumUsedAsAnIdentifier
+		| UncheckedTypeOperation
+		| MissingSerialVersion
+		| VarargsArgumentNeedCast
+		| ForbiddenReference
+		/*| NullReference*/;
 
 	// Debug attributes
 	public static final int Source = 1; // SourceFileAttribute
@@ -197,6 +225,12 @@
 	// max problems per compilation unit
 	public int maxProblemsPerUnit = 100; // no more than 100 problems per default
 	
+	// access restrictions
+	public char[][] importRestrictionInclude;
+	public char[][] importRestrictionExclude;
+	public char[][] exportRestrictionInclude;
+	public char[][] exportRestrictionExclude;
+	
 	// tags used to recognize tasks in comments
 	public char[][] taskTags = null;
 	public char[][] taskPriorites = null;
@@ -216,9 +250,11 @@
 	// constructor/setter parameter hiding
 	public boolean reportSpecialParameterHidingField = false;
 
-	// check javadoc comments
+	// check javadoc comments tags
 	public int reportInvalidJavadocTagsVisibility = AccPrivate; 
-	public boolean reportInvalidJavadocTags = true; 
+	public boolean reportInvalidJavadocTags = true;
+	public boolean reportInvalidJavadocTagsDeprecatedRef = true;
+	public boolean reportInvalidJavadocTagsNotVisibleRef = true;
 
 	// check missing javadoc tags
 	public int reportMissingJavadocTagsVisibility = AccPrivate; 
@@ -281,12 +317,15 @@
 		optionsMap.put(OPTION_ReportPossibleAccidentalBooleanAssignment, getSeverityString(AccidentalBooleanAssign)); 
 		optionsMap.put(OPTION_ReportEmptyStatement, getSeverityString(EmptyStatement)); 
 		optionsMap.put(OPTION_ReportAssertIdentifier, getSeverityString(AssertUsedAsAnIdentifier)); 
+		optionsMap.put(OPTION_ReportEnumIdentifier, getSeverityString(EnumUsedAsAnIdentifier)); 
 		optionsMap.put(OPTION_ReportUndocumentedEmptyBlock, getSeverityString(UndocumentedEmptyBlock)); 
 		optionsMap.put(OPTION_ReportUnnecessaryTypeCheck, getSeverityString(UnnecessaryTypeCheck)); 
 		optionsMap.put(OPTION_ReportUnnecessaryElse, getSeverityString(UnnecessaryElse)); 
 		optionsMap.put(OPTION_ReportInvalidJavadoc, getSeverityString(InvalidJavadoc));
 		optionsMap.put(OPTION_ReportInvalidJavadocTagsVisibility, getVisibilityString(this.reportInvalidJavadocTagsVisibility));
-		optionsMap.put(OPTION_ReportInvalidJavadocTags, this.reportInvalidJavadocTags? ENABLED : DISABLED);
+		optionsMap.put(OPTION_ReportInvalidJavadocTags, this.reportInvalidJavadocTags ? ENABLED : DISABLED);
+		optionsMap.put(OPTION_ReportInvalidJavadocTagsDeprecatedRef, this.reportInvalidJavadocTagsDeprecatedRef ? ENABLED : DISABLED);
+		optionsMap.put(OPTION_ReportInvalidJavadocTagsNotVisibleRef, this.reportInvalidJavadocTagsNotVisibleRef ? ENABLED : DISABLED);
 		optionsMap.put(OPTION_ReportMissingJavadocTags, getSeverityString(MissingJavadocTags));
 		optionsMap.put(OPTION_ReportMissingJavadocTagsVisibility, getVisibilityString(this.reportMissingJavadocTagsVisibility));
 		optionsMap.put(OPTION_ReportMissingJavadocTagsOverriding, this.reportMissingJavadocTagsOverriding ? ENABLED : DISABLED);
@@ -297,6 +336,11 @@
 		optionsMap.put(OPTION_ReportUnusedDeclaredThrownException, getSeverityString(UnusedDeclaredThrownException));
 		optionsMap.put(OPTION_ReportUnusedDeclaredThrownExceptionWhenOverriding, this.reportUnusedDeclaredThrownExceptionWhenOverriding ? ENABLED : DISABLED); 
 		optionsMap.put(OPTION_ReportUnqualifiedFieldAccess, getSeverityString(UnqualifiedFieldAccess));
+		optionsMap.put(OPTION_ReportUncheckedTypeOperation, getSeverityString(UncheckedTypeOperation));
+		optionsMap.put(OPTION_ReportFinalParameterBound, getSeverityString(FinalParameterBound));
+		optionsMap.put(OPTION_ReportMissingSerialVersion, getSeverityString(MissingSerialVersion));
+		optionsMap.put(OPTION_ReportForbiddenReference, getSeverityString(ForbiddenReference));
+		optionsMap.put(OPTION_ReportVarargsArgumentNeedCast, getSeverityString(VarargsArgumentNeedCast)); 
 		optionsMap.put(OPTION_Compliance, versionFromJdkLevel(this.complianceLevel)); 
 		optionsMap.put(OPTION_Source, versionFromJdkLevel(this.sourceLevel)); 
 		optionsMap.put(OPTION_TargetPlatform, versionFromJdkLevel(this.targetJDK)); 
@@ -311,6 +355,11 @@
 		optionsMap.put(OPTION_ReportSpecialParameterHidingField, this.reportSpecialParameterHidingField ? ENABLED : DISABLED); 
 		optionsMap.put(OPTION_MaxProblemPerUnit, String.valueOf(this.maxProblemsPerUnit));
 		optionsMap.put(OPTION_InlineJsr, this.inlineJsrBytecode ? ENABLED : DISABLED); 
+		optionsMap.put(OPTION_ImportRestrictionInclude, this.importRestrictionInclude == null ? "" : new String(CharOperation.concatWith(this.importRestrictionInclude,','))); //$NON-NLS-1$
+		optionsMap.put(OPTION_ImportRestrictionExclude, this.importRestrictionExclude == null ? "" : new String(CharOperation.concatWith(this.importRestrictionExclude,','))); //$NON-NLS-1$
+		optionsMap.put(OPTION_ImportRestrictionInclude, this.exportRestrictionInclude == null ? "" : new String(CharOperation.concatWith(this.exportRestrictionInclude,','))); //$NON-NLS-1$
+		optionsMap.put(OPTION_ExportRestrictionExclude, this.exportRestrictionExclude == null ? "" : new String(CharOperation.concatWith(this.exportRestrictionExclude,','))); //$NON-NLS-1$
+		optionsMap.put(OPTION_ReportNullReference, getSeverityString(NullReference)); 
 		return optionsMap;		
 	}
 	
@@ -406,6 +455,7 @@
 		if ((optionValue = optionsMap.get(OPTION_TargetPlatform)) != null) {
 			long level = versionToJdkLevel(optionValue);
 			if (level != 0) this.targetJDK = level;
+			if (this.targetJDK >= JDK1_5) this.inlineJsrBytecode = true; // forced in 1.5 mode
 		}
 		if ((optionValue = optionsMap.get(OPTION_Encoding)) != null) {
 			if (optionValue instanceof String) {
@@ -484,11 +534,53 @@
 				this.isTaskCaseSensitive = false;
 			}
 		}
+		if ((optionValue = optionsMap.get(OPTION_ImportRestrictionInclude)) != null) {
+			if (optionValue instanceof String) {
+				String stringValue = (String) optionValue;
+				if (stringValue.length() == 0) {
+					this.importRestrictionInclude = null;
+				} else {
+					this.importRestrictionInclude = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+				}
+			}
+		}	
+		if ((optionValue = optionsMap.get(OPTION_ImportRestrictionExclude)) != null) {
+			if (optionValue instanceof String) {
+				String stringValue = (String) optionValue;
+				if (stringValue.length() == 0) {
+					this.importRestrictionExclude = null;
+				} else {
+					this.importRestrictionExclude = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+				}
+			}
+		}			
+		if ((optionValue = optionsMap.get(OPTION_ExportRestrictionInclude)) != null) {
+			if (optionValue instanceof String) {
+				String stringValue = (String) optionValue;
+				if (stringValue.length() == 0) {
+					this.exportRestrictionInclude = null;
+				} else {
+					this.exportRestrictionInclude = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+				}
+			}
+		}			
+		if ((optionValue = optionsMap.get(OPTION_ExportRestrictionExclude)) != null) {
+			if (optionValue instanceof String) {
+				String stringValue = (String) optionValue;
+				if (stringValue.length() == 0) {
+					this.exportRestrictionExclude = null;
+				} else {
+					this.exportRestrictionExclude = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+				}
+			}
+		}			
 		if ((optionValue = optionsMap.get(OPTION_InlineJsr)) != null) {
-			if (ENABLED.equals(optionValue)) {
-				this.inlineJsrBytecode = true;
-			} else if (DISABLED.equals(optionValue)) {
-				this.inlineJsrBytecode = false;
+			if (this.targetJDK < JDK1_5) { // only optional if target < 1.5 (inlining on from 1.5 on)
+				if (ENABLED.equals(optionValue)) {
+					this.inlineJsrBytecode = true;
+				} else if (DISABLED.equals(optionValue)) {
+					this.inlineJsrBytecode = false;
+				}
 			}
 		}
 		if ((optionValue = optionsMap.get(OPTION_ReportMethodWithConstructorName)) != null) updateSeverity(MethodWithConstructorName, optionValue);
@@ -508,16 +600,24 @@
 		if ((optionValue = optionsMap.get(OPTION_ReportEmptyStatement)) != null) updateSeverity(EmptyStatement, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportNonExternalizedStringLiteral)) != null) updateSeverity(NonExternalizedString, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportAssertIdentifier)) != null) updateSeverity(AssertUsedAsAnIdentifier, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportEnumIdentifier)) != null) updateSeverity(EnumUsedAsAnIdentifier, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportNonStaticAccessToStatic)) != null) updateSeverity(NonStaticAccessToStatic, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportIndirectStaticAccess)) != null) updateSeverity(IndirectStaticAccess, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportIncompatibleNonInheritedInterfaceMethod)) != null) updateSeverity(IncompatibleNonInheritedInterfaceMethod, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportUndocumentedEmptyBlock)) != null) updateSeverity(UndocumentedEmptyBlock, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportUnnecessaryTypeCheck)) != null) updateSeverity(UnnecessaryTypeCheck, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportUnnecessaryElse)) != null) updateSeverity(UnnecessaryElse, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportFinallyBlockNotCompletingNormally)) != null) updateSeverity(FinallyBlockNotCompleting, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportUnqualifiedFieldAccess)) != null) updateSeverity(UnqualifiedFieldAccess, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportNoEffectAssignment)) != null) updateSeverity(NoEffectAssignment, optionValue);
-		if ((optionValue = optionsMap.get(OPTION_ReportUnnecessaryElse)) != null) updateSeverity(UnnecessaryElse, optionValue);
-
+		if ((optionValue = optionsMap.get(OPTION_ReportUncheckedTypeOperation)) != null) updateSeverity(UncheckedTypeOperation, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportFinalParameterBound)) != null) updateSeverity(FinalParameterBound, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportMissingSerialVersion)) != null) updateSeverity(MissingSerialVersion, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportForbiddenReference)) != null) updateSeverity(ForbiddenReference, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportVarargsArgumentNeedCast)) != null) updateSeverity(VarargsArgumentNeedCast, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportNullReference)) != null) updateSeverity(NullReference, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportAutoboxing)) != null) updateSeverity(Autoboxing, optionValue);
+		
 		// Javadoc options
 		if ((optionValue = optionsMap.get(OPTION_DocCommentSupport)) != null) {
 			if (ENABLED.equals(optionValue)) {
@@ -542,11 +642,25 @@
 		}
 		if ((optionValue = optionsMap.get(OPTION_ReportInvalidJavadocTags)) != null) {
 			if (ENABLED.equals(optionValue)) {
-				this.reportInvalidJavadocTags= true;
+				this.reportInvalidJavadocTags = true;
 			} else if (DISABLED.equals(optionValue)) {
 				this.reportInvalidJavadocTags = false;
 			}
 		}
+		if ((optionValue = optionsMap.get(OPTION_ReportInvalidJavadocTagsDeprecatedRef)) != null) {
+			if (ENABLED.equals(optionValue)) {
+				this.reportInvalidJavadocTagsDeprecatedRef = true;
+			} else if (DISABLED.equals(optionValue)) {
+				this.reportInvalidJavadocTagsDeprecatedRef = false;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_ReportInvalidJavadocTagsNotVisibleRef)) != null) {
+			if (ENABLED.equals(optionValue)) {
+				this.reportInvalidJavadocTagsNotVisibleRef = true;
+			} else if (DISABLED.equals(optionValue)) {
+				this.reportInvalidJavadocTagsNotVisibleRef = false;
+			}
+		}
 		if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocTags)) != null) {
 			updateSeverity(MissingJavadocTags, optionValue);
 		}
@@ -621,6 +735,8 @@
 		buf.append("\n\t- javadoc comment support: ").append(this.docCommentSupport ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 		buf.append("\n\t\t+ invalid javadoc: ").append(getSeverityString(InvalidJavadoc)); //$NON-NLS-1$
 		buf.append("\n\t\t+ report invalid javadoc tags: ").append(this.reportInvalidJavadocTags ? ENABLED : DISABLED); //$NON-NLS-1$
+		buf.append("\n\t\t\t* deprecated references: ").append(this.reportInvalidJavadocTagsDeprecatedRef ? ENABLED : DISABLED); //$NON-NLS-1$
+		buf.append("\n\t\t\t* not visble references: ").append(this.reportInvalidJavadocTagsNotVisibleRef ? ENABLED : DISABLED); //$NON-NLS-1$
 		buf.append("\n\t\t+ visibility level to report invalid javadoc tags: ").append(getVisibilityString(this.reportInvalidJavadocTagsVisibility)); //$NON-NLS-1$
 		buf.append("\n\t\t+ missing javadoc tags: ").append(getSeverityString(MissingJavadocTags)); //$NON-NLS-1$
 		buf.append("\n\t\t+ visibility level to report missing javadoc tags: ").append(getVisibilityString(this.reportMissingJavadocTagsVisibility)); //$NON-NLS-1$
@@ -648,6 +764,17 @@
 		buf.append("\n\t- report unused parameter when overriding concrete method : ").append(this.reportUnusedParameterWhenOverridingConcrete ? ENABLED : DISABLED); //$NON-NLS-1$
 		buf.append("\n\t- report constructor/setter parameter hiding existing field : ").append(this.reportSpecialParameterHidingField ? ENABLED : DISABLED); //$NON-NLS-1$
 		buf.append("\n\t- inline JSR bytecode : ").append(this.inlineJsrBytecode ? ENABLED : DISABLED); //$NON-NLS-1$
+		buf.append("\n\t- unsafe type operation: ").append(getSeverityString(UncheckedTypeOperation)); //$NON-NLS-1$
+		buf.append("\n\t- final bound for type parameter: ").append(getSeverityString(FinalParameterBound)); //$NON-NLS-1$
+		buf.append("\n\t- missing serialVersionUID: ").append(getSeverityString(MissingSerialVersion)); //$NON-NLS-1$
+		buf.append("\n\t- varargs argument need cast: ").append(getSeverityString(VarargsArgumentNeedCast)); //$NON-NLS-1$
+		buf.append("\n\t- forbidden reference to type with access restriction: ").append(getSeverityString(ForbiddenReference)); //$NON-NLS-1$
+		buf.append("\n\t- import access restriction includes: ").append(this.importRestrictionInclude == null ? "" : new String(CharOperation.concatWith(this.importRestrictionInclude,',')));  //$NON-NLS-1$ //$NON-NLS-2$
+		buf.append("\n\t- import access restriction excludes: ").append(this.importRestrictionExclude == null ? "" : new String(CharOperation.concatWith(this.importRestrictionExclude,',')));  //$NON-NLS-1$ //$NON-NLS-2$
+		buf.append("\n\t- export access restriction includes: ").append(this.exportRestrictionInclude == null ? "" : new String(CharOperation.concatWith(this.exportRestrictionInclude,',')));  //$NON-NLS-1$ //$NON-NLS-2$
+		buf.append("\n\t- export access restriction excludes: ").append(this.exportRestrictionExclude == null ? "" : new String(CharOperation.concatWith(this.exportRestrictionExclude,',')));  //$NON-NLS-1$ //$NON-NLS-2$
+		buf.append("\n\t- null reference: ").append(getSeverityString(NullReference)); //$NON-NLS-1$
+		buf.append("\n\t- autoboxing: ").append(getSeverityString(Autoboxing)); //$NON-NLS-1$
 		return buf.toString();
 	}
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/Constant.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/Constant.java
index f82b409..3130eed 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/Constant.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/Constant.java
@@ -112,7 +112,7 @@
 	//	    case (T_String<<4)+T_long  		 : return NotAConstant;   
 	//	    case (T_String<<4)+T_short  	 : return NotAConstant;   
 	//	    case (T_String<<4)+T_void  		 : return NotAConstant;   
-		    case (T_String<<4)+T_String  	 : return this;   
+		    case (T_JavaLangString<<4)+T_JavaLangString  	 : return this;   
 	//	    case (T_String<<4)+T_Object  	 : return NotAConstant;   
 	//	    case (T_String<<4)+T_double  	 : return NotAConstant;   
 	//	    case (T_String<<4)+T_float  	 : return NotAConstant;   
@@ -213,7 +213,8 @@
 		switch (operator) {
 			case NOT	: 	
 							return Constant.fromValue(!cst.booleanValue());
-			case PLUS	:	return cst; 
+			case PLUS	:
+							return computeConstantOperationPLUS(Zero,T_int,cst,id);
 			case MINUS	:	//the two special -9223372036854775808L and -2147483648 are inlined at parseTime
 							switch (id){
 								case T_float  :	float f;
@@ -233,7 +234,7 @@
 														return Constant.fromValue(0.0d);}
 												break; //default case
 							}
-							return computeConstantOperationMINUS(Zero,T_int,operator,cst,id);
+							return computeConstantOperationMINUS(Zero,T_int,cst,id);
 			case TWIDDLE:	
 				switch (id){
 					case T_char :	return Constant.fromValue(~ cst.charValue());
@@ -250,29 +251,29 @@
 	public static final Constant computeConstantOperation(Constant left, int leftId, int operator, Constant right, int rightId) {
 
 		switch (operator) {
-			case AND		: return computeConstantOperationAND		(left,leftId,operator,right,rightId);
-			case AND_AND	: return computeConstantOperationAND_AND	(left,leftId,operator,right,rightId);
-			case DIVIDE 	: return computeConstantOperationDIVIDE		(left,leftId,operator,right,rightId);
-			case GREATER	: return computeConstantOperationGREATER	(left,leftId,operator,right,rightId);
-			case GREATER_EQUAL	: return computeConstantOperationGREATER_EQUAL(left,leftId,operator,right,rightId);
-			case LEFT_SHIFT	: return computeConstantOperationLEFT_SHIFT	(left,leftId,operator,right,rightId);
-			case LESS		: return computeConstantOperationLESS		(left,leftId,operator,right,rightId);
-			case LESS_EQUAL	: return computeConstantOperationLESS_EQUAL	(left,leftId,operator,right,rightId);
-			case MINUS		: return computeConstantOperationMINUS		(left,leftId,operator,right,rightId);
-			case MULTIPLY	: return computeConstantOperationMULTIPLY	(left,leftId,operator,right,rightId);
-			case OR			: return computeConstantOperationOR			(left,leftId,operator,right,rightId);
-			case OR_OR		: return computeConstantOperationOR_OR		(left,leftId,operator,right,rightId);
-			case PLUS		: return computeConstantOperationPLUS		(left,leftId,operator,right,rightId);
-			case REMAINDER	: return computeConstantOperationREMAINDER	(left,leftId,operator,right,rightId);
-			case RIGHT_SHIFT: return computeConstantOperationRIGHT_SHIFT(left,leftId,operator,right,rightId);
-			case UNSIGNED_RIGHT_SHIFT: return computeConstantOperationUNSIGNED_RIGHT_SHIFT(left,leftId,operator,right,rightId);
-			case XOR		: return computeConstantOperationXOR		(left,leftId,operator,right,rightId);
+			case AND		: return computeConstantOperationAND		(left,leftId,right,rightId);
+			case AND_AND	: return computeConstantOperationAND_AND	(left,leftId,right,rightId);
+			case DIVIDE 	: return computeConstantOperationDIVIDE		(left,leftId,right,rightId);
+			case GREATER	: return computeConstantOperationGREATER	(left,leftId,right,rightId);
+			case GREATER_EQUAL	: return computeConstantOperationGREATER_EQUAL(left,leftId,right,rightId);
+			case LEFT_SHIFT	: return computeConstantOperationLEFT_SHIFT	(left,leftId,right,rightId);
+			case LESS		: return computeConstantOperationLESS		(left,leftId,right,rightId);
+			case LESS_EQUAL	: return computeConstantOperationLESS_EQUAL	(left,leftId,right,rightId);
+			case MINUS		: return computeConstantOperationMINUS		(left,leftId,right,rightId);
+			case MULTIPLY	: return computeConstantOperationMULTIPLY	(left,leftId,right,rightId);
+			case OR			: return computeConstantOperationOR			(left,leftId,right,rightId);
+			case OR_OR		: return computeConstantOperationOR_OR		(left,leftId,right,rightId);
+			case PLUS		: return computeConstantOperationPLUS		(left,leftId,right,rightId);
+			case REMAINDER	: return computeConstantOperationREMAINDER	(left,leftId,right,rightId);
+			case RIGHT_SHIFT: return computeConstantOperationRIGHT_SHIFT(left,leftId,right,rightId);
+			case UNSIGNED_RIGHT_SHIFT: return computeConstantOperationUNSIGNED_RIGHT_SHIFT(left,leftId,right,rightId);
+			case XOR		: return computeConstantOperationXOR		(left,leftId,right,rightId);
 	
 			default : return NotAConstant;
 		}
 	}
 	
-	public static final Constant computeConstantOperationAND(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationAND(Constant left, int leftId, Constant right, int rightId) {
 		
 		switch (leftId){
 			case T_boolean :		return Constant.fromValue(left.booleanValue() & right.booleanValue());
@@ -325,12 +326,12 @@
 		return NotAConstant;
 	} 
 		
-	public static final Constant computeConstantOperationAND_AND(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationAND_AND(Constant left, int leftId, Constant right, int rightId) {
 	
 		return Constant.fromValue(left.booleanValue() && right.booleanValue());
 	}
 		
-	public static final Constant computeConstantOperationDIVIDE(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationDIVIDE(Constant left, int leftId, Constant right, int rightId) {
 		// division by zero must be handled outside this method (error reporting)
 	
 		switch (leftId){
@@ -416,7 +417,7 @@
 		return NotAConstant;
 	} 
 		
-	public static final Constant computeConstantOperationEQUAL_EQUAL(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationEQUAL_EQUAL(Constant left, int leftId, Constant right, int rightId) {
 		
 		switch (leftId){
 			case T_boolean :
@@ -500,15 +501,15 @@
 					case T_long:	return Constant.fromValue(left.longValue() == right.longValue());
 				}
 			break;
-			case T_String :
-				if (rightId == T_String) {
+			case T_JavaLangString :
+				if (rightId == T_JavaLangString) {
 					//String are interned in th compiler==>thus if two string constant
 					//get to be compared, it is an equal on the vale which is done
 					return Constant.fromValue(((StringConstant)left).compileTimeEqual((StringConstant)right));
 				}
 			break;	
 			case T_null :
-				if (rightId == T_String) { 
+				if (rightId == T_JavaLangString) { 
 					return Constant.fromValue(false);
 				} else {
 					if (rightId == T_null) { 
@@ -520,7 +521,7 @@
 		return Constant.fromValue(false);
 	}
 		
-	public static final Constant computeConstantOperationGREATER(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationGREATER(Constant left, int leftId, Constant right, int rightId) {
 		
 		switch (leftId){
 			case T_char : 
@@ -605,7 +606,7 @@
 		return NotAConstant;
 	}
 
-	public static final Constant computeConstantOperationGREATER_EQUAL(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationGREATER_EQUAL(Constant left, int leftId, Constant right, int rightId) {
 		
 		switch (leftId){
 			case T_char : 
@@ -690,7 +691,7 @@
 		return NotAConstant;
 	}  
 		
-	public static final Constant computeConstantOperationLEFT_SHIFT(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationLEFT_SHIFT(Constant left, int leftId, Constant right, int rightId) {
 		
 		switch (leftId){
 			case T_char :
@@ -743,7 +744,7 @@
 		return NotAConstant;
 	} 
 		
-	public static final Constant computeConstantOperationLESS(Constant left, int leftId, int operator, Constant right, int rightId) { 
+	public static final Constant computeConstantOperationLESS(Constant left, int leftId, Constant right, int rightId) { 
 		
 		switch (leftId){
 			case T_char : 
@@ -828,7 +829,7 @@
 		return NotAConstant;
 	}
 		
-	public static final Constant computeConstantOperationLESS_EQUAL(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationLESS_EQUAL(Constant left, int leftId, Constant right, int rightId) {
 		
 		switch (leftId){
 			case T_char : 
@@ -912,7 +913,7 @@
 		return NotAConstant;
 	}  
 	
-	public static final Constant computeConstantOperationMINUS(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationMINUS(Constant left, int leftId, Constant right, int rightId) {
 		
 		switch (leftId){
 			case T_char : 
@@ -997,7 +998,7 @@
 		return NotAConstant;
 	}
 	
-	public static final Constant computeConstantOperationMULTIPLY(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationMULTIPLY(Constant left, int leftId, Constant right, int rightId) {
 	
 		switch (leftId){
 			case T_char :
@@ -1081,7 +1082,7 @@
 		return NotAConstant;
 	}
 	
-	public static final Constant computeConstantOperationOR(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationOR(Constant left, int leftId, Constant right, int rightId) {
 		
 		switch (leftId){
 			case T_boolean :		return Constant.fromValue(left.booleanValue() | right.booleanValue());
@@ -1135,20 +1136,20 @@
 		return NotAConstant;
 	}
 	
-	public static final Constant computeConstantOperationOR_OR(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationOR_OR(Constant left, int leftId, Constant right, int rightId) {
 	
 		return Constant.fromValue(left.booleanValue() || right.booleanValue());
 	}
 		
-	public static final Constant computeConstantOperationPLUS(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationPLUS(Constant left, int leftId, Constant right, int rightId) {
 		
 		switch (leftId){
-			case T_Object :
-				if (rightId == T_String) {
+			case T_JavaLangObject :
+				if (rightId == T_JavaLangString) {
 					return Constant.fromValue(left.stringValue() + right.stringValue());
 				}
 			case T_boolean :
-				if (rightId == T_String) {
+				if (rightId == T_JavaLangString) {
 					return Constant.fromValue(left.stringValue() + right.stringValue());
 				}
 			break;
@@ -1161,7 +1162,7 @@
 					case T_short:	return Constant.fromValue(left.charValue() + right.shortValue());
 					case T_int:		return Constant.fromValue(left.charValue() + right.intValue());
 					case T_long:	return Constant.fromValue(left.charValue() + right.longValue());
-					case T_String:	return Constant.fromValue(left.stringValue() + right.stringValue());
+					case T_JavaLangString:	return Constant.fromValue(left.stringValue() + right.stringValue());
 				}
 			break;
 			case T_float :
@@ -1173,7 +1174,7 @@
 					case T_short:	return Constant.fromValue(left.floatValue() + right.shortValue());
 					case T_int:		return Constant.fromValue(left.floatValue() + right.intValue());
 					case T_long:	return Constant.fromValue(left.floatValue() + right.longValue());
-					case T_String:	return Constant.fromValue(left.stringValue() + right.stringValue()); 
+					case T_JavaLangString:	return Constant.fromValue(left.stringValue() + right.stringValue()); 
 				}
 			break;
 			case T_double :
@@ -1185,7 +1186,7 @@
 					case T_short:	return Constant.fromValue(left.doubleValue() + right.shortValue());
 					case T_int:		return Constant.fromValue(left.doubleValue() + right.intValue());
 					case T_long:	return Constant.fromValue(left.doubleValue() + right.longValue());
-					case T_String:	return Constant.fromValue(left.stringValue() + right.stringValue());
+					case T_JavaLangString:	return Constant.fromValue(left.stringValue() + right.stringValue());
 				}
 			break;
 			case T_byte :
@@ -1197,7 +1198,7 @@
 					case T_short:	return Constant.fromValue(left.byteValue() + right.shortValue());
 					case T_int:		return Constant.fromValue(left.byteValue() + right.intValue());
 					case T_long:	return Constant.fromValue(left.byteValue() + right.longValue());
-					case T_String:	return Constant.fromValue(left.stringValue() + right.stringValue()); 
+					case T_JavaLangString:	return Constant.fromValue(left.stringValue() + right.stringValue()); 
 				}
 	
 			break;			
@@ -1210,7 +1211,7 @@
 					case T_short:	return Constant.fromValue(left.shortValue() + right.shortValue());
 					case T_int:		return Constant.fromValue(left.shortValue() + right.intValue());
 					case T_long:	return Constant.fromValue(left.shortValue() + right.longValue());
-					case T_String:	return Constant.fromValue(left.stringValue() + right.stringValue());
+					case T_JavaLangString:	return Constant.fromValue(left.stringValue() + right.stringValue());
 				}
 			break;
 			case T_int :
@@ -1222,7 +1223,7 @@
 					case T_short:	return Constant.fromValue(left.intValue() + right.shortValue());
 					case T_int:		return Constant.fromValue(left.intValue() + right.intValue());
 					case T_long:	return Constant.fromValue(left.intValue() + right.longValue());
-					case T_String:	return Constant.fromValue(left.stringValue() + right.stringValue());
+					case T_JavaLangString:	return Constant.fromValue(left.stringValue() + right.stringValue());
 				}
 			break;		
 			case T_long :
@@ -1234,10 +1235,10 @@
 					case T_short:	return Constant.fromValue(left.longValue() + right.shortValue());
 					case T_int:		return Constant.fromValue(left.longValue() + right.intValue());
 					case T_long:	return Constant.fromValue(left.longValue() + right.longValue());
-					case T_String:	return Constant.fromValue(left.stringValue() + right.stringValue()); 
+					case T_JavaLangString:	return Constant.fromValue(left.stringValue() + right.stringValue()); 
 				}
 			break;
-			case T_String :
+			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());
@@ -1246,7 +1247,7 @@
 					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_String:	return Constant.fromValue(left.stringValue() + right.stringValue()); 
+					case T_JavaLangString:	return Constant.fromValue(left.stringValue() + right.stringValue()); 
 					case T_boolean:	return Constant.fromValue(left.stringValue() + right.stringValue());
 				}
 			break;	
@@ -1259,7 +1260,7 @@
 					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_String:	return Constant.fromValue(left.stringValue() + right.stringValue()); 
+					case T_JavaLangString:	return Constant.fromValue(left.stringValue() + right.stringValue()); 
 				}
 				
 			}
@@ -1267,7 +1268,7 @@
 		return NotAConstant;
 	}
 		
-	public static final Constant computeConstantOperationREMAINDER(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationREMAINDER(Constant left, int leftId, Constant right, int rightId) {
 		
 		switch (leftId){
 			case T_char : 
@@ -1352,7 +1353,7 @@
 		return NotAConstant;
 	} 
 	
-	public static final Constant computeConstantOperationRIGHT_SHIFT(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationRIGHT_SHIFT(Constant left, int leftId, Constant right, int rightId) {
 		
 		switch (leftId){
 			case T_char :
@@ -1405,7 +1406,7 @@
 		return NotAConstant;
 	}
 
-	public static final Constant computeConstantOperationUNSIGNED_RIGHT_SHIFT(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationUNSIGNED_RIGHT_SHIFT(Constant left, int leftId, Constant right, int rightId) {
 		
 		switch (leftId){
 			case T_char :
@@ -1458,7 +1459,7 @@
 		return NotAConstant;
 	}
 	
-	public static final Constant computeConstantOperationXOR(Constant left, int leftId, int operator, Constant right, int rightId) {
+	public static final Constant computeConstantOperationXOR(Constant left, int leftId, Constant right, int rightId) {
 		
 		switch (leftId){
 			case T_boolean :		return Constant.fromValue(left.booleanValue() ^ right.booleanValue());
@@ -1603,7 +1604,7 @@
 			case T_double : return "double"; //$NON-NLS-1$
 			case T_boolean : return "boolean"; //$NON-NLS-1$
 			case T_long : return "long";//$NON-NLS-1$
-			case T_String : return "java.lang.String"; //$NON-NLS-1$
+			case T_JavaLangString : return "java.lang.String"; //$NON-NLS-1$
 			case T_null : return "null";	 //$NON-NLS-1$
 			default: return "unknown"; //$NON-NLS-1$
 		}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java
index 52398d0..9ae827d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.impl;
 
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.compiler.env.ISourceType;
@@ -20,12 +21,12 @@
 	/**
 	 * Accept the resolved binary form for the requested type.
 	 */
-	void accept(IBinaryType binaryType, PackageBinding packageBinding);
+	void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction);
 
 	/**
 	 * Accept the requested type's compilation unit.
 	 */
-	void accept(ICompilationUnit unit);
+	void accept(ICompilationUnit unit, AccessRestriction accessRestriction);
 
 	/**
 	 * Accept the unresolved source forms for the requested type.
@@ -33,5 +34,5 @@
 	 * contains multiple types. The first one is then guaranteed to be the one corresponding to the
 	 * requested type.
 	 */
-	void accept(ISourceType[] sourceType, PackageBinding packageBinding);
+	void accept(ISourceType[] sourceType, PackageBinding packageBinding, AccessRestriction accessRestriction);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/StringConstant.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/StringConstant.java
index 0248540..51ab819 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/StringConstant.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/StringConstant.java
@@ -43,6 +43,6 @@
 
 	return "(String)\"" + value +"\""; } //$NON-NLS-2$ //$NON-NLS-1$
 public int typeID() {
-	return T_String;
+	return T_JavaLangString;
 }
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
index da45684..541002b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
+import java.util.Map;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 
@@ -20,19 +21,56 @@
 
 	public TypeBinding leafComponentType;
 	public int dimensions;
-
+	LookupEnvironment environment;	
 	char[] constantPoolName;
-public ArrayBinding(TypeBinding type, int dimensions) {
+	char[] genericTypeSignature;
+	
+public ArrayBinding(TypeBinding type, int dimensions, LookupEnvironment environment) {
 	this.tagBits |= IsArrayType;
 	this.leafComponentType = type;
 	this.dimensions = dimensions;
+	this.environment = environment;
+	if (type instanceof UnresolvedReferenceBinding)
+		((UnresolvedReferenceBinding) type).addWrapper(this);
+	else
+    	this.tagBits |= type.tagBits & (HasTypeVariable | HasDirectWildcard);
 }
+
+public int kind() {
+	return ARRAY_TYPE;
+}
+
+/**
+ * Collect the substitutes into a map for certain type variables inside the receiver type
+ * e.g.   Collection<T>.findSubstitute(T, Collection<List<X>>):   T --> List<X>
+ */
+public void collectSubstitutes(TypeBinding otherType, Map substitutes) {
+    if (otherType.isArrayType()) {
+        int otherDim = otherType.dimensions();
+        if (otherDim == this.dimensions) {
+		    this.leafComponentType.collectSubstitutes(otherType.leafComponentType(), substitutes);
+        } else if (otherDim > this.dimensions) {
+            ArrayBinding otherReducedType = this.environment.createArrayType(otherType.leafComponentType(), otherDim - this.dimensions);
+            this.leafComponentType.collectSubstitutes(otherReducedType, substitutes);
+        }
+    } 
+}
+
+/*
+ * brakets leafUniqueKey
+ * p.X[][] --> [[Lp/X;
+ */
+public char[] computeUniqueKey() {
+	char[] brackets = new char[dimensions];
+	for (int i = dimensions - 1; i >= 0; i--) brackets[i] = '[';
+	return CharOperation.concat(brackets, this.leafComponentType.computeUniqueKey());
+ }
+	
 /**
  * Answer the receiver's constant pool name.
  * NOTE: This method should only be used during/after code gen.
  * e.g. '[Ljava/lang/Object;'
  */
-
 public char[] constantPoolName() {
 	if (constantPoolName != null)
 		return constantPoolName;
@@ -41,7 +79,7 @@
 	for (int i = dimensions - 1; i >= 0; i--) brackets[i] = '[';
 	return constantPoolName = CharOperation.concat(brackets, leafComponentType.signature());
 }
-String debugName() {
+public String debugName() {
 	StringBuffer brackets = new StringBuffer(dimensions * 2);
 	for (int i = dimensions; --i >= 0;)
 		brackets.append("[]"); //$NON-NLS-1$
@@ -56,16 +94,41 @@
 * When the receiver's dimension size is one then answer the leaf component type.
 */
 
-public TypeBinding elementsType(Scope scope) {
-	if (dimensions == 1) 	return leafComponentType;
-	return scope.createArray(leafComponentType, dimensions - 1);
+public TypeBinding elementsType() {
+	if (this.dimensions == 1) return this.leafComponentType;
+	return this.environment.createArrayType(this.leafComponentType, this.dimensions - 1);
 }
+/**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#erasure()
+ */
+public TypeBinding erasure() {
+    TypeBinding erasedType = this.leafComponentType.erasure();
+    if (this.leafComponentType != erasedType)
+        return this.environment.createArrayType(erasedType, this.dimensions);
+    return this;
+}
+public LookupEnvironment environment() {
+    return this.environment;
+}
+
+public char[] genericTypeSignature() {
+	
+    if (this.genericTypeSignature == null) {
+		char[] brackets = new char[dimensions];
+		for (int i = dimensions - 1; i >= 0; i--) brackets[i] = '[';
+		this.genericTypeSignature = CharOperation.concat(brackets, leafComponentType.genericTypeSignature());
+    }
+    return this.genericTypeSignature;
+}
+
 public PackageBinding getPackage() {
 	return leafComponentType.getPackage();
 }
+public int hashCode() {
+	return this.leafComponentType == null ? super.hashCode() : this.leafComponentType.hashCode();
+}
 /* Answer true if the receiver type can be assigned to the argument type (right)
 */
-
 public boolean isCompatibleWith(TypeBinding right) {
 	if (this == right)
 		return true;
@@ -81,6 +144,9 @@
 	} else {
 		if (right.isBaseType())
 			return false;
+		if (right.isWildcard()) {
+		    return ((WildcardBinding) right).boundCheck(this);
+		}
 	}
 	//Check dimensions - Java does not support explicitly sized dimensions for types.
 	//However, if it did, the type checking support would go here.
@@ -143,6 +209,12 @@
 	}
 	return CharOperation.concat(leafComponentType.sourceName(), brackets);
 }
+public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) {
+	if (this.leafComponentType == unresolvedType) {
+		this.leafComponentType = resolvedType.isGenericType() ? env.createRawType(resolvedType, resolvedType.enclosingType()) : resolvedType;
+		this.tagBits |= this.leafComponentType.tagBits & (HasTypeVariable | HasDirectWildcard);
+	}
+}
 public String toString() {
 	return leafComponentType != null ? debugName() : "NULL TYPE ARRAY"; //$NON-NLS-1$
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypes.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypes.java
index b1ec5eb..a6e82bf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypes.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypes.java
@@ -11,14 +11,14 @@
 package org.eclipse.jdt.internal.compiler.lookup;
 
 public interface BaseTypes {
-	final BaseTypeBinding IntBinding = new BaseTypeBinding(TypeIds.T_int, "int".toCharArray(), new char[] {'I'}); //$NON-NLS-1$
-	final BaseTypeBinding ByteBinding = new BaseTypeBinding(TypeIds.T_byte, "byte".toCharArray(), new char[] {'B'}); //$NON-NLS-1$
-	final BaseTypeBinding ShortBinding = new BaseTypeBinding(TypeIds.T_short, "short".toCharArray(), new char[] {'S'}); //$NON-NLS-1$
-	final BaseTypeBinding CharBinding = new BaseTypeBinding(TypeIds.T_char, "char".toCharArray(), new char[] {'C'}); //$NON-NLS-1$
-	final BaseTypeBinding LongBinding = new BaseTypeBinding(TypeIds.T_long, "long".toCharArray(), new char[] {'J'}); //$NON-NLS-1$
-	final BaseTypeBinding FloatBinding = new BaseTypeBinding(TypeIds.T_float, "float".toCharArray(), new char[] {'F'}); //$NON-NLS-1$
-	final BaseTypeBinding DoubleBinding = new BaseTypeBinding(TypeIds.T_double, "double".toCharArray(), new char[] {'D'}); //$NON-NLS-1$
-	final BaseTypeBinding BooleanBinding = new BaseTypeBinding(TypeIds.T_boolean, "boolean".toCharArray(), new char[] {'Z'}); //$NON-NLS-1$
-	final BaseTypeBinding NullBinding = new BaseTypeBinding(TypeIds.T_null, "null".toCharArray(), new char[] {'N'}); //N stands for null even if it is never internally used //$NON-NLS-1$
-	final BaseTypeBinding VoidBinding = new BaseTypeBinding(TypeIds.T_void, "void".toCharArray(), new char[] {'V'}); //$NON-NLS-1$
+	final BaseTypeBinding IntBinding = new BaseTypeBinding(TypeIds.T_int, TypeConstants.INT, new char[] {'I'}); //$NON-NLS-1$
+	final BaseTypeBinding ByteBinding = new BaseTypeBinding(TypeIds.T_byte, TypeConstants.BYTE, new char[] {'B'}); //$NON-NLS-1$
+	final BaseTypeBinding ShortBinding = new BaseTypeBinding(TypeIds.T_short, TypeConstants.SHORT, new char[] {'S'}); //$NON-NLS-1$
+	final BaseTypeBinding CharBinding = new BaseTypeBinding(TypeIds.T_char, TypeConstants.CHAR, new char[] {'C'}); //$NON-NLS-1$
+	final BaseTypeBinding LongBinding = new BaseTypeBinding(TypeIds.T_long, TypeConstants.LONG, new char[] {'J'}); //$NON-NLS-1$
+	final BaseTypeBinding FloatBinding = new BaseTypeBinding(TypeIds.T_float, TypeConstants.FLOAT, new char[] {'F'}); //$NON-NLS-1$
+	final BaseTypeBinding DoubleBinding = new BaseTypeBinding(TypeIds.T_double, TypeConstants.DOUBLE, new char[] {'D'}); //$NON-NLS-1$
+	final BaseTypeBinding BooleanBinding = new BaseTypeBinding(TypeIds.T_boolean, TypeConstants.BOOLEAN, new char[] {'Z'}); //$NON-NLS-1$
+	final BaseTypeBinding NullBinding = new BaseTypeBinding(TypeIds.T_null, TypeConstants.NULL, new char[] {'N'}); //N stands for null even if it is never internally used //$NON-NLS-1$
+	final BaseTypeBinding VoidBinding = new BaseTypeBinding(TypeIds.T_void, TypeConstants.VOID, new char[] {'V'}); //$NON-NLS-1$
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
index 6ada2f8..1523121 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
@@ -10,12 +10,15 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
+import java.util.ArrayList;
+
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.env.IBinaryField;
 import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
 import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 
 /*
@@ -30,16 +33,72 @@
 */
 
 public final class BinaryTypeBinding extends ReferenceBinding {
-	// all of these fields are ONLY guaranteed to be initialized if accessed using their public accessor method
-	private ReferenceBinding superclass;
-	private ReferenceBinding enclosingType;
-	private ReferenceBinding[] superInterfaces;
-	private FieldBinding[] fields;
-	private MethodBinding[] methods;
-	private ReferenceBinding[] memberTypes;
 
-	// For the link with the principle structure
-	private LookupEnvironment environment;
+// all of these fields are ONLY guaranteed to be initialized if accessed using their public accessor method
+private ReferenceBinding superclass;
+private ReferenceBinding enclosingType;
+private ReferenceBinding[] superInterfaces;
+private FieldBinding[] fields;
+private MethodBinding[] methods;
+private ReferenceBinding[] memberTypes;
+protected TypeVariableBinding[] typeVariables;
+
+// For the link with the principle structure
+private LookupEnvironment environment;
+
+public static ReferenceBinding resolveType(ReferenceBinding type, LookupEnvironment environment, boolean convertGenericToRawType) {
+	if (type instanceof UnresolvedReferenceBinding)
+		return ((UnresolvedReferenceBinding) type).resolve(environment, convertGenericToRawType);
+	if (type.isParameterizedType())
+		return ((ParameterizedTypeBinding) type).resolve();
+	if (type.isWildcard())
+		return ((WildcardBinding) type).resolve();
+
+	if (convertGenericToRawType && type.isGenericType()) // raw reference to generic ?
+	    return environment.createRawType(type, type.enclosingType());
+	return type;
+}
+public static TypeBinding resolveType(TypeBinding type, LookupEnvironment environment, ParameterizedTypeBinding parameterizedType, int rank) {
+	switch (type.kind()) {
+		
+		case Binding.PARAMETERIZED_TYPE :
+			return ((ParameterizedTypeBinding) type).resolve();
+			
+		case Binding.WILDCARD_TYPE :
+			return ((WildcardBinding) type).resolve();
+			
+		case Binding.ARRAY_TYPE :
+			resolveType(((ArrayBinding) type).leafComponentType, environment, parameterizedType, rank);
+			break;
+			
+		case Binding.TYPE_PARAMETER :
+			((TypeVariableBinding) type).resolve(environment);
+			break;
+						
+		case Binding.GENERIC_TYPE :
+			if (parameterizedType == null) // raw reference to generic ?
+			    return environment.createRawType((ReferenceBinding) type, type.enclosingType());
+			break;
+			
+		default:			
+			if (type instanceof UnresolvedReferenceBinding)
+				return ((UnresolvedReferenceBinding) type).resolve(environment, parameterizedType == null);
+	}
+	return type;
+}
+// resolve hierarchy types in 2 steps by first resolving any UnresolvedTypes
+static ReferenceBinding resolveUnresolvedType(ReferenceBinding type, LookupEnvironment environment, boolean convertGenericToRawType) {
+	if (type instanceof UnresolvedReferenceBinding)
+		return ((UnresolvedReferenceBinding) type).resolve(environment, convertGenericToRawType);
+
+	if (type.isParameterizedType())
+		resolveUnresolvedType(((ParameterizedTypeBinding) type).type, environment, false); // still part of parameterized type ref
+	else if (type.isWildcard())
+		resolveType(((WildcardBinding) type).genericType, environment, null, 0);
+	return type;
+}
+
+
 public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType, LookupEnvironment environment) {
 	this.compoundName = CharOperation.splitOn('/', binaryType.getName());
 	computeId();
@@ -49,6 +108,11 @@
 	this.fPackage = packageBinding;
 	this.fileName = binaryType.getFileName();
 
+	char[] typeSignature = environment.options.sourceLevel >= ClassFileConstants.JDK1_5 ? binaryType.getGenericSignature() : null;
+	this.typeVariables = typeSignature != null && typeSignature.length > 0 && typeSignature[0] == '<'
+		? null // is initialized in cachePartsFrom (called from LookupEnvironment.createBinaryTypeFrom())... must set to null so isGenericType() answers true
+		: NoTypeVariables;
+
 	// source name must be one name without "$".
 	char[] possibleSourceName = this.compoundName[this.compoundName.length - 1];
 	int start = CharOperation.lastIndexOf('$', possibleSourceName) + 1;
@@ -60,7 +124,7 @@
 	}
 
 	this.modifiers = binaryType.getModifiers();
-	if (binaryType.isInterface())
+	if (binaryType.getKind() == IGenericType.INTERFACE_DECL)
 		this.modifiers |= AccInterface;
 		
 	if (binaryType.isAnonymous()) {
@@ -108,28 +172,85 @@
 	return availableMethods;
 }
 
+public int kind() {
+	if (this.typeVariables != NoTypeVariables) return Binding.GENERIC_TYPE;
+	return Binding.TYPE;
+}	
+
 void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
-	
 	// default initialization for super-interfaces early, in case some aborting compilation error occurs,
 	// and still want to use binaries passed that point (e.g. type hierarchy resolver, see bug 63748).
+	this.typeVariables = NoTypeVariables;
 	this.superInterfaces = NoSuperInterfaces;
-	
-	char[] superclassName = binaryType.getSuperclassName();
-	if (superclassName != null)
-		// attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested)
-		this.superclass = environment.getTypeFromConstantPoolName(superclassName, 0, -1);
 
+	// need enclosing type to access type variables
 	char[] enclosingTypeName = binaryType.getEnclosingTypeName();
 	if (enclosingTypeName != null) {
 		// attempt to find the enclosing type if it exists in the cache (otherwise - resolve it when requested)
-		this.enclosingType = environment.getTypeFromConstantPoolName(enclosingTypeName, 0, -1);
+		this.enclosingType = environment.getTypeFromConstantPoolName(enclosingTypeName, 0, -1, true); // pretend parameterized to avoid raw
 		this.tagBits |= MemberTypeMask;   // must be a member type not a top-level or local type
+		this.tagBits |= 	HasUnresolvedEnclosingType;
 		if (this.enclosingType().isStrictfp())
 			this.modifiers |= AccStrictfp;
 		if (this.enclosingType().isDeprecated())
 			this.modifiers |= AccDeprecatedImplicitly;
 	}
 
+	long sourceLevel = environment.options.sourceLevel;
+	char[] typeSignature = null;
+	if (sourceLevel >= ClassFileConstants.JDK1_5) {
+		typeSignature = binaryType.getGenericSignature();
+		this.tagBits |= binaryType.getTagBits();
+	}
+	if (typeSignature == null) {
+		char[] superclassName = binaryType.getSuperclassName();
+		if (superclassName != null) {
+			// attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested)
+			this.superclass = environment.getTypeFromConstantPoolName(superclassName, 0, -1, false);
+			this.tagBits |= 	HasUnresolvedSuperclass;
+		}
+
+		this.superInterfaces = NoSuperInterfaces;
+		char[][] interfaceNames = binaryType.getInterfaceNames();
+		if (interfaceNames != null) {
+			int size = interfaceNames.length;
+			if (size > 0) {
+				this.superInterfaces = new ReferenceBinding[size];
+				for (int i = 0; i < size; i++)
+					// attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
+					this.superInterfaces[i] = environment.getTypeFromConstantPoolName(interfaceNames[i], 0, -1, false);
+				this.tagBits |= 	HasUnresolvedSuperinterfaces;
+			}
+		}
+	} else {
+		// ClassSignature = ParameterPart(optional) super_TypeSignature interface_signature
+		SignatureWrapper wrapper = new SignatureWrapper(typeSignature);
+		if (wrapper.signature[wrapper.start] == '<') {
+			// ParameterPart = '<' ParameterSignature(s) '>'
+			wrapper.start++; // skip '<'
+			this.typeVariables = createTypeVariables(wrapper, this);
+			wrapper.start++; // skip '>'
+			this.tagBits |=  HasUnresolvedTypeVariables;
+			this.modifiers |= AccGenericSignature;
+		}
+
+		// attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested)
+		this.superclass = (ReferenceBinding) environment.getTypeFromTypeSignature(wrapper, NoTypeVariables, this);
+		this.tagBits |= 	HasUnresolvedSuperclass;
+
+		this.superInterfaces = NoSuperInterfaces;
+		if (!wrapper.atEnd()) {
+			// attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
+			java.util.ArrayList types = new java.util.ArrayList(2);
+			do {
+				types.add(environment.getTypeFromTypeSignature(wrapper, NoTypeVariables, this));
+			} while (!wrapper.atEnd());
+			this.superInterfaces = new ReferenceBinding[types.size()];
+			types.toArray(this.superInterfaces);
+			this.tagBits |= 	HasUnresolvedSuperinterfaces;
+		}
+	}
+
 	this.memberTypes = NoMemberTypes;
 	IBinaryNestedType[] memberTypeStructures = binaryType.getMemberTypes();
 	if (memberTypeStructures != null) {
@@ -138,109 +259,174 @@
 			this.memberTypes = new ReferenceBinding[size];
 			for (int i = 0; i < size; i++)
 				// attempt to find each member type if it exists in the cache (otherwise - resolve it when requested)
-				this.memberTypes[i] = environment.getTypeFromConstantPoolName(memberTypeStructures[i].getName(), 0, -1);
+				this.memberTypes[i] = environment.getTypeFromConstantPoolName(memberTypeStructures[i].getName(), 0, -1, false);
+			this.tagBits |= 	HasUnresolvedMemberTypes;
 		}
 	}
 
-	char[][] interfaceNames = binaryType.getInterfaceNames();
-	if (interfaceNames != null) {
-		int size = interfaceNames.length;
-		if (size > 0) {
-			this.superInterfaces = new ReferenceBinding[size];
-			for (int i = 0; i < size; i++)
-				// attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
-				this.superInterfaces[i] = environment.getTypeFromConstantPoolName(interfaceNames[i], 0, -1);
-		}
-	}
 	if (needFieldsAndMethods) {
-		createFields(binaryType.getFields());
-		createMethods(binaryType.getMethods());
+		createFields(binaryType.getFields(), sourceLevel);
+		createMethods(binaryType.getMethods(), sourceLevel);
 	} else { // protect against incorrect use of the needFieldsAndMethods flag, see 48459
 		this.fields = NoFields;
 		this.methods = NoMethods;
 	}
 }
-private void createFields(IBinaryField[] iFields) {
+private void createFields(IBinaryField[] iFields, long sourceLevel) {
 	this.fields = NoFields;
 	if (iFields != null) {
 		int size = iFields.length;
 		if (size > 0) {
 			this.fields = new FieldBinding[size];
+			boolean use15specifics = sourceLevel >= ClassFileConstants.JDK1_5;
 			for (int i = 0; i < size; i++) {
-				IBinaryField field = iFields[i];
-				this.fields[i] =
+				IBinaryField binaryField = iFields[i];
+				char[] fieldSignature = use15specifics ? binaryField.getGenericSignature() : null;
+				TypeBinding type = fieldSignature == null
+					? environment.getTypeFromSignature(binaryField.getTypeName(), 0, -1, false, this)
+					: environment.getTypeFromTypeSignature(new SignatureWrapper(fieldSignature), NoTypeVariables, this);
+				FieldBinding field =
 					new FieldBinding(
-						field.getName(),
-						environment.getTypeFromSignature(field.getTypeName(), 0, -1),
-						field.getModifiers() | AccUnresolved,
+						binaryField.getName(),
+						type,
+						binaryField.getModifiers() | AccUnresolved,
 						this,
-						field.getConstant());
+						binaryField.getConstant());
+				field.id = i; // ordinal
+				if (use15specifics) {
+					field.tagBits |= binaryField.getTagBits();
+				}
+				this.fields[i] = field;
+
 			}
 		}
 	}
 }
-private MethodBinding createMethod(IBinaryMethod method) {
+private MethodBinding createMethod(IBinaryMethod method, long sourceLevel) {
 	int methodModifiers = method.getModifiers() | AccUnresolved;
-
+	if (sourceLevel < ClassFileConstants.JDK1_5)
+		methodModifiers &= ~AccVarargs; // vararg methods are not recognized until 1.5
 	ReferenceBinding[] exceptions = NoExceptions;
-	char[][] exceptionTypes = method.getExceptionTypeNames();
-	if (exceptionTypes != null) {
-		int size = exceptionTypes.length;
-		if (size > 0) {
-			exceptions = new ReferenceBinding[size];
-			for (int i = 0; i < size; i++)
-				exceptions[i] = environment.getTypeFromConstantPoolName(exceptionTypes[i], 0, -1);
-		}
-	}
-
 	TypeBinding[] parameters = NoParameters;
-	char[] methodSignature = method.getMethodDescriptor();   // of the form (I[Ljava/jang/String;)V
-	int numOfParams = 0;
-	char nextChar;
-	int index = 0;   // first character is always '(' so skip it
-	while ((nextChar = methodSignature[++index]) != ')') {
-		if (nextChar != '[') {
-			numOfParams++;
-			if (nextChar == 'L')
-				while ((nextChar = methodSignature[++index]) != ';'){/*empty*/}
+	TypeVariableBinding[] typeVars = NoTypeVariables;
+	TypeBinding returnType = null;
+
+	final boolean use15specifics = sourceLevel >= ClassFileConstants.JDK1_5;
+	char[] methodSignature = use15specifics ? method.getGenericSignature() : null;
+	if (methodSignature == null) { // no generics
+		char[] methodDescriptor = method.getMethodDescriptor();   // of the form (I[Ljava/jang/String;)V
+		int numOfParams = 0;
+		char nextChar;
+		int index = 0;   // first character is always '(' so skip it
+		while ((nextChar = methodDescriptor[++index]) != ')') {
+			if (nextChar != '[') {
+				numOfParams++;
+				if (nextChar == 'L')
+					while ((nextChar = methodDescriptor[++index]) != ';'){/*empty*/}
+			}
+		}
+
+		// Ignore synthetic argument for member types.
+		int startIndex = (method.isConstructor() && isMemberType() && !isStatic()) ? 1 : 0;
+		int size = numOfParams - startIndex;
+		if (size > 0) {
+			parameters = new TypeBinding[size];
+			index = 1;
+			int end = 0;   // first character is always '(' so skip it
+			for (int i = 0; i < numOfParams; i++) {
+				while ((nextChar = methodDescriptor[++end]) == '['){/*empty*/}
+				if (nextChar == 'L')
+					while ((nextChar = methodDescriptor[++end]) != ';'){/*empty*/}
+	
+				if (i >= startIndex)   // skip the synthetic arg if necessary
+					parameters[i - startIndex] = environment.getTypeFromSignature(methodDescriptor, index, end, false, this);
+				index = end + 1;
+			}
+		}
+
+		char[][] exceptionTypes = method.getExceptionTypeNames();
+		if (exceptionTypes != null) {
+			size = exceptionTypes.length;
+			if (size > 0) {
+				exceptions = new ReferenceBinding[size];
+				for (int i = 0; i < size; i++)
+					exceptions[i] = environment.getTypeFromConstantPoolName(exceptionTypes[i], 0, -1, false);
+			}
+		}
+
+		if (!method.isConstructor())
+			returnType = environment.getTypeFromSignature(methodDescriptor, index + 1, -1, false, this);   // index is currently pointing at the ')'
+	} else {
+		// MethodTypeSignature = ParameterPart(optional) '(' TypeSignatures ')' return_typeSignature ['^' TypeSignature (optional)]
+		SignatureWrapper wrapper = new SignatureWrapper(methodSignature);
+		if (wrapper.signature[wrapper.start] == '<') {
+			// <A::Ljava/lang/annotation/Annotation;>(Ljava/lang/Class<TA;>;)TA;
+			// ParameterPart = '<' ParameterSignature(s) '>'
+			wrapper.start++; // skip '<'
+			typeVars = createTypeVariables(wrapper, this);
+			wrapper.start++; // skip '>'
+		}
+
+		if (wrapper.signature[wrapper.start] == '(') {
+			wrapper.start++; // skip '('
+			if (wrapper.signature[wrapper.start] == ')') {
+				wrapper.start++; // skip ')'
+			} else {
+				java.util.ArrayList types = new java.util.ArrayList(2);
+				int startIndex = (method.isConstructor() && isMemberType() && !isStatic()) ? 1 : 0;
+				if (startIndex == 1)
+					environment.getTypeFromTypeSignature(wrapper, typeVars, this); // skip synthetic argument
+				while (wrapper.signature[wrapper.start] != ')') {
+					types.add(environment.getTypeFromTypeSignature(wrapper, typeVars, this));
+				}
+				wrapper.start++; // skip ')'
+				parameters = new TypeBinding[types.size()];
+				types.toArray(parameters);
+			}
+		}
+
+		if (!method.isConstructor())
+			returnType = environment.getTypeFromTypeSignature(wrapper, typeVars, this);
+
+		if (!wrapper.atEnd() && wrapper.signature[wrapper.start] == '^') {
+			// attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
+			java.util.ArrayList types = new java.util.ArrayList(2);
+			do {
+				wrapper.start++; // skip '^'
+				types.add(environment.getTypeFromTypeSignature(wrapper, typeVars, this));
+			} while (!wrapper.atEnd() && wrapper.signature[wrapper.start] == '^');
+			exceptions = new ReferenceBinding[types.size()];
+			types.toArray(exceptions);
+		} else { // get the exceptions the old way
+			char[][] exceptionTypes = method.getExceptionTypeNames();
+			if (exceptionTypes != null) {
+				int size = exceptionTypes.length;
+				if (size > 0) {
+					exceptions = new ReferenceBinding[size];
+					for (int i = 0; i < size; i++)
+						exceptions[i] = environment.getTypeFromConstantPoolName(exceptionTypes[i], 0, -1, false);
+				}
+			}
 		}
 	}
 
-	// Ignore synthetic argument for member types.
-	int startIndex = (method.isConstructor() && isMemberType() && !isStatic()) ? 1 : 0;
-	int size = numOfParams - startIndex;
-	if (size > 0) {
-		parameters = new TypeBinding[size];
-		index = 1;
-		int end = 0;   // first character is always '(' so skip it
-		for (int i = 0; i < numOfParams; i++) {
-			while ((nextChar = methodSignature[++end]) == '['){/*empty*/}
-			if (nextChar == 'L')
-				while ((nextChar = methodSignature[++end]) != ';'){/*empty*/}
-
-			if (i >= startIndex)   // skip the synthetic arg if necessary
-				parameters[i - startIndex] = environment.getTypeFromSignature(methodSignature, index, end);
-			index = end + 1;
-		}
+	MethodBinding result = method.isConstructor()
+		? new MethodBinding(methodModifiers, parameters, exceptions, this)
+		: new MethodBinding(methodModifiers, method.getSelector(), returnType, parameters, exceptions, this);
+	if (use15specifics) {
+		result.tagBits |= method.getTagBits();
 	}
-
-	MethodBinding binding = null;
-	if (method.isConstructor())
-		binding = new MethodBinding(methodModifiers, parameters, exceptions, this);
-	else
-		binding = new MethodBinding(
-			methodModifiers,
-			method.getSelector(),
-			environment.getTypeFromSignature(methodSignature, index + 1, -1),   // index is currently pointing at the ')'
-			parameters,
-			exceptions,
-			this);
-	return binding;
+	result.typeVariables = typeVars;
+	// fixup the declaring element of the type variable
+	for (int i = 0, length = typeVars.length; i < length; i++) {
+		typeVars[i].declaringElement = result;
+	}
+	return result;
 }
 /**
  * Create method bindings for binary type, filtering out <clinit> and synthetics
  */
-private void createMethods(IBinaryMethod[] iMethods) {
+private void createMethods(IBinaryMethod[] iMethods, long sourceLevel) {
 	int total = 0, initialTotal = 0, iClinit = -1;
 	int[] toSkip = null;
 	if (iMethods != null) {
@@ -270,25 +456,71 @@
 	this.methods = new MethodBinding[total];
 	if (total == initialTotal) {
 		for (int i = 0; i < initialTotal; i++)
-			this.methods[i] = createMethod(iMethods[i]);
+			this.methods[i] = createMethod(iMethods[i], sourceLevel);
 	} else {
 		for (int i = 0, index = 0; i < initialTotal; i++)
 			if (iClinit != i && (toSkip == null || toSkip[i] != -1))
-				this.methods[index++] = createMethod(iMethods[i]);
+				this.methods[index++] = createMethod(iMethods[i], sourceLevel);
 	}
 	modifiers |= AccUnresolved; // until methods() is sent
 }
+
+private TypeVariableBinding[] createTypeVariables(SignatureWrapper wrapper, Binding declaringElement) {
+	// detect all type variables first
+	char[] typeSignature = wrapper.signature;
+	int depth = 0, length = typeSignature.length;
+	int rank = 0;
+	ArrayList variables = new ArrayList(1);
+	depth = 0;
+	boolean pendingVariable = true;
+	createVariables: {
+		for (int i = 1; i < length; i++) {
+			switch(typeSignature[i]) {
+				case '<' : 
+					depth++;
+					break;
+				case '>' : 
+					if (--depth < 0)
+						break createVariables;
+					break;
+				case ';' :
+					if ((depth == 0) && (i +1 < length) && (typeSignature[i+1] != ':'))
+						pendingVariable = true;
+					break;
+				default:
+					if (pendingVariable) {
+						pendingVariable = false;
+						int colon = CharOperation.indexOf(':', typeSignature, i);
+						char[] variableName = CharOperation.subarray(typeSignature, i, colon);
+						variables.add(new TypeVariableBinding(variableName, declaringElement, rank++));
+					}
+			}
+		}
+	}
+	// initialize type variable bounds - may refer to forward variables
+	TypeVariableBinding[] result;
+	variables.toArray(result = new TypeVariableBinding[rank]);
+	for (int i = 0; i < rank; i++) {
+		initializeTypeVariable(result[i], result, wrapper);
+	}
+	return result;
+}
+
 /* Answer the receiver's enclosing type... null if the receiver is a top level type.
 *
 * NOTE: enclosingType of a binary type is resolved when needed
 */
 
 public ReferenceBinding enclosingType() {
-	if (enclosingType == null)
-		return null;
-	if (enclosingType instanceof UnresolvedReferenceBinding)
-		enclosingType = ((UnresolvedReferenceBinding) enclosingType).resolve(environment);
-	return enclosingType;
+	if ((this.tagBits & HasUnresolvedEnclosingType) == 0)
+		return this.enclosingType;
+
+	this.enclosingType = resolveUnresolvedType(this.enclosingType, this.environment, false); // no raw conversion for now
+	this.tagBits &= ~HasUnresolvedEnclosingType;
+
+	// finish resolving the type
+	this.enclosingType = resolveType(this.enclosingType, this.environment, false);
+	return this.enclosingType;
 }
 // NOTE: the type of each field of a binary type is resolved when needed
 
@@ -297,13 +529,13 @@
 		resolveTypeFor(fields[i]);
 	return fields;
 }
-// NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
 
+// NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
 public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
 	int argCount = argumentTypes.length;
 	nextMethod : for (int m = methods.length; --m >= 0;) {
 		MethodBinding method = methods[m];
-		if (method.selector == ConstructorDeclaration.ConstantPoolName && method.parameters.length == argCount) {
+		if (method.selector == TypeConstants.INIT && method.parameters.length == argCount) {
 			resolveTypesFor(method);
 			TypeBinding[] toMatch = method.parameters;
 			for (int p = 0; p < argCount; p++)
@@ -317,7 +549,8 @@
 // NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
 // searches up the hierarchy as long as no potential (but not exact) match was found.
 
-public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes) {
+public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
+	// sender from refScope calls recordTypeReference(this)
 	int argCount = argumentTypes.length;
 	int selectorLength = selector.length;
 	boolean foundNothing = true;
@@ -338,10 +571,15 @@
 
 	if (foundNothing) {
 		if (isInterface()) {
-			 if (superInterfaces.length == 1)
-				return superInterfaces[0].getExactMethod(selector, argumentTypes);
+			 if (superInterfaces.length == 1) {
+				if (refScope != null)
+					refScope.recordTypeReference(superInterfaces[0]);
+				return superInterfaces[0].getExactMethod(selector, argumentTypes, refScope);
+			 }
 		} else if (superclass != null) {
-			return superclass.getExactMethod(selector, argumentTypes);
+			if (refScope != null)
+				refScope.recordTypeReference(superclass);
+			return superclass.getExactMethod(selector, argumentTypes, refScope);
 		}
 	}
 	return null;
@@ -368,7 +606,7 @@
 			int prefixLength = this.compoundName[this.compoundName.length - 1].length + 1; // enclosing$
 			if (name.length == (prefixLength + typeName.length)) // enclosing $ typeName
 				if (CharOperation.fragmentEquals(typeName, name, prefixLength, true)) // only check trailing portion
-					return this.memberTypes[i] = ((UnresolvedReferenceBinding) memberType).resolve(environment);
+					return this.memberTypes[i] = resolveType(memberType, this.environment, false); // no raw conversion for now
 	    } else if (CharOperation.equals(typeName, memberType.sourceName)) {
 	        return memberType;
 	    }
@@ -408,11 +646,81 @@
 }
 // NOTE: member types of binary types are resolved when needed
 
+public TypeVariableBinding getTypeVariable(char[] variableName) {
+	TypeVariableBinding variable = super.getTypeVariable(variableName);
+	variable.resolve(this.environment);
+	return variable;
+}
+private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBinding[] existingVariables, SignatureWrapper wrapper) {
+	// ParameterSignature = Identifier ':' TypeSignature
+	//   or Identifier ':' TypeSignature(optional) InterfaceBound(s)
+	// InterfaceBound = ':' TypeSignature
+	int colon = CharOperation.indexOf(':', wrapper.signature, wrapper.start);
+	wrapper.start = colon + 1; // skip name + ':'
+	ReferenceBinding type, firstBound = null;
+	if (wrapper.signature[wrapper.start] == ':') {
+		type = environment.getType(JAVA_LANG_OBJECT);
+	} else {
+		type = (ReferenceBinding) environment.getTypeFromTypeSignature(wrapper, existingVariables, this);
+		firstBound = type;
+	}
+
+	// variable is visible to its bounds
+	variable.modifiers |= AccUnresolved;
+	variable.superclass = type;
+
+	ReferenceBinding[] bounds = null;
+	if (wrapper.signature[wrapper.start] == ':') {
+		java.util.ArrayList types = new java.util.ArrayList(2);
+		do {
+			wrapper.start++; // skip ':'
+			types.add(environment.getTypeFromTypeSignature(wrapper, existingVariables, this));
+		} while (wrapper.signature[wrapper.start] == ':');
+		bounds = new ReferenceBinding[types.size()];
+		types.toArray(bounds);
+	}
+
+	variable.superInterfaces = bounds == null ? NoSuperInterfaces : bounds;
+	if (firstBound == null) {
+		firstBound = variable.superInterfaces.length == 0 ? null : variable.superInterfaces[0];
+		variable.modifiers |= AccInterface;
+	}
+	variable.firstBound = firstBound;
+}
+/**
+ * Returns true if a type is identical to another one,
+ * or for generic types, true if compared to its raw type.
+ */
+public boolean isEquivalentTo(TypeBinding otherType) {
+	
+    if (this == otherType) return true;
+    if (otherType == null) return false;
+    switch(otherType.kind()) {
+
+    	case Binding.WILDCARD_TYPE :
+			return ((WildcardBinding) otherType).boundCheck(this);
+
+		case Binding.RAW_TYPE :
+			return otherType.erasure() == this;
+    }
+	return false;
+}
+public boolean isGenericType() {
+    return this.typeVariables != NoTypeVariables;
+}
+// NOTE: member types of binary types are resolved when needed
+
 public ReferenceBinding[] memberTypes() {
-	for (int i = memberTypes.length; --i >= 0;)
-		if (memberTypes[i] instanceof UnresolvedReferenceBinding)
-			memberTypes[i] = ((UnresolvedReferenceBinding) memberTypes[i]).resolve(environment);
-	return memberTypes;
+ 	if ((this.tagBits & HasUnresolvedMemberTypes) == 0)
+		return this.memberTypes;
+
+	for (int i = this.memberTypes.length; --i >= 0;)
+		this.memberTypes[i] = resolveUnresolvedType(this.memberTypes[i], this.environment, false); // no raw conversion for now
+	this.tagBits &= ~HasUnresolvedMemberTypes;
+
+	for (int i = this.memberTypes.length; --i >= 0;)
+		this.memberTypes[i] = resolveType(this.memberTypes[i], this.environment, false); // no raw conversion for now
+	return this.memberTypes;
 }
 // NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
 
@@ -422,62 +730,71 @@
 
 	for (int i = methods.length; --i >= 0;)
 		resolveTypesFor(methods[i]);
-	modifiers ^= AccUnresolved;
+	modifiers &= ~AccUnresolved;
 	return methods;
 }
-TypeBinding resolveType(TypeBinding type) {
-	if (type instanceof UnresolvedReferenceBinding)
-		return ((UnresolvedReferenceBinding) type).resolve(environment);
-	if (type instanceof ArrayBinding) {
-		ArrayBinding array = (ArrayBinding) type;
-		if (array.leafComponentType instanceof UnresolvedReferenceBinding)
-			array.leafComponentType = ((UnresolvedReferenceBinding) array.leafComponentType).resolve(environment);
-	}
-	return type;
-}
 private FieldBinding resolveTypeFor(FieldBinding field) {
-	if ((field.modifiers & AccUnresolved) != 0) {
-		field.type = resolveType(field.type);
-		field.modifiers ^= AccUnresolved;
-	}
+	if ((field.modifiers & AccUnresolved) == 0)
+		return field;
+
+	field.type = resolveType(field.type, this.environment, null, 0);
+	field.modifiers &= ~AccUnresolved;
 	return field;
 }
-private MethodBinding resolveTypesFor(MethodBinding method) {
+MethodBinding resolveTypesFor(MethodBinding method) {
 	if ((method.modifiers & AccUnresolved) == 0)
 		return method;
 
 	if (!method.isConstructor())
-		method.returnType = resolveType(method.returnType);
+		method.returnType = resolveType(method.returnType, this.environment, null, 0);
 	for (int i = method.parameters.length; --i >= 0;)
-		method.parameters[i] = resolveType(method.parameters[i]);
+		method.parameters[i] = resolveType(method.parameters[i], this.environment, null, 0);
 	for (int i = method.thrownExceptions.length; --i >= 0;)
-		if (method.thrownExceptions[i] instanceof UnresolvedReferenceBinding)
-			method.thrownExceptions[i] = ((UnresolvedReferenceBinding) method.thrownExceptions[i]).resolve(environment);
-	method.modifiers ^= AccUnresolved;
+		method.thrownExceptions[i] = resolveType(method.thrownExceptions[i], this.environment, true);
+	for (int i = method.typeVariables.length; --i >= 0;)
+		method.typeVariables[i].resolve(this.environment);
+	method.modifiers &= ~AccUnresolved;
 	return method;
 }
+
 /* Answer the receiver's superclass... null if the receiver is Object or an interface.
 *
 * NOTE: superclass of a binary type is resolved when needed
 */
 
 public ReferenceBinding superclass() {
-	if (superclass == null)
-		return null;
-	if (superclass instanceof UnresolvedReferenceBinding)
-		superclass = ((UnresolvedReferenceBinding) superclass).resolve(environment);
-	return superclass;
+	if ((this.tagBits & HasUnresolvedSuperclass) == 0)
+		return this.superclass;
+
+	this.superclass = resolveUnresolvedType(this.superclass, this.environment, true);
+	this.tagBits &= ~HasUnresolvedSuperclass;
+
+	// finish resolving the type
+	this.superclass = resolveType(this.superclass, this.environment, true);
+	return this.superclass;
 }
 // NOTE: superInterfaces of binary types are resolved when needed
 
 public ReferenceBinding[] superInterfaces() {
-	for (int i = superInterfaces.length; --i >= 0;)
-		if (superInterfaces[i] instanceof UnresolvedReferenceBinding)
-			superInterfaces[i] = ((UnresolvedReferenceBinding) superInterfaces[i]).resolve(environment);
-	return superInterfaces;
+	if ((this.tagBits & HasUnresolvedSuperinterfaces) == 0)
+		return this.superInterfaces;
+
+	for (int i = this.superInterfaces.length; --i >= 0;)
+		this.superInterfaces[i] = resolveUnresolvedType(this.superInterfaces[i], this.environment, true);
+	this.tagBits &= ~HasUnresolvedSuperinterfaces;
+
+	for (int i = this.superInterfaces.length; --i >= 0;)
+		this.superInterfaces[i] = resolveType(this.superInterfaces[i], this.environment, true);
+	return this.superInterfaces;
 }
-MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types
-	return methods;
+public TypeVariableBinding[] typeVariables() {
+ 	if ((this.tagBits & HasUnresolvedTypeVariables) == 0)
+		return this.typeVariables;
+
+ 	for (int i = this.typeVariables.length; --i >= 0;)
+		this.typeVariables[i].resolve(this.environment);
+	this.tagBits &= ~HasUnresolvedTypeVariables;
+	return this.typeVariables;
 }
 public String toString() {
 	String s = ""; //$NON-NLS-1$
@@ -547,4 +864,7 @@
 	s += "\n\n\n"; //$NON-NLS-1$
 	return s;
 }
+MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types
+	return methods;
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
index d6225aa..45e7a6f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
@@ -10,18 +10,53 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
-public abstract class Binding implements BindingIds, CompilerModifiers, ProblemReasons {
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+
+public abstract class Binding implements CompilerModifiers, ProblemReasons {
+
+	// binding kinds
+	public static final int FIELD = ASTNode.Bit1;
+	public static final int LOCAL = ASTNode.Bit2;
+	public static final int VARIABLE = FIELD | LOCAL;
+	public static final int TYPE = ASTNode.Bit3;
+	public static final int METHOD = ASTNode.Bit4;
+	public static final int PACKAGE = ASTNode.Bit5;
+	public static final int IMPORT = ASTNode.Bit6;
+	public static final int ARRAY_TYPE = TYPE | ASTNode.Bit7;
+	public static final int PARAMETERIZED_TYPE = TYPE | ASTNode.Bit8;
+	public static final int WILDCARD_TYPE = TYPE | ASTNode.Bit9;
+	public static final int RAW_TYPE = TYPE | ASTNode.Bit10;
+	public static final int GENERIC_TYPE = TYPE | ASTNode.Bit11;
+	public static final int TYPE_PARAMETER = TYPE | ASTNode.Bit12;
+	public static final int ANNOTATION_BINDING = TYPE | ASTNode.Bit13; // for annotation refs
+
 	/* API
 	* Answer the receiver's binding type from Binding.BindingID.
 	*
 	* Note: Do NOT expect this to be used very often... only in switch statements with
 	* more than 2 possible choices.
 	*/
-	public abstract int bindingType();
+	public abstract int kind();
+	/*
+	 * Computes a key that uniquely identifies this binding.
+	 * Returns null if binding is not a TypeBinding, a MethodBinding, a FieldBinding or a PackageBinding.
+	 */
+	public char[] computeUniqueKey() {
+		return null;
+	}
+	
+	/**
+	 * Compute the tagbits for standard annotations. For source types, these could require
+	 * lazily resolving corresponding annotation nodes, in case of forward references.
+	 * @see org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding#getAnnotationTagBits()
+	 */
+	public long getAnnotationTagBits() {
+		return 0;
+	}
+
 	/* API
 	* Answer true if the receiver is not a problem binding
 	*/
-	
 	public final boolean isValidBinding() {
 		return problemId() == NoError;
 	}
@@ -29,14 +64,13 @@
 	* Answer the problem id associated with the receiver.
 	* NoError if the receiver is a valid binding.
 	*/
-	
+	// TODO (philippe) should rename into problemReason()
 	public int problemId() {
 		return NoError;
 	}
 	/* Answer a printable representation of the receiver.
 	*/
 	public abstract char[] readableName();
-
 	/* Shorter printable representation of the receiver (no qualified type)
 	 */	
 	public char[] shortReadableName(){
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
index f0f9451..50a15c7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
@@ -14,7 +14,6 @@
 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 {
@@ -223,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.constant == Constant.NotAConstant));
+				boolean generateCurrentLocalVar = (local.useFlag == LocalVariableBinding.USED && !local.isConstantValue());
 					
 				// do not report fake used variable
 				if (local.useFlag == LocalVariableBinding.UNUSED
@@ -319,7 +318,7 @@
 	 */
 	public final ReferenceBinding findLocalType(char[] name) {
 
-	    long compliance = environment().options.complianceLevel;
+		long compliance = environment().options.complianceLevel;
 		for (int i = 0, length = subscopeCount; i < length; i++) {
 			if (subscopes[i] instanceof ClassScope) {
 				LocalTypeBinding sourceType = (LocalTypeBinding)((ClassScope) subscopes[i]).referenceContext.binding;
@@ -377,10 +376,11 @@
 	 */
 	public Binding getBinding(char[][] compoundName, int mask, InvocationSite invocationSite, boolean needResolve) {
 
-		Binding binding = getBinding(compoundName[0], mask | TYPE | PACKAGE, invocationSite, needResolve);
+		Binding binding = getBinding(compoundName[0], mask | Binding.TYPE | Binding.PACKAGE, invocationSite, needResolve);
 		invocationSite.setFieldIndex(1);
 		if (binding instanceof VariableBinding) return binding;
-		compilationUnitScope().recordSimpleReference(compoundName[0]);
+		CompilationUnitScope unitScope = compilationUnitScope();
+		unitScope.recordSimpleReference(compoundName[0]);
 		if (!binding.isValidBinding()) return binding;
 
 		int length = compoundName.length;
@@ -388,7 +388,7 @@
 		foundType : if (binding instanceof PackageBinding) {
 			PackageBinding packageBinding = (PackageBinding) binding;
 			while (currentIndex < length) {
-				compilationUnitScope().recordReference(packageBinding.compoundName, compoundName[currentIndex]);
+				unitScope.recordReference(packageBinding.compoundName, compoundName[currentIndex]);
 				binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
 				invocationSite.setFieldIndex(currentIndex);
 				if (binding == null) {
@@ -429,7 +429,7 @@
 			char[] nextName = compoundName[currentIndex++];
 			invocationSite.setFieldIndex(currentIndex);
 			invocationSite.setActualReceiverType(typeBinding);
-			if ((mask & FIELD) != 0 && (binding = findField(typeBinding, nextName, invocationSite, true /*resolve*/)) != null) {
+			if ((mask & Binding.FIELD) != 0 && (binding = findField(typeBinding, nextName, invocationSite, true /*resolve*/)) != null) {
 				if (!binding.isValidBinding())
 					return new ProblemFieldBinding(
 						((FieldBinding) binding).declaringClass,
@@ -438,7 +438,7 @@
 				break; // binding is now a field
 			}
 			if ((binding = findMemberType(nextName, typeBinding)) == null) {
-				if ((mask & FIELD) != 0) {
+				if ((mask & Binding.FIELD) != 0) {
 					return new ProblemBinding(
 						CharOperation.subarray(compoundName, 0, currentIndex),
 						typeBinding,
@@ -454,7 +454,7 @@
 					CharOperation.subarray(compoundName, 0, currentIndex),
 					binding.problemId());
 		}
-		if ((mask & FIELD) != 0 && (binding instanceof FieldBinding)) {
+		if ((mask & Binding.FIELD) != 0 && (binding instanceof FieldBinding)) {
 			// was looking for a field and found a field
 			FieldBinding field = (FieldBinding) binding;
 			if (!field.isStatic())
@@ -464,7 +464,7 @@
 					NonStaticReferenceInStaticContext);
 			return binding;
 		}
-		if ((mask & TYPE) != 0 && (binding instanceof ReferenceBinding)) {
+		if ((mask & Binding.TYPE) != 0 && (binding instanceof ReferenceBinding)) {
 			// was looking for a type and found a type
 			return binding;
 		}
@@ -484,7 +484,7 @@
 		Binding binding =
 			getBinding(
 				compoundName[currentIndex++],
-				VARIABLE | TYPE | PACKAGE,
+				Binding.VARIABLE | Binding.TYPE | Binding.PACKAGE,
 				invocationSite, 
 				true /*resolve*/);
 		if (!binding.isValidBinding())
@@ -638,7 +638,7 @@
 
 		// use 'this' if possible
 		if (!currentMethodScope.isConstructorCall && !currentMethodScope.isStatic) {
-			if (sourceType == targetEnclosingType || (!onlyExactMatch && targetEnclosingType.isSuperclassOf(sourceType))) {
+			if (sourceType == targetEnclosingType || (!onlyExactMatch && sourceType.findSuperTypeErasingTo(targetEnclosingType) != null)) {
 				return EmulationPathToImplicitThis; // implicit this is good enough
 			}
 		}
@@ -658,7 +658,7 @@
 				// reject allocation and super constructor call
 				if (ignoreEnclosingArgInConstructorCall 
 						&& currentMethodScope.isConstructorCall 
-						&& (sourceType == targetEnclosingType || (!onlyExactMatch && targetEnclosingType.isSuperclassOf(sourceType)))) {
+						&& (sourceType == targetEnclosingType || (!onlyExactMatch && sourceType.findSuperTypeErasingTo(targetEnclosingType) != null))) {
 					return NoEnclosingInstanceInConstructorCall;
 				}
 				return new Object[] { syntheticArg };
@@ -695,7 +695,7 @@
 
 				//done?
 				if (currentType == targetEnclosingType
-					|| (!onlyExactMatch && targetEnclosingType.isSuperclassOf(currentType)))	break;
+					|| (!onlyExactMatch && currentType.findSuperTypeErasingTo(targetEnclosingType) != null))	break;
 
 				if (currentMethodScope != null) {
 					currentMethodScope = currentMethodScope.enclosingMethodScope();
@@ -719,7 +719,7 @@
 				currentType = currentEnclosingType;
 			}
 			if (currentType == targetEnclosingType
-				|| (!onlyExactMatch && targetEnclosingType.isSuperclassOf(currentType))) {
+				|| (!onlyExactMatch && currentType.findSuperTypeErasingTo(targetEnclosingType) != null)) {
 				return path;
 			}
 		}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
index 575119c..82bda2d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
@@ -11,18 +11,26 @@
 package org.eclipse.jdt.internal.compiler.lookup;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.Clinit;
+import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
 
 public class ClassScope extends Scope {
 	public TypeDeclaration referenceContext;
-	
+	private 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 ClassScope(Scope parent, TypeDeclaration context) {
 		super(CLASS_SCOPE, parent);
 		this.referenceContext = context;
@@ -47,18 +55,31 @@
 	}
 	
 	private void buildFields() {
+		boolean hierarchyIsInconsistent = referenceContext.binding.isHierarchyInconsistent();
 		if (referenceContext.fields == null) {
-			referenceContext.binding.fields = NoFields;
+			if (hierarchyIsInconsistent) { // 72468
+				referenceContext.binding.fields = new FieldBinding[1];
+				referenceContext.binding.fields[0] =
+					new FieldBinding(IncompleteHierarchy, IntBinding, AccPrivate, referenceContext.binding, null);
+			} else {
+				referenceContext.binding.fields = NoFields;
+			}
 			return;
 		}
 		// count the number of fields vs. initializers
 		FieldDeclaration[] fields = referenceContext.fields;
 		int size = fields.length;
 		int count = 0;
-		for (int i = 0; i < size; i++)
-			if (fields[i].isField())
-				count++;
+		for (int i = 0; i < size; i++) {
+			switch (fields[i].getKind()) {
+				case AbstractVariableDeclaration.FIELD:
+				case AbstractVariableDeclaration.ENUM_CONSTANT:
+					count++;
+			}
+		}
 
+		if (hierarchyIsInconsistent)
+			count++;
 		// iterate the field declarations to create the bindings, lose all duplicates
 		FieldBinding[] fieldBindings = new FieldBinding[count];
 		HashtableOfObject knownFieldNames = new HashtableOfObject(count);
@@ -66,7 +87,7 @@
 		count = 0;
 		for (int i = 0; i < size; i++) {
 			FieldDeclaration field = fields[i];
-			if (!field.isField()) {
+			if (field.getKind() == AbstractVariableDeclaration.INITIALIZER) {
 				if (referenceContext.binding.isInterface())
 					problemReporter().interfaceCannotHaveInitializers(referenceContext.binding, field);
 			} else {
@@ -100,7 +121,7 @@
 		}
 		// remove duplicate fields
 		if (duplicate) {
-			FieldBinding[] newFieldBindings = new FieldBinding[knownFieldNames.size() - 1];
+			FieldBinding[] newFieldBindings = new FieldBinding[fieldBindings.length];
 			// we know we'll be removing at least 1 duplicate name
 			size = count;
 			count = 0;
@@ -111,6 +132,8 @@
 			}
 			fieldBindings = newFieldBindings;
 		}
+		if (hierarchyIsInconsistent)
+			fieldBindings[count++] = new FieldBinding(IncompleteHierarchy, IntBinding, AccPrivate, referenceContext.binding, null);
 
 		if (count != fieldBindings.length)
 			System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count);
@@ -144,7 +167,8 @@
 		LocalTypeBinding localType = new LocalTypeBinding(this, enclosingType, this.switchCase());
 		referenceContext.binding = localType;
 		checkAndSetModifiers();
-
+		buildTypeVariables();
+		
 		// Look at member types
 		ReferenceBinding[] memberTypeBindings = NoMemberTypes;
 		if (referenceContext.memberTypes != null) {
@@ -153,7 +177,7 @@
 			int count = 0;
 			nextMember : for (int i = 0; i < size; i++) {
 				TypeDeclaration memberContext = referenceContext.memberTypes[i];
-				if (memberContext.isInterface()) {
+				if (memberContext.kind() == IGenericType.INTERFACE_DECL) {
 					problemReporter().nestedClassCannotDeclareInterface(memberContext);
 					continue nextMember;
 				}
@@ -173,7 +197,6 @@
 						continue nextMember;
 					}
 				}
-
 				ClassScope memberScope = new ClassScope(this, referenceContext.memberTypes[i]);
 				LocalTypeBinding memberBinding = memberScope.buildLocalType(localType, packageBinding);
 				memberBinding.setAsMemberType();
@@ -196,68 +219,16 @@
 		referenceContext.binding.verifyMethods(environment().methodVerifier());
 	}
 	
-	private void buildMethods() {
-		if (referenceContext.methods == null) {
-			referenceContext.binding.methods = NoMethods;
-			return;
-		}
-
-		// iterate the method declarations to create the bindings
-		AbstractMethodDeclaration[] methods = referenceContext.methods;
-		int size = methods.length;
-		int clinitIndex = -1;
-		for (int i = 0; i < size; i++) {
-			if (methods[i] instanceof Clinit) {
-				clinitIndex = i;
-				break;
-			}
-		}
-		MethodBinding[] methodBindings = new MethodBinding[clinitIndex == -1 ? size : size - 1];
-
-		int count = 0;
-		for (int i = 0; i < size; i++) {
-			if (i != clinitIndex) {
-				MethodScope scope = new MethodScope(this, methods[i], false);
-				MethodBinding methodBinding = scope.createMethod(methods[i]);
-				if (methodBinding != null) // is null if binding could not be created
-					methodBindings[count++] = methodBinding;
-			}
-		}
-		if (count != methodBindings.length)
-			System.arraycopy(methodBindings, 0, methodBindings = new MethodBinding[count], 0, count);
-
-		referenceContext.binding.methods = methodBindings;
-		referenceContext.binding.modifiers |= AccUnresolved; // until methods() is sent
-	}
-	SourceTypeBinding buildType(SourceTypeBinding enclosingType, PackageBinding packageBinding) {
-		// provide the typeDeclaration with needed scopes
-		referenceContext.scope = this;
-		referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
-		referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
-
-		if (enclosingType == null) {
-			char[][] className = CharOperation.arrayConcat(packageBinding.compoundName, referenceContext.name);
-			referenceContext.binding = new SourceTypeBinding(className, packageBinding, this);
-		} else {
-			char[][] className = CharOperation.deepCopy(enclosingType.compoundName);
-			className[className.length - 1] =
-				CharOperation.concat(className[className.length - 1], referenceContext.name, '$');
-			referenceContext.binding = new MemberTypeBinding(className, this, enclosingType);
-		}
-
-		SourceTypeBinding sourceType = referenceContext.binding;
-		sourceType.fPackage.addType(sourceType);
-		checkAndSetModifiers();
-
-		// Look at member types
+	private void buildMemberTypes(AccessRestriction accessRestriction) {
+	    SourceTypeBinding sourceType = referenceContext.binding;
 		ReferenceBinding[] memberTypeBindings = NoMemberTypes;
 		if (referenceContext.memberTypes != null) {
-			int size = referenceContext.memberTypes.length;
-			memberTypeBindings = new ReferenceBinding[size];
+			int length = referenceContext.memberTypes.length;
+			memberTypeBindings = new ReferenceBinding[length];
 			int count = 0;
-			nextMember : for (int i = 0; i < size; i++) {
+			nextMember : for (int i = 0; i < length; i++) {
 				TypeDeclaration memberContext = referenceContext.memberTypes[i];
-				if (memberContext.isInterface()
+				if (memberContext.kind() == IGenericType.INTERFACE_DECL
 					&& sourceType.isNestedType()
 					&& sourceType.isClass()
 					&& !sourceType.isStatic()) {
@@ -282,15 +253,102 @@
 				}
 
 				ClassScope memberScope = new ClassScope(this, memberContext);
-				memberTypeBindings[count++] = memberScope.buildType(sourceType, packageBinding);
+				memberTypeBindings[count++] = memberScope.buildType(sourceType, sourceType.fPackage, accessRestriction);
 			}
-			if (count != size)
+			if (count != length)
 				System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
 		}
 		sourceType.memberTypes = memberTypeBindings;
+	}
+	
+	private void buildMethods() {
+		boolean isEnum = referenceContext.kind() == IGenericType.ENUM_DECL;
+		if (referenceContext.methods == null && !isEnum) {
+			referenceContext.binding.methods = NoMethods;
+			return;
+		}
+
+		// iterate the method declarations to create the bindings
+		AbstractMethodDeclaration[] methods = referenceContext.methods;
+		int size = methods == null ? 0 : methods.length;
+		// look for <clinit> method
+		int clinitIndex = -1;
+		for (int i = 0; i < size; i++) {
+			if (methods[i].isClinit()) {
+				clinitIndex = i;
+				break;
+			}
+		}
+
+		int count = isEnum ? 2 : 0; // reserve 2 slots for special enum methods: #values() and #valueOf(String)
+		MethodBinding[] methodBindings = new MethodBinding[(clinitIndex == -1 ? size : size - 1) + count];
+		// create special methods for enums
+		if (isEnum) {
+		    SourceTypeBinding sourceType = referenceContext.binding;
+			methodBindings[0] = sourceType.addSyntheticEnumMethod(TypeConstants.VALUES); // add <EnumType>[] values() 
+			methodBindings[1] = sourceType.addSyntheticEnumMethod(TypeConstants.VALUEOF); // add <EnumType> valueOf() 
+		}
+		// create bindings for source methods
+		for (int i = 0; i < size; i++) {
+			if (i != clinitIndex) {
+				MethodScope scope = new MethodScope(this, methods[i], false);
+				MethodBinding methodBinding = scope.createMethod(methods[i]);
+				if (methodBinding != null) // is null if binding could not be created
+					methodBindings[count++] = methodBinding;
+			}
+		}
+		if (count != methodBindings.length)
+			System.arraycopy(methodBindings, 0, methodBindings = new MethodBinding[count], 0, count);
+
+		referenceContext.binding.methods = methodBindings;
+		referenceContext.binding.modifiers |= AccUnresolved; // until methods() is sent
+	}
+	
+	SourceTypeBinding buildType(SourceTypeBinding enclosingType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+		// provide the typeDeclaration with needed scopes
+		referenceContext.scope = this;
+		referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
+		referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
+
+		if (enclosingType == null) {
+			char[][] className = CharOperation.arrayConcat(packageBinding.compoundName, referenceContext.name);
+			referenceContext.binding = new SourceTypeBinding(className, packageBinding, this);
+		} else {
+			char[][] className = CharOperation.deepCopy(enclosingType.compoundName);
+			className[className.length - 1] =
+				CharOperation.concat(className[className.length - 1], referenceContext.name, '$');
+			referenceContext.binding = new MemberTypeBinding(className, this, enclosingType);
+		}
+
+		SourceTypeBinding sourceType = referenceContext.binding;
+		environment().setAccessRestriction(sourceType, accessRestriction);		
+		sourceType.fPackage.addType(sourceType);
+		checkAndSetModifiers();
+		buildTypeVariables();
+		buildMemberTypes(accessRestriction);
 		return sourceType;
 	}
 	
+	private void buildTypeVariables() {
+	    
+	    SourceTypeBinding sourceType = referenceContext.binding;
+		TypeParameter[] typeParameters = referenceContext.typeParameters;
+		
+	    // do not construct type variables if source < 1.5
+		if (typeParameters == null || environment().options.sourceLevel < ClassFileConstants.JDK1_5) {
+		    sourceType.typeVariables = NoTypeVariables;
+		    return;
+		}
+		sourceType.typeVariables = NoTypeVariables; // safety
+
+		if (sourceType.id == T_JavaLangObject) { // handle the case of redefining java.lang.Object up front
+			problemReporter().objectCannotBeGeneric(referenceContext);
+			return; 
+		}
+		sourceType.typeVariables = createTypeVariables(typeParameters, sourceType);
+		sourceType.modifiers |= AccGenericSignature;
+	}
+	
 	private void checkAndSetModifiers() {
 		SourceTypeBinding sourceType = referenceContext.binding;
 		int modifiers = sourceType.modifiers;
@@ -306,11 +364,18 @@
 				modifiers |= AccStrictfp;
 			if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
 				modifiers |= AccDeprecatedImplicitly;
-			if (enclosingType.isInterface())
+			if ((enclosingType.modifiers & AccInterface) != 0)
 				modifiers |= AccPublic;
+			if (sourceType.isEnum())
+				modifiers |= AccStatic;
 		} else if (sourceType.isLocalType()) {
-			if (sourceType.isAnonymousType()) 
+			if (sourceType.isAnonymousType()) {
 			    modifiers |= AccFinal;
+			    // set AccEnum flag for anonymous body of enum constants
+			    if (referenceContext.allocation.type == null) {
+			    	modifiers |= AccEnum;
+			    }
+			}
 			Scope scope = this;
 			do {
 				switch (scope.kind) {
@@ -355,13 +420,18 @@
 		// after this point, tests on the 16 bits reserved.
 		int realModifiers = modifiers & AccJustFlag;
 
-		if ((realModifiers & AccInterface) != 0) {
+		if ((realModifiers & AccInterface) != 0) { // interface and annotation type
 			// detect abnormal cases for interfaces
 			if (isMemberType) {
 				int unexpectedModifiers =
-					~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccInterface | AccStrictfp);
-				if ((realModifiers & unexpectedModifiers) != 0)
-					problemReporter().illegalModifierForMemberInterface(sourceType);
+					~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccInterface | AccStrictfp | AccAnnotation);
+				if ((realModifiers & unexpectedModifiers) != 0) {
+					if ((realModifiers & AccAnnotation) != 0) {
+						problemReporter().illegalModifierForAnnotationMemberType(sourceType);
+					} else {
+						problemReporter().illegalModifierForMemberInterface(sourceType);
+					}
+				}
 				/*
 				} else if (sourceType.isLocalType()) { //interfaces cannot be defined inside a method
 					int unexpectedModifiers = ~(AccAbstract | AccInterface | AccStrictfp);
@@ -369,13 +439,38 @@
 						problemReporter().illegalModifierForLocalInterface(sourceType);
 				*/
 			} else {
-				int unexpectedModifiers = ~(AccPublic | AccAbstract | AccInterface | AccStrictfp);
-				if ((realModifiers & unexpectedModifiers) != 0)
-					problemReporter().illegalModifierForInterface(sourceType);
+				int unexpectedModifiers = ~(AccPublic | AccAbstract | AccInterface | AccStrictfp | AccAnnotation);
+				if ((realModifiers & unexpectedModifiers) != 0) {
+					if ((realModifiers & AccAnnotation) != 0) {
+						problemReporter().illegalModifierForAnnotationType(sourceType);
+					} else {
+						problemReporter().illegalModifierForInterface(sourceType);
+					}
+				}
 			}
 			modifiers |= AccAbstract;
+		} else if ((realModifiers & AccEnum) != 0) {
+			// detect abnormal cases for enums
+			if (isMemberType) { // includes member types defined inside local types
+				int unexpectedModifiers =
+					~(AccPublic | AccPrivate | AccProtected | AccStatic | AccStrictfp | AccEnum);
+				if ((realModifiers & unexpectedModifiers) != 0)
+					problemReporter().illegalModifierForMemberEnum(sourceType);
+			} else if (sourceType.isLocalType()) {
+				int unexpectedModifiers = ~(AccStrictfp | AccFinal | AccEnum); // add final since implicitly set for anonymous type
+				if ((realModifiers & unexpectedModifiers) != 0)
+					problemReporter().illegalModifierForLocalEnum(sourceType);
+			} else {
+				int unexpectedModifiers = ~(AccPublic | AccStrictfp | AccEnum);
+				if ((realModifiers & unexpectedModifiers) != 0)
+					problemReporter().illegalModifierForEnum(sourceType);
+			}
+			if ((referenceContext.bits & ASTNode.HasAbstractMethods) != 0) {
+				modifiers |= AccAbstract;
+			}
+			
 		} else {
-			// detect abnormal cases for types
+			// detect abnormal cases for classes
 			if (isMemberType) { // includes member types defined inside local types
 				int unexpectedModifiers =
 					~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccFinal | AccStrictfp);
@@ -404,9 +499,9 @@
 
 					// need to keep the less restrictive
 					if ((realModifiers & AccProtected) != 0)
-						modifiers ^= AccProtected;
+						modifiers &= ~AccProtected;
 					if ((realModifiers & AccPrivate) != 0)
-						modifiers ^= AccPrivate;
+						modifiers &= ~AccPrivate;
 				}
 			} else {
 				int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
@@ -416,13 +511,13 @@
 					// need to keep the less restrictive
 					if ((accessorBits & AccPublic) != 0) {
 						if ((accessorBits & AccProtected) != 0)
-							modifiers ^= AccProtected;
+							modifiers &= ~AccProtected;
 						if ((accessorBits & AccPrivate) != 0)
-							modifiers ^= AccPrivate;
+							modifiers &= ~AccPrivate;
 					}
 					if ((accessorBits & AccProtected) != 0)
 						if ((accessorBits & AccPrivate) != 0)
-							modifiers ^= AccPrivate;
+							modifiers &= ~AccPrivate;
 				}
 			}
 
@@ -452,16 +547,30 @@
 		if ((modifiers & AccAlternateModifierProblem) != 0)
 			problemReporter().duplicateModifierForField(fieldBinding.declaringClass, fieldDecl);
 
-		if (fieldBinding.declaringClass.isInterface()) {
+		if ((fieldBinding.declaringClass.modifiers  & AccInterface) != 0) {
 			int expectedValue = AccPublic | AccStatic | AccFinal;
 			// set the modifiers
 			modifiers |= expectedValue;
 
 			// and then check that they are the only ones
-			if ((modifiers & AccJustFlag) != expectedValue)
-				problemReporter().illegalModifierForInterfaceField(fieldBinding.declaringClass, fieldDecl);
+			if ((modifiers & AccJustFlag) != expectedValue) {
+				if ((fieldBinding.declaringClass.modifiers  & AccAnnotation) != 0) {
+					problemReporter().illegalModifierForAnnotationField(fieldDecl);
+				} else {
+					problemReporter().illegalModifierForInterfaceField(fieldDecl);
+				}
+			}
 			fieldBinding.modifiers = modifiers;
 			return;
+		} else if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+			// check that they are not modifiers in source
+			if ((modifiers & AccJustFlag) != 0)
+				problemReporter().illegalModifierForEnumConstant(fieldBinding.declaringClass, fieldDecl);
+		
+			// set the modifiers
+			int implicitValue = AccPublic | AccStatic | AccFinal | AccEnum;
+			fieldBinding.modifiers|= implicitValue;
+			return;
 		}
 
 		// after this point, tests on the 16 bits reserved.
@@ -480,13 +589,13 @@
 			// need to keep the less restrictive
 			if ((accessorBits & AccPublic) != 0) {
 				if ((accessorBits & AccProtected) != 0)
-					modifiers ^= AccProtected;
+					modifiers &= ~AccProtected;
 				if ((accessorBits & AccPrivate) != 0)
-					modifiers ^= AccPrivate;
+					modifiers &= ~AccPrivate;
 			}
 			if ((accessorBits & AccProtected) != 0)
 				if ((accessorBits & AccPrivate) != 0)
-					modifiers ^= AccPrivate;
+					modifiers &= ~AccPrivate;
 		}
 
 		if ((realModifiers & (AccFinal | AccVolatile)) == (AccFinal | AccVolatile))
@@ -499,81 +608,85 @@
 		}
 		fieldBinding.modifiers = modifiers;
 	}
-	
+
 	private void checkForInheritedMemberTypes(SourceTypeBinding sourceType) {
 		// search up the hierarchy of the sourceType to see if any superType defines a member type
 		// when no member types are defined, tag the sourceType & each superType with the HasNoMemberTypes bit
+		// assumes super types have already been checked & tagged
 		ReferenceBinding currentType = sourceType;
 		ReferenceBinding[][] interfacesToVisit = null;
 		int lastPosition = -1;
 		do {
-			if ((currentType.tagBits & HasNoMemberTypes) != 0)
-				break; // already know it has no inherited member types, can stop looking up
 			if (currentType.hasMemberTypes()) // avoid resolving member types eagerly
-				return; // has member types
+				return;
+
 			ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
 			if (itsInterfaces != NoSuperInterfaces) {
 				if (interfacesToVisit == null)
 					interfacesToVisit = new ReferenceBinding[5][];
 				if (++lastPosition == interfacesToVisit.length)
-					System.arraycopy(
-						interfacesToVisit,
-						0,
-						interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
-						0,
-						lastPosition);
+					System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
 				interfacesToVisit[lastPosition] = itsInterfaces;
 			}
-		} while ((currentType = currentType.superclass()) != null);
+		} while ((currentType = currentType.superclass()) != null && (currentType.tagBits & HasNoMemberTypes) == 0);
 
-		boolean hasMembers = false;
 		if (interfacesToVisit != null) {
-			done : for (int i = 0; i <= lastPosition; i++) {
+			// contains the interfaces between the sourceType and any superclass, which was tagged as having no member types
+			boolean needToTag = false;
+			for (int i = 0; i <= lastPosition; i++) {
 				ReferenceBinding[] interfaces = interfacesToVisit[i];
 				for (int j = 0, length = interfaces.length; j < length; j++) {
 					ReferenceBinding anInterface = interfaces[j];
-					if ((anInterface.tagBits & InterfaceVisited) == 0) { // if interface as not already been visited
-						anInterface.tagBits |= InterfaceVisited;
-						if ((anInterface.tagBits & HasNoMemberTypes) != 0)
-							continue; // already know it has no inherited member types
-						if (anInterface.memberTypes() != NoMemberTypes) {
-							hasMembers = true;
-							break done;
-						}
+					if ((anInterface.tagBits & HasNoMemberTypes) == 0) { // skip interface if it already knows it has no member types
+						if (anInterface.hasMemberTypes()) // avoid resolving member types eagerly
+							return;
 
+						needToTag = true;
 						ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
 						if (itsInterfaces != NoSuperInterfaces) {
 							if (++lastPosition == interfacesToVisit.length)
-								System.arraycopy(
-									interfacesToVisit,
-									0,
-									interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
-									0,
-									lastPosition);
+								System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
 							interfacesToVisit[lastPosition] = itsInterfaces;
 						}
 					}
 				}
 			}
 
-			for (int i = 0; i <= lastPosition; i++) {
-				ReferenceBinding[] interfaces = interfacesToVisit[i];
-				for (int j = 0, length = interfaces.length; j < length; j++) {
-					interfaces[j].tagBits &= ~InterfaceVisited;
-					if (!hasMembers)
+			if (needToTag) {
+				for (int i = 0; i <= lastPosition; i++) {
+					ReferenceBinding[] interfaces = interfacesToVisit[i];
+					for (int j = 0, length = interfaces.length; j < length; j++)
 						interfaces[j].tagBits |= HasNoMemberTypes;
 				}
 			}
 		}
 
-		if (!hasMembers) {
-			currentType = sourceType;
-			do {
-				currentType.tagBits |= HasNoMemberTypes;
-			} while ((currentType = currentType.superclass()) != null);
+		// tag the sourceType and all of its superclasses, unless they have already been tagged
+		currentType = sourceType;
+		do {
+			currentType.tagBits |= HasNoMemberTypes;
+		} while ((currentType = currentType.superclass()) != null && (currentType.tagBits & HasNoMemberTypes) == 0);
+	}
+	// Perform deferred bound checks for parameterized type references (only done after hierarchy is connected)
+	private void  checkParameterizedTypeBounds() {
+		TypeReference superclass = referenceContext.superclass;
+		if (superclass != null) {
+			superclass.checkBounds(this);
+		}
+		TypeReference[] superinterfaces = referenceContext.superInterfaces;
+		if (superinterfaces != null) {
+			for (int i = 0, length = superinterfaces.length; i < length; i++) {
+				superinterfaces[i].checkBounds(this);
+			}
+		}
+		TypeParameter[] typeParameters = referenceContext.typeParameters;
+		if (typeParameters != null) {
+			for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++) {
+				typeParameters[i].checkBounds(this);
+			}
 		}
 	}
-	
+
 	private void connectMemberTypes() {
 		SourceTypeBinding sourceType = referenceContext.binding;
 		if (sourceType.memberTypes != NoMemberTypes)
@@ -593,26 +706,32 @@
 	*/
 	private boolean connectSuperclass() {
 		SourceTypeBinding sourceType = referenceContext.binding;
-		if (sourceType.id == T_Object) { // handle the case of redefining java.lang.Object up front
+		if (sourceType.id == T_JavaLangObject) { // handle the case of redefining java.lang.Object up front
 			sourceType.superclass = null;
 			sourceType.superInterfaces = NoSuperInterfaces;
-			if (referenceContext.superclass != null || referenceContext.superInterfaces != null)
+			if (!sourceType.isClass())
+				problemReporter().objectMustBeClass(sourceType);
+			if (referenceContext.superclass != null || (referenceContext.superInterfaces != null && referenceContext.superInterfaces.length > 0))
 				problemReporter().objectCannotHaveSuperTypes(sourceType);
 			return true; // do not propagate Object's hierarchy problems down to every subtype
 		}
 		if (referenceContext.superclass == null) {
+			if (sourceType.isEnum() && environment().options.sourceLevel >= JDK1_5) // do not connect if source < 1.5 as enum already got flagged as syntax error
+				return connectEnumSuperclass();
 			sourceType.superclass = getJavaLangObject();
-			return !detectCycle(sourceType, sourceType.superclass, null);
+			return !detectHierarchyCycle(sourceType, sourceType.superclass, null);
 		}
-		ReferenceBinding superclass = findSupertype(referenceContext.superclass);
-		if (superclass != null) { // is null if a cycle was detected cycle
-			referenceContext.superclass.resolvedType = superclass; // hold onto the problem type
-			if (!superclass.isValidBinding()) {
-				problemReporter().invalidSuperclass(sourceType, referenceContext.superclass, superclass);
-			} else if (superclass.isInterface()) {
-				problemReporter().superclassMustBeAClass(sourceType, referenceContext.superclass, superclass);
+		TypeReference superclassRef = referenceContext.superclass;
+		ReferenceBinding superclass = findSupertype(superclassRef);
+		if (superclass != null) { // is null if a cycle was detected cycle or a problem
+			if (!superclass.isClass()) {
+				problemReporter().superclassMustBeAClass(sourceType, superclassRef, superclass);
 			} else if (superclass.isFinal()) {
-				problemReporter().classExtendFinalClass(sourceType, referenceContext.superclass, superclass);
+				problemReporter().classExtendFinalClass(sourceType, superclassRef, superclass);
+			} else if ((superclass.tagBits & TagBits.HasDirectWildcard) != 0) {
+				problemReporter().superTypeCannotUseWildcard(sourceType, superclassRef, superclass);
+			} else if (superclass.erasure().id == T_JavaLangEnum) {
+				problemReporter().cannotExtendEnum(sourceType, superclassRef, superclass);
 			} else {
 				// only want to reach here when no errors are reported
 				sourceType.superclass = superclass;
@@ -622,10 +741,36 @@
 		sourceType.tagBits |= HierarchyHasProblems;
 		sourceType.superclass = getJavaLangObject();
 		if ((sourceType.superclass.tagBits & BeginHierarchyCheck) == 0)
-			detectCycle(sourceType, sourceType.superclass, null);
+			detectHierarchyCycle(sourceType, sourceType.superclass, null);
 		return false; // reported some error against the source type
 	}
 
+	/**
+	 *  enum X (implicitly) extends Enum<X>
+	 */
+	private boolean connectEnumSuperclass() {
+		SourceTypeBinding sourceType = referenceContext.binding;
+		ReferenceBinding rootEnumType = getJavaLangEnum();
+		boolean foundCycle = detectHierarchyCycle(sourceType, rootEnumType, null);
+		// arity check for well-known Enum<E>
+		TypeVariableBinding[] refTypeVariables = rootEnumType.typeVariables();
+		if (refTypeVariables == NoTypeVariables) { // check generic
+			problemReporter().nonGenericTypeCannotBeParameterized(null, rootEnumType, new TypeBinding[]{ sourceType });
+			return false; // cannot reach here as AbortCompilation is thrown
+		} else if (1 != refTypeVariables.length) { // check arity
+			problemReporter().incorrectArityForParameterizedType(null, rootEnumType, new TypeBinding[]{ sourceType });
+			return false; // cannot reach here as AbortCompilation is thrown
+		}			
+		// check argument type compatibility
+		ParameterizedTypeBinding  superType = createParameterizedType(rootEnumType, new TypeBinding[]{ sourceType } , null);
+		sourceType.superclass = superType;
+		// bound check
+		if (!refTypeVariables[0].boundCheck(superType, sourceType)) {
+			problemReporter().typeMismatchError(rootEnumType, refTypeVariables[0], sourceType, null);
+		}
+		return !foundCycle;
+	}
+
 	/*
 		Our current belief based on available JCK 1.3 tests is:
 			inherited member types are visible as a potential superclass.
@@ -639,9 +784,16 @@
 	private boolean connectSuperInterfaces() {
 		SourceTypeBinding sourceType = referenceContext.binding;
 		sourceType.superInterfaces = NoSuperInterfaces;
-		if (referenceContext.superInterfaces == null)
+		if (referenceContext.superInterfaces == null) {
+			if (sourceType.isAnnotationType() && environment().options.sourceLevel >= JDK1_5) { // do not connect if source < 1.5 as annotation already got flagged as syntax error) {
+				ReferenceBinding annotationType = getJavaLangAnnotationAnnotation();
+				boolean foundCycle = detectHierarchyCycle(sourceType, annotationType, null);
+				sourceType.superInterfaces = new ReferenceBinding[] { annotationType };
+				return !foundCycle;
+			}
 			return true;
-		if (sourceType.id == T_Object) // already handled the case of redefining java.lang.Object
+		}
+		if (sourceType.id == T_JavaLangObject) // already handled the case of redefining java.lang.Object
 			return true;
 
 		boolean noProblems = true;
@@ -649,21 +801,14 @@
 		ReferenceBinding[] interfaceBindings = new ReferenceBinding[length];
 		int count = 0;
 		nextInterface : for (int i = 0; i < length; i++) {
-			ReferenceBinding superInterface = findSupertype(referenceContext.superInterfaces[i]);
+		    TypeReference superInterfaceRef = referenceContext.superInterfaces[i];
+			ReferenceBinding superInterface = findSupertype(superInterfaceRef);
 			if (superInterface == null) { // detected cycle
-				noProblems = false;
-				continue nextInterface;
-			}
-			referenceContext.superInterfaces[i].resolvedType = superInterface; // hold onto the problem type
-			if (!superInterface.isValidBinding()) {
-				problemReporter().invalidSuperinterface(
-					sourceType,
-					referenceContext.superInterfaces[i],
-					superInterface);
 				sourceType.tagBits |= HierarchyHasProblems;
 				noProblems = false;
 				continue nextInterface;
 			}
+			superInterfaceRef.resolvedType = superInterface; // hold onto the problem type
 			// Check for a duplicate interface once the name is resolved, otherwise we may be confused (ie : a.b.I and c.d.I)
 			for (int k = 0; k < count; k++) {
 				if (interfaceBindings[k] == superInterface) {
@@ -672,8 +817,26 @@
 					continue nextInterface;
 				}
 			}
-			if (superInterface.isClass()) {
-				problemReporter().superinterfaceMustBeAnInterface(sourceType, referenceContext, superInterface);
+			if (!superInterface.isInterface()) {
+				problemReporter().superinterfaceMustBeAnInterface(sourceType, superInterfaceRef, superInterface);
+				sourceType.tagBits |= HierarchyHasProblems;
+				noProblems = false;
+				continue nextInterface;
+			}
+			if ((superInterface.tagBits & TagBits.HasDirectWildcard) != 0) {
+				problemReporter().superTypeCannotUseWildcard(sourceType, superInterfaceRef, superInterface);
+				sourceType.tagBits |= HierarchyHasProblems;
+				noProblems = false;
+				continue nextInterface;
+			}
+			ReferenceBinding invalid = findAmbiguousInterface(superInterface, sourceType);
+			if (invalid != null) {
+				ReferenceBinding generic = null;
+				if (superInterface.isParameterizedType())
+					generic = ((ParameterizedTypeBinding) superInterface).type;
+				else if (invalid.isParameterizedType())
+					generic = ((ParameterizedTypeBinding) invalid).type;
+				problemReporter().superinterfacesCollide(generic, referenceContext, superInterface, invalid);
 				sourceType.tagBits |= HierarchyHasProblems;
 				noProblems = false;
 				continue nextInterface;
@@ -694,15 +857,16 @@
 	void connectTypeHierarchy() {
 		SourceTypeBinding sourceType = referenceContext.binding;
 		if ((sourceType.tagBits & BeginHierarchyCheck) == 0) {
-			boolean noProblems = true;
 			sourceType.tagBits |= BeginHierarchyCheck;
-			if (sourceType.isClass())
-				noProblems &= connectSuperclass();
+			boolean noProblems = connectTypeVariables(referenceContext.typeParameters);
+			noProblems &= connectSuperclass();
 			noProblems &= connectSuperInterfaces();
 			sourceType.tagBits |= EndHierarchyCheck;
 			if (noProblems && sourceType.isHierarchyInconsistent())
 				problemReporter().hierarchyHasProblems(sourceType);
 		}
+		// Perform deferred bound checks for parameterized type references (only done after hierarchy is connected)
+		checkParameterizedTypeBounds();
 		connectMemberTypes();
 		try {
 			checkForInheritedMemberTypes(sourceType);
@@ -727,27 +891,80 @@
 		if ((sourceType.tagBits & BeginHierarchyCheck) != 0)
 			return;
 
-		boolean noProblems = true;
 		sourceType.tagBits |= BeginHierarchyCheck;
-		if (sourceType.isClass())
-			noProblems &= connectSuperclass();
+		boolean noProblems = connectTypeVariables(referenceContext.typeParameters);
+		noProblems &= connectSuperclass();
 		noProblems &= connectSuperInterfaces();
 		sourceType.tagBits |= EndHierarchyCheck;
 		if (noProblems && sourceType.isHierarchyInconsistent())
 			problemReporter().hierarchyHasProblems(sourceType);
 	}
-	
+
+	public boolean detectAnnotationCycle(TypeBinding sourceType, TypeBinding annotationElementType, TypeReference reference) {
+		if (!annotationElementType.isAnnotationType()) 
+			return false;
+
+		if (sourceType == annotationElementType) {
+			problemReporter().annotationCircularity(sourceType, annotationElementType, reference);
+			return true;
+		}
+		// TODO (kent) add support for detecting indirect cases using TagBits.BeginAnnotationCheck/EndAnnotationCheck
+		return false;
+	}
+
+	public boolean detectHierarchyCycle(TypeBinding superType, TypeReference reference, TypeBinding[] argTypes) {
+		if (!(superType instanceof ReferenceBinding)) return false;
+
+		if (argTypes != null) {
+			for (int i = 0, l = argTypes.length; i < l; i++) {
+				TypeBinding argType = argTypes[i].leafComponentType();
+				if ((argType.tagBits & BeginHierarchyCheck) == 0 && argType instanceof SourceTypeBinding)
+			    	// ensure if this is a source argument type that it has already been checked
+			    	((SourceTypeBinding) argType).scope.connectTypeHierarchyWithoutMembers();
+			}
+		}
+
+		if (reference == this.superTypeReference) { // see findSuperType()
+			if (superType.isTypeVariable())
+				return false; // error case caught in resolveSuperType()
+			// abstract class X<K,V> implements java.util.Map<K,V>
+			//    static abstract class M<K,V> implements Entry<K,V>
+			if (superType.isParameterizedType())
+				superType = ((ParameterizedTypeBinding) superType).type;
+			compilationUnitScope().recordSuperTypeReference(superType); // to record supertypes
+			return detectHierarchyCycle(referenceContext.binding, (ReferenceBinding) superType, reference);
+		}
+
+		if ((superType.tagBits & BeginHierarchyCheck) == 0 && superType instanceof SourceTypeBinding)
+			// ensure if this is a source superclass that it has already been checked
+			((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers();
+		return false;
+	}
+
 	// Answer whether a cycle was found between the sourceType & the superType
-	private boolean detectCycle(
-		SourceTypeBinding sourceType,
-		ReferenceBinding superType,
-		TypeReference reference) {
+	private boolean detectHierarchyCycle(SourceTypeBinding sourceType, ReferenceBinding superType, TypeReference reference) {
+		if (superType.isRawType())
+			superType = ((RawTypeBinding) superType).type;
+		// by this point the superType must be a binary or source type
+
 		if (sourceType == superType) {
 			problemReporter().hierarchyCircularity(sourceType, superType, reference);
 			sourceType.tagBits |= HierarchyHasProblems;
 			return true;
 		}
 
+		if (superType.isMemberType()) {
+			ReferenceBinding current = superType.enclosingType();
+			do {
+				if (current.isHierarchyBeingConnected()) {
+					problemReporter().hierarchyCircularity(sourceType, current, reference);
+					sourceType.tagBits |= HierarchyHasProblems;
+					current.tagBits |= HierarchyHasProblems;
+					return true;
+				}
+			} while ((current = current.enclosingType()) != null);
+		}
+
 		if (superType.isBinaryBinding()) {
 			// force its superclass & superinterfaces to be found... 2 possibilities exist - the source type is included in the hierarchy of:
 			//		- a binary type... this case MUST be caught & reported here
@@ -760,10 +977,13 @@
 					superType.tagBits |= HierarchyHasProblems;
 					return true;
 				}
-				hasCycle |= detectCycle(sourceType, superType.superclass(), reference);
-				if ((superType.superclass().tagBits & HierarchyHasProblems) != 0) {
+				ReferenceBinding parentType = superType.superclass();
+				if (parentType.isParameterizedType())
+					parentType = ((ParameterizedTypeBinding) parentType).type;
+				hasCycle |= detectHierarchyCycle(sourceType, parentType, reference);
+				if ((parentType.tagBits & HierarchyHasProblems) != 0) {
 					sourceType.tagBits |= HierarchyHasProblems;
-					superType.tagBits |= HierarchyHasProblems; // propagate down the hierarchy
+					parentType.tagBits |= HierarchyHasProblems; // propagate down the hierarchy
 				}
 			}
 
@@ -777,7 +997,9 @@
 						superType.tagBits |= HierarchyHasProblems;
 						return true;
 					}
-					hasCycle |= detectCycle(sourceType, anInterface, reference);
+					if (anInterface.isParameterizedType())
+						anInterface = ((ParameterizedTypeBinding) anInterface).type;
+					hasCycle |= detectHierarchyCycle(sourceType, anInterface, reference);
 					if ((anInterface.tagBits & HierarchyHasProblems) != 0) {
 						sourceType.tagBits |= HierarchyHasProblems;
 						superType.tagBits |= HierarchyHasProblems;
@@ -787,93 +1009,68 @@
 			return hasCycle;
 		}
 
-		if ((superType.tagBits & EndHierarchyCheck) == 0
-			&& (superType.tagBits & BeginHierarchyCheck) != 0) {
-			problemReporter().hierarchyCircularity(sourceType, superType, reference);
-			sourceType.tagBits |= HierarchyHasProblems;
-			superType.tagBits |= HierarchyHasProblems;
-			return true;
+		if (superType.isHierarchyBeingConnected()) {
+			if (((SourceTypeBinding) superType).scope.superTypeReference != null) { // if null then its connecting its type variables
+				problemReporter().hierarchyCircularity(sourceType, superType, reference);
+				sourceType.tagBits |= HierarchyHasProblems;
+				superType.tagBits |= HierarchyHasProblems;
+				return true;
+			}
 		}
 		if ((superType.tagBits & BeginHierarchyCheck) == 0)
 			// ensure if this is a source superclass that it has already been checked
-			 ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers();
+			((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers();
 		if ((superType.tagBits & HierarchyHasProblems) != 0)
 			sourceType.tagBits |= HierarchyHasProblems;
 		return false;
 	}
-	
+
+	private ReferenceBinding findAmbiguousInterface(ReferenceBinding newInterface, ReferenceBinding currentType) {
+		TypeBinding newErasure = newInterface.erasure();
+		if (newInterface == newErasure) return null;
+
+		ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
+		int lastPosition = -1;
+		do {
+			ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+			if (itsInterfaces != NoSuperInterfaces) {
+				if (++lastPosition == interfacesToVisit.length)
+					System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+				interfacesToVisit[lastPosition] = itsInterfaces;
+			}
+		} while ((currentType = currentType.superclass()) != null);
+
+		for (int i = 0; i <= lastPosition; i++) {
+			ReferenceBinding[] interfaces = interfacesToVisit[i];
+			for (int j = 0, length = interfaces.length; j < length; j++) {
+				currentType = interfaces[j];
+				if (currentType.erasure() == newErasure)
+					if (currentType != newInterface)
+						return currentType;
+
+				ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+				if (itsInterfaces != NoSuperInterfaces) {
+					if (++lastPosition == interfacesToVisit.length)
+						System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+					interfacesToVisit[lastPosition] = itsInterfaces;
+				}
+			}
+		}
+		return null;
+	}
+
 	private ReferenceBinding findSupertype(TypeReference typeReference) {
 		try {
 			typeReference.aboutToResolve(this); // allows us to trap completion & selection nodes
-			char[][] compoundName = typeReference.getTypeName();
-			compilationUnitScope().recordQualifiedReference(compoundName);
-			SourceTypeBinding sourceType = referenceContext.binding;
-			int size = compoundName.length;
-			int n = 1;
-			ReferenceBinding superType;
-	
-			// resolve the first name of the compoundName
-			if (CharOperation.equals(compoundName[0], sourceType.sourceName)) {
-				superType = sourceType;
-				// match against the sourceType even though nested members cannot be supertypes
-			} else {
-				Binding typeOrPackage = parent.getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
-				if (typeOrPackage == null || !typeOrPackage.isValidBinding())
-					return new ProblemReferenceBinding(
-						compoundName[0],
-						typeOrPackage == null ? NotFound : typeOrPackage.problemId());
-	
-				boolean checkVisibility = false;
-				for (; n < size; n++) {
-					if (!(typeOrPackage instanceof PackageBinding))
-						break;
-					PackageBinding packageBinding = (PackageBinding) typeOrPackage;
-					typeOrPackage = packageBinding.getTypeOrPackage(compoundName[n]);
-					if (typeOrPackage == null || !typeOrPackage.isValidBinding())
-						return new ProblemReferenceBinding(
-							CharOperation.subarray(compoundName, 0, n + 1),
-							typeOrPackage == null ? NotFound : typeOrPackage.problemId());
-					checkVisibility = true;
-				}
-	
-				// convert to a ReferenceBinding
-				if (typeOrPackage instanceof PackageBinding) // error, the compoundName is a packageName
-					return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), NotFound);
-				superType = (ReferenceBinding) typeOrPackage;
-				compilationUnitScope().recordTypeReference(superType); // to record supertypes
-	
-				if (checkVisibility
-					&& n == size) { // if we're finished and know the final supertype then check visibility
-					if (!superType.canBeSeenBy(sourceType.fPackage))
-						// its a toplevel type so just check package access
-						return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), superType, NotVisible);
-				}
-			}
-			// at this point we know we have a type but we have to look for cycles
-			while (true) {
-				// must detect cycles & force connection up the hierarchy... also handle cycles with binary types.
-				// must be guaranteed that the superType knows its entire hierarchy
-				if (detectCycle(sourceType, superType, typeReference))
-					return null; // cycle error was already reported
-	
-				if (n >= size)
-					break;
-	
-				// retrieve the next member type
-				char[] typeName = compoundName[n++];
-				superType = findMemberType(typeName, superType);
-				if (superType == null)
-					return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), NotFound);
-				if (!superType.isValidBinding()) {
-					superType.compoundName = CharOperation.subarray(compoundName, 0, n);
-					return superType;
-				}
-			}
+			compilationUnitScope().recordQualifiedReference(typeReference.getTypeName());
+			this.superTypeReference = typeReference;
+			ReferenceBinding superType = (ReferenceBinding) typeReference.resolveSuperType(this);
+			this.superTypeReference = null;
 			return superType;
 		} catch (AbortCompilation e) {
 			e.updateContext(typeReference, referenceCompilationUnit().compilationResult);
 			throw e;
-		}
+		}			
 	}
 
 	/* Answer the problem reporter to use for raising new problems.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
index d4a8d4f..9033073 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
@@ -11,16 +11,11 @@
 package org.eclipse.jdt.internal.compiler.lookup;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.*;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
-import org.eclipse.jdt.internal.compiler.util.CompoundNameVector;
-import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
-import org.eclipse.jdt.internal.compiler.util.HashtableOfType;
-import org.eclipse.jdt.internal.compiler.util.ObjectVector;
-import org.eclipse.jdt.internal.compiler.util.SimpleNameVector;
+import org.eclipse.jdt.internal.compiler.util.*;
 
 public class CompilationUnitScope extends Scope {
 	
@@ -36,6 +31,7 @@
 	private CompoundNameVector qualifiedReferences;
 	private SimpleNameVector simpleNameReferences;
 	private ObjectVector referencedTypes;
+	private ObjectVector referencedSuperTypes;
 	
 	HashtableOfType constantPoolNameUsage;
 
@@ -50,17 +46,19 @@
 		this.qualifiedReferences = new CompoundNameVector();
 		this.simpleNameReferences = new SimpleNameVector();
 		this.referencedTypes = new ObjectVector();
+		this.referencedSuperTypes = new ObjectVector();
 	} else {
 		this.qualifiedReferences = null; // used to test if dependencies should be recorded
 		this.simpleNameReferences = null;
 		this.referencedTypes = null;
+		this.referencedSuperTypes = null;
 	}
 }
 void buildFieldsAndMethods() {
 	for (int i = 0, length = topLevelTypes.length; i < length; i++)
 		topLevelTypes[i].scope.buildFieldsAndMethods();
 }
-void buildTypeBindings() {
+void buildTypeBindings(AccessRestriction accessRestriction) {
 	topLevelTypes = new SourceTypeBinding[0]; // want it initialized if the package cannot be resolved
 	if (referenceContext.compilationResult.compilationUnit != null) {
 		char[][] expectedPackageName = referenceContext.compilationResult.compilationUnit.getPackageName();
@@ -120,7 +118,7 @@
 		}
 
 		ClassScope child = new ClassScope(this, typeDecl);
-		SourceTypeBinding type = child.buildType(null, fPackage);
+		SourceTypeBinding type = child.buildType(null, fPackage, accessRestriction);
 		if(type != null) {
 			topLevelTypes[count++] = type;
 		}
@@ -141,7 +139,7 @@
 	int numberOfImports = numberOfStatements + 1;
 	for (int i = 0; i < numberOfStatements; i++) {
 		ImportReference importReference = referenceContext.imports[i];
-		if (importReference.onDemand && CharOperation.equals(JAVA_LANG, importReference.tokens)) {
+		if (importReference.onDemand && CharOperation.equals(JAVA_LANG, importReference.tokens) && !importReference.isStatic()) {
 			numberOfImports--;
 			break;
 		}
@@ -155,20 +153,23 @@
 		char[][] compoundName = importReference.tokens;
 
 		// skip duplicates or imports of the current package
-		for (int j = 0; j < index; j++)
-			if (resolvedImports[j].onDemand == importReference.onDemand)
+		for (int j = 0; j < index; j++) {
+			ImportBinding resolved = resolvedImports[j];
+			if (resolved.onDemand == importReference.onDemand && resolved.isStatic() == importReference.isStatic())
 				if (CharOperation.equals(compoundName, resolvedImports[j].compoundName))
 					continue nextImport;
-		if (importReference.onDemand == true)
+		}
+
+		if (importReference.onDemand) {
 			if (CharOperation.equals(compoundName, currentPackageName))
 				continue nextImport;
 
-		if (importReference.onDemand) {
-			Binding importBinding = findOnDemandImport(compoundName);
-			if (!importBinding.isValidBinding())
+			Binding importBinding = findImport(compoundName, compoundName.length);
+			if (!importBinding.isValidBinding() || (importReference.isStatic() && importBinding instanceof PackageBinding))
 				continue nextImport;	// we report all problems in faultInImports()
 			resolvedImports[index++] = new ImportBinding(compoundName, true, importBinding, importReference);
 		} else {
+			// resolve single imports only when the last name matches
 			resolvedImports[index++] = new ImportBinding(compoundName, false, null, importReference);
 		}
 	}
@@ -261,7 +262,7 @@
 	int numberOfImports = numberOfStatements + 1;
 	for (int i = 0; i < numberOfStatements; i++) {
 		ImportReference importReference = referenceContext.imports[i];
-		if (importReference.onDemand && CharOperation.equals(JAVA_LANG, importReference.tokens)) {
+		if (importReference.onDemand && CharOperation.equals(JAVA_LANG, importReference.tokens) && !importReference.isStatic()) {
 			numberOfImports--;
 			break;
 		}
@@ -270,63 +271,73 @@
 	resolvedImports[0] = getDefaultImports()[0];
 	int index = 1;
 
+	// keep static imports with normal imports until there is a reason to split them up
+	// on demand imports continue to be packages & types. need to check on demand type imports for fields/methods
+	// single imports change from being just types to types or fields
 	nextImport : for (int i = 0; i < numberOfStatements; i++) {
 		ImportReference importReference = referenceContext.imports[i];
 		char[][] compoundName = importReference.tokens;
 
 		// skip duplicates or imports of the current package
-		for (int j = 0; j < index; j++)
-			if (resolvedImports[j].onDemand == importReference.onDemand)
-				if (CharOperation.equals(compoundName, resolvedImports[j].compoundName)) {
+		for (int j = 0; j < index; j++) {
+			ImportBinding resolved = resolvedImports[j];
+			if (resolved.onDemand == importReference.onDemand && resolved.isStatic() == importReference.isStatic()) {
+				if (CharOperation.equals(compoundName, resolved.compoundName)) {
 					problemReporter().unusedImport(importReference); // since skipped, must be reported now
 					continue nextImport;
 				}
-		if (importReference.onDemand == true)
+			}
+		}
+		if (importReference.onDemand) {
 			if (CharOperation.equals(compoundName, currentPackageName)) {
 				problemReporter().unusedImport(importReference); // since skipped, must be reported now
 				continue nextImport;
 			}
-		if (importReference.onDemand) {
-			Binding importBinding = findOnDemandImport(compoundName);
+
+			Binding importBinding = findImport(compoundName, compoundName.length);
 			if (!importBinding.isValidBinding()) {
 				problemReporter().importProblem(importReference, importBinding);
 				continue nextImport;
 			}
-			resolvedImports[index++] = new ImportBinding(compoundName, true, importBinding, importReference);
-		} else {
-			Binding typeBinding = findSingleTypeImport(compoundName);
-			if (!typeBinding.isValidBinding()) {
-				problemReporter().importProblem(importReference, typeBinding);
-				continue nextImport;
-			}
-			if (typeBinding instanceof PackageBinding) {
+			if (importReference.isStatic() && importBinding instanceof PackageBinding) {
 				problemReporter().cannotImportPackage(importReference);
 				continue nextImport;
 			}
-			if (typeBinding instanceof ReferenceBinding) {
-				ReferenceBinding referenceBinding = (ReferenceBinding) typeBinding;
-				if (importReference.isTypeUseDeprecated(referenceBinding, this)) {
-					problemReporter().deprecatedType((TypeBinding) typeBinding, importReference);
-				}
-			}
-			ReferenceBinding existingType = typesBySimpleNames.get(compoundName[compoundName.length - 1]);
-			if (existingType != null) {
-				// duplicate test above should have caught this case, but make sure
-				if (existingType == typeBinding) {
-					continue nextImport;
-				}
-				// either the type collides with a top level type or another imported type
-				for (int j = 0, length = topLevelTypes.length; j < length; j++) {
-					if (CharOperation.equals(topLevelTypes[j].sourceName, existingType.sourceName)) {
-						problemReporter().conflictingImport(importReference);
-						continue nextImport;
-					}
-				}
-				problemReporter().duplicateImport(importReference);
+			resolvedImports[index++] = new ImportBinding(compoundName, true, importBinding, importReference);
+		} else {
+			Binding importBinding = findSingleImport(compoundName, importReference.isStatic());
+			if (!importBinding.isValidBinding()) {
+				problemReporter().importProblem(importReference, importBinding);
 				continue nextImport;
 			}
-			resolvedImports[index++] = new ImportBinding(compoundName, false, typeBinding, importReference);
-			typesBySimpleNames.put(compoundName[compoundName.length - 1], (ReferenceBinding) typeBinding);
+			if (importBinding instanceof PackageBinding) {
+				problemReporter().cannotImportPackage(importReference);
+				continue nextImport;
+			}
+			// collisions between an imported static field & a type should be checked according to spec... but currently not by javac
+			if (importBinding instanceof ReferenceBinding) {
+				ReferenceBinding referenceBinding = (ReferenceBinding) importBinding;
+				if (importReference.isTypeUseDeprecated(referenceBinding, this))
+					problemReporter().deprecatedType(referenceBinding, importReference);
+
+				ReferenceBinding existingType = typesBySimpleNames.get(compoundName[compoundName.length - 1]);
+				if (existingType != null) {
+					// duplicate test above should have caught this case, but make sure
+					if (existingType == referenceBinding)
+						continue nextImport;
+					// either the type collides with a top level type or another imported type
+					for (int j = 0, length = topLevelTypes.length; j < length; j++) {
+						if (CharOperation.equals(topLevelTypes[j].sourceName, existingType.sourceName)) {
+							problemReporter().conflictingImport(importReference);
+							continue nextImport;
+						}
+					}
+					problemReporter().duplicateImport(importReference);
+					continue nextImport;
+				}
+				typesBySimpleNames.put(compoundName[compoundName.length - 1], referenceBinding);
+			}
+			resolvedImports[index++] = new ImportBinding(compoundName, false, importBinding, importReference);
 		}
 	}
 
@@ -339,7 +350,7 @@
 	resolvedSingeTypeImports = new HashtableOfObject(length);
 	for (int i = 0; i < length; i++) {
 		ImportBinding binding = imports[i];
-		if (!binding.onDemand)
+		if (!binding.onDemand && binding.resolvedImport instanceof ReferenceBinding)
 			resolvedSingeTypeImports.put(binding.compoundName[binding.compoundName.length - 1], binding);
 	}
 }
@@ -349,12 +360,11 @@
 	for (int i = 0, length = topLevelTypes.length; i < length; i++)
 		topLevelTypes[i].faultInTypesForFieldsAndMethods();
 }
-private Binding findOnDemandImport(char[][] compoundName) {
+private Binding findImport(char[][] compoundName, int length) {
 	recordQualifiedReference(compoundName);
 
 	Binding binding = environment.getTopLevelPackage(compoundName[0]);
 	int i = 1;
-	int length = compoundName.length;
 	foundNothingOrType: if (binding != null) {
 		PackageBinding packageBinding = (PackageBinding) binding;
 		while (i < length) {
@@ -373,50 +383,70 @@
 
 	ReferenceBinding type;
 	if (binding == null) {
-		if (environment.defaultPackage == null
-				|| environment.options.complianceLevel >= ClassFileConstants.JDK1_4){
-			return new ProblemReferenceBinding(
-				CharOperation.subarray(compoundName, 0, i),
-				NotFound);
-		}
+		if (environment.defaultPackage == null || environment.options.complianceLevel >= ClassFileConstants.JDK1_4)
+			return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), NotFound);
 		type = findType(compoundName[0], environment.defaultPackage, environment.defaultPackage);
 		if (type == null || !type.isValidBinding())
-			return new ProblemReferenceBinding(
-				CharOperation.subarray(compoundName, 0, i),
-				NotFound);
+			return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), NotFound);
 		i = 1; // reset to look for member types inside the default package type
 	} else {
 		type = (ReferenceBinding) binding;
 	}
 
-	for (; i < length; i++) {
-		if (!type.canBeSeenBy(fPackage)) {
-			return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), type, NotVisible);		
-		}
-		// does not look for inherited member types on purpose
-		if ((type = type.getMemberType(compoundName[i])) == null) {
-			return new ProblemReferenceBinding(
-				CharOperation.subarray(compoundName, 0, i + 1),
-				NotFound);
-		}
+	while (i < length) {
+		if (!type.canBeSeenBy(fPackage))
+			return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), type, NotVisible);
+
+		char[] name = compoundName[i++];
+		// does not look for inherited member types on purpose, only immediate members
+		type = type.getMemberType(name);
+		if (type == null)
+			return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), NotFound);
 	}
 	if (!type.canBeSeenBy(fPackage))
 		return new ProblemReferenceBinding(compoundName, type, NotVisible);
 	return type;
 }
-private Binding findSingleTypeImport(char[][] compoundName) {
+private Binding findSingleImport(char[][] compoundName, boolean findStaticImports) {
 	if (compoundName.length == 1) {
 		// findType records the reference
 		// the name cannot be a package
-		if (environment.defaultPackage == null 
-			|| environment.options.complianceLevel >= ClassFileConstants.JDK1_4)
+		if (environment.defaultPackage == null || environment.options.complianceLevel >= ClassFileConstants.JDK1_4)
 			return new ProblemReferenceBinding(compoundName, NotFound);
 		ReferenceBinding typeBinding = findType(compoundName[0], environment.defaultPackage, fPackage);
 		if (typeBinding == null)
 			return new ProblemReferenceBinding(compoundName, NotFound);
 		return typeBinding;
 	}
-	return findOnDemandImport(compoundName);
+
+	if (findStaticImports)
+		return findSingleStaticImport(compoundName);
+	return findImport(compoundName, compoundName.length);
+}
+private Binding findSingleStaticImport(char[][] compoundName) {
+	Binding binding = findImport(compoundName, compoundName.length - 1);
+	if (!binding.isValidBinding()) return binding;
+
+	char[] name = compoundName[compoundName.length - 1];
+	if (binding instanceof PackageBinding) {
+		Binding temp = ((PackageBinding) binding).getTypeOrPackage(name);
+		if (temp != null && temp instanceof ReferenceBinding) // must resolve to a member type or field, not a top level type
+			return new ProblemReferenceBinding(compoundName, InvalidTypeForStaticImport);
+		return binding; // cannot be a package, error is caught in sender
+	}
+
+	// look to see if its a static field first
+	ReferenceBinding type = (ReferenceBinding) binding;
+	FieldBinding field = findField(type, name, null, true);
+	if (field != null && field.isStatic() && field.canBeSeenBy(fPackage))
+		return field;
+
+	type = findMemberType(name, type);
+	if (type == null || !type.isStatic())
+		return new ProblemReferenceBinding(compoundName, type, NotFound);
+	if (!type.canBeSeenBy(fPackage))
+		return new ProblemReferenceBinding(compoundName, type, NotVisible);
+	return type;
 }
 ImportBinding[] getDefaultImports() {
 	// initialize the default imports if necessary... share the default java.lang.* import
@@ -432,6 +462,12 @@
 
 	return environment.defaultImports = new ImportBinding[] {new ImportBinding(JAVA_LANG, true, importBinding, null)};
 }
+// NOT Public API
+public final Binding getImport(char[][] compoundName, boolean onDemand, boolean isStaticImport) {
+	if (onDemand)
+		return findImport(compoundName, compoundName.length);
+	return findSingleImport(compoundName, isStaticImport);
+}
 /* Answer the problem reporter to use for raising new problems.
 *
 * Note that as a side-effect, this updates the current reference context
@@ -505,53 +541,55 @@
 	recordQualifiedReference(qualifiedEnclosingName);
 	recordSimpleReference(simpleName);
 }
+void recordReference(ReferenceBinding type, char[] simpleName) {
+	ReferenceBinding actualType = typeToRecord(type);
+	if (actualType != null)
+		recordReference(actualType.compoundName, simpleName);
+}
 void recordSimpleReference(char[] simpleName) {
 	if (simpleNameReferences == null) return; // not recording dependencies
 
 	if (!simpleNameReferences.contains(simpleName))
 		simpleNameReferences.add(simpleName);
 }
+void recordSuperTypeReference(TypeBinding type) {
+	if (referencedSuperTypes == null) return; // not recording dependencies
+
+	ReferenceBinding actualType = typeToRecord(type);
+	if (actualType != null && !referencedSuperTypes.containsIdentical(actualType))
+		referencedSuperTypes.add(actualType);
+}
+public void recordTypeConversion(TypeBinding superType, TypeBinding subType) {
+	recordSuperTypeReference(subType); // must record the hierarchy of the subType that is converted to the superType
+}
 void recordTypeReference(TypeBinding type) {
 	if (referencedTypes == null) return; // not recording dependencies
 
-	if (type.isArrayType())
-		type = ((ArrayBinding) type).leafComponentType;
-
-	if (type.isBaseType()) return;
-	if (referencedTypes.containsIdentical(type)) return;
-	if (((ReferenceBinding) type).isLocalType()) return;
-
-	referencedTypes.add(type);
+	ReferenceBinding actualType = typeToRecord(type);
+	if (actualType != null && !referencedTypes.containsIdentical(actualType))
+		referencedTypes.add(actualType);
 }
 void recordTypeReferences(TypeBinding[] types) {
-	if (qualifiedReferences == null) return; // not recording dependencies
+	if (referencedTypes == null) return; // not recording dependencies
 	if (types == null || types.length == 0) return;
 
 	for (int i = 0, max = types.length; i < max; i++) {
 		// No need to record supertypes of method arguments & thrown exceptions, just the compoundName
 		// If a field/method is retrieved from such a type then a separate call does the job
-		TypeBinding type = types[i];
-		if (type.isArrayType())
-			type = ((ArrayBinding) type).leafComponentType;
-		if (!type.isBaseType()) {
-			ReferenceBinding actualType = (ReferenceBinding) type;
-			if (!actualType.isLocalType())
-				recordQualifiedReference(actualType.isMemberType()
-					? CharOperation.splitOn('.', actualType.readableName())
-					: actualType.compoundName);
-		}
+		ReferenceBinding actualType = typeToRecord(types[i]);
+		if (actualType != null && !referencedTypes.containsIdentical(actualType))
+			referencedTypes.add(actualType);
 	}
 }
-Binding resolveSingleTypeImport(ImportBinding importBinding) {
+Binding resolveSingleImport(ImportBinding importBinding) {
 	if (importBinding.resolvedImport == null) {
-		importBinding.resolvedImport = findSingleTypeImport(importBinding.compoundName);
+		importBinding.resolvedImport = findSingleImport(importBinding.compoundName, importBinding.isStatic());
 		if (!importBinding.resolvedImport.isValidBinding() || importBinding.resolvedImport instanceof PackageBinding) {
-			if (this.imports != null){
+			if (this.imports != null) {
 				ImportBinding[] newImports = new ImportBinding[imports.length - 1];
 				for (int i = 0, n = 0, max = this.imports.length; i < max; i++)
-					if (this.imports[i] != importBinding){
+					if (this.imports[i] != importBinding)
 						newImports[n++] = this.imports[i];
-					}
 				this.imports = newImports;
 			}
 			return null;
@@ -560,26 +598,33 @@
 	return importBinding.resolvedImport;
 }
 public void storeDependencyInfo() {
-	// add the type hierarchy of each referenced type
+	// add the type hierarchy of each referenced supertype
 	// cannot do early since the hierarchy may not be fully resolved
-	for (int i = 0; i < referencedTypes.size; i++) { // grows as more types are added
-		ReferenceBinding type = (ReferenceBinding) referencedTypes.elementAt(i);
+	for (int i = 0; i < referencedSuperTypes.size; i++) { // grows as more types are added
+		ReferenceBinding type = (ReferenceBinding) referencedSuperTypes.elementAt(i);
+		if (!referencedTypes.containsIdentical(type))
+			referencedTypes.add(type);
+
 		if (!type.isLocalType()) {
+			ReferenceBinding enclosing = type.enclosingType();
+			if (enclosing != null)
+				recordSuperTypeReference(enclosing);
+		}
+		ReferenceBinding superclass = type.superclass();
+		if (superclass != null)
+			recordSuperTypeReference(superclass);
+		ReferenceBinding[] interfaces = type.superInterfaces();
+		if (interfaces != null)
+			for (int j = 0, length = interfaces.length; j < length; j++)
+				recordSuperTypeReference(interfaces[j]);
+	}
+
+	for (int i = 0, l = referencedTypes.size; i < l; i++) {
+		ReferenceBinding type = (ReferenceBinding) referencedTypes.elementAt(i);
+		if (!type.isLocalType())
 			recordQualifiedReference(type.isMemberType()
 				? CharOperation.splitOn('.', type.readableName())
 				: type.compoundName);
-			ReferenceBinding enclosing = type.enclosingType();
-			if (enclosing != null && !referencedTypes.containsIdentical(enclosing))
-				referencedTypes.add(enclosing); // to record its supertypes
-		}
-		ReferenceBinding superclass = type.superclass();
-		if (superclass != null && !referencedTypes.containsIdentical(superclass))
-				referencedTypes.add(superclass); // to record its supertypes
-		ReferenceBinding[] interfaces = type.superInterfaces();
-		if (interfaces != null && interfaces.length > 0)
-			for (int j = 0, length = interfaces.length; j < length; j++)
-				if (!referencedTypes.containsIdentical(interfaces[j]))
-					referencedTypes.add(interfaces[j]); // to record its supertypes
 	}
 
 	int size = qualifiedReferences.size;
@@ -597,6 +642,25 @@
 public String toString() {
 	return "--- CompilationUnit Scope : " + new String(referenceContext.getFileName()); //$NON-NLS-1$
 }
+private ReferenceBinding typeToRecord(TypeBinding type) {
+	if (type.isArrayType())
+		type = ((ArrayBinding) type).leafComponentType;
+
+	switch (type.kind()) {
+		case Binding.TYPE_PARAMETER :
+		case Binding.WILDCARD_TYPE :
+			return null;
+		case Binding.PARAMETERIZED_TYPE :
+		case Binding.RAW_TYPE :
+			type = type.erasure();
+	}
+
+	if (type instanceof ReferenceBinding) {
+		ReferenceBinding refType = (ReferenceBinding) type;
+		if (!refType.isLocalType()) return refType;
+	}
+	return null;
+}
 public void verifyMethods(MethodVerifier verifier) {
 	for (int i = 0, length = topLevelTypes.length; i < length; i++)
 		topLevelTypes[i].verifyMethods(verifier);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilerModifiers.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilerModifiers.java
index 31f21cc..f8e80f1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilerModifiers.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilerModifiers.java
@@ -10,30 +10,34 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 
 public interface CompilerModifiers extends ClassFileConstants { // modifier constant
 	// those constants are depending upon ClassFileConstants (relying that classfiles only use the 16 lower bits)
 	final int AccDefault = 0;
-	final int AccJustFlag = 0xFFFF;
-	final int AccCatchesExceptions = 0x10000; // bit17
-	final int AccThrowsExceptions = 0x20000; // bit18 - also IConstants.AccSynthetic
-	final int AccProblem = 0x40000; // bit19
-	final int AccFromClassFile = 0x80000; // bit20
-	final int AccIsConstantValue = 0x80000;	 // bit20
-	final int AccDefaultAbstract = 0x80000; // bit20
+	final int AccJustFlag = // 16 lower bits
+	    	ASTNode.Bit1|ASTNode.Bit2|ASTNode.Bit3|ASTNode.Bit4|ASTNode.Bit5|ASTNode.Bit6|ASTNode.Bit7|ASTNode.Bit8|
+			ASTNode.Bit9|ASTNode.Bit10|ASTNode.Bit11|ASTNode.Bit12|ASTNode.Bit13|ASTNode.Bit14|ASTNode.Bit15|ASTNode.Bit16;
+
+	// bit17 - free
+	// bit18 - IConstants.AccAnnotationDefault
+	final int AccRestrictedAccess = ASTNode.Bit19; 
+	final int AccFromClassFile = ASTNode.Bit20; 
+	final int AccDefaultAbstract = ASTNode.Bit20; 
 	// bit21 - IConstants.AccDeprecated
-	final int AccDeprecatedImplicitly = 0x200000; // bit22 to record whether deprecated itself or contained by a deprecated type
-	final int AccAlternateModifierProblem = 0x400000; // bit23
-	final int AccModifierProblem = 0x800000; // bit24
-	final int AccSemicolonBody = 0x1000000; // bit25
-	final int AccUnresolved = 0x2000000; // bit26
-	final int AccClearPrivateModifier = 0x4000000; // bit27 might be requested during private access emulation
-	final int AccBlankFinal = 0x4000000; // bit27 for blank final variables
-	final int AccIsDefaultConstructor = 0x4000000; // bit27 for default constructor
-	final int AccPrivateUsed = 0x8000000; // bit28 used to diagnose unused private members
+	final int AccDeprecatedImplicitly = ASTNode.Bit22; // record whether deprecated itself or contained by a deprecated type
+	final int AccAlternateModifierProblem = ASTNode.Bit23; 
+	final int AccModifierProblem = ASTNode.Bit24; 
+	final int AccSemicolonBody = ASTNode.Bit25; 
+	final int AccUnresolved = ASTNode.Bit26; 
+	final int AccClearPrivateModifier = ASTNode.Bit27; // might be requested during private access emulation
+	final int AccBlankFinal = ASTNode.Bit27; // for blank final variables
+	final int AccIsDefaultConstructor = ASTNode.Bit27; // for default constructor
+	final int AccPrivateUsed = ASTNode.Bit28; // used to diagnose unused private members
 	final int AccVisibilityMASK = AccPublic | AccProtected | AccPrivate;
 	
-	final int AccOverriding = 0x10000000; // bit29 to record fact a method overrides another one
-	final int AccImplementing = 0x20000000; // bit30 to record fact a method implements another one (it is concrete and overrides an abstract one)
+	final int AccOverriding = ASTNode.Bit29; // record fact a method overrides another one
+	final int AccImplementing = ASTNode.Bit30; // record fact a method implements another one (it is concrete and overrides an abstract one)
+	final int AccGenericSignature = ASTNode.Bit31; // record fact a type/method/field involves generics in its signature (and need special signature attr)
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
index 4889096..5a01f8b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
@@ -10,20 +10,21 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 
 public class FieldBinding extends VariableBinding {
 	public ReferenceBinding declaringClass;
 protected FieldBinding() {
+	super(null, null, 0, null);
 	// for creating problem field
 }
 public FieldBinding(char[] name, TypeBinding type, int modifiers, ReferenceBinding declaringClass, Constant constant) {
-	this.modifiers = modifiers;
-	this.type = type;
-	this.name = name;
+	super(name, type, modifiers, constant);
 	this.declaringClass = declaringClass;
-	this.constant = constant;
 
 	// propagate the deprecated modifier
 	if (this.declaringClass != null)
@@ -36,20 +37,27 @@
 }
 // special API used to change field declaring class for runtime visibility check
 public FieldBinding(FieldBinding initialFieldBinding, ReferenceBinding declaringClass) {
-	this.modifiers = initialFieldBinding.modifiers;
-	this.type = initialFieldBinding.type;
-	this.name = initialFieldBinding.name;
+	super(initialFieldBinding.name, initialFieldBinding.type, initialFieldBinding.modifiers, initialFieldBinding.constant());
 	this.declaringClass = declaringClass;
-	this.constant = initialFieldBinding.constant;
 	this.id = initialFieldBinding.id;
 }
 /* API
 * Answer the receiver's binding type from Binding.BindingID.
 */
 
-public final int bindingType() {
+public final int kind() {
 	return FIELD;
 }
+/* Answer true if the receiver is visible to the invocationPackage.
+*/
+
+public final boolean canBeSeenBy(PackageBinding invocationPackage) {
+	if (isPublic()) return true;
+	if (isPrivate()) return false;
+
+	// isProtected() or isDefault()
+	return invocationPackage == declaringClass.getPackage();
+}
 /* Answer true if the receiver is visible to the type provided by the scope.
 * InvocationSite implements isSuperAccess() to provide additional information
 * if the receiver is protected.
@@ -101,7 +109,15 @@
 	if (isPrivate()) {
 		// answer true if the receiverType is the declaringClass
 		// AND the invocationType and the declaringClass have a common enclosingType
-		if (receiverType != declaringClass) return false;
+		receiverCheck: {
+			if (receiverType != declaringClass) {
+				// special tolerance for type variable direct bounds
+				if (receiverType.isTypeVariable() && ((TypeVariableBinding) receiverType).isErasureBoundTo(declaringClass.erasure())) {
+					break receiverCheck;
+				}
+				return false;
+			}
+		}
 
 		if (invocationType != declaringClass) {
 			ReferenceBinding outerInvocationType = invocationType;
@@ -111,7 +127,7 @@
 				temp = temp.enclosingType();
 			}
 
-			ReferenceBinding outerDeclaringClass = declaringClass;
+			ReferenceBinding outerDeclaringClass = (ReferenceBinding)declaringClass.erasure();
 			temp = outerDeclaringClass.enclosingType();
 			while (temp != null) {
 				outerDeclaringClass = temp;
@@ -136,10 +152,47 @@
 	} while ((currentType = currentType.superclass()) != null);
 	return false;
 }
+/*
+ * declaringUniqueKey dot fieldName
+ * p.X { X<T> x} --> Lp/X;.x;
+ */
+public char[] computeUniqueKey() {
+	char[] declaringKey = this.declaringClass == null /*case of length field for an array*/ ? CharOperation.NO_CHAR : this.declaringClass.computeUniqueKey();
+	int declaringLength = declaringKey.length;
+	int nameLength = this.name.length;
+	char[] uniqueKey = new char[declaringLength + 1 + nameLength];
+	System.arraycopy(declaringKey, 0, uniqueKey, 0, declaringLength);
+	uniqueKey[declaringLength] = '.';
+	System.arraycopy(this.name, 0, uniqueKey, declaringLength + 1, nameLength);
+	return uniqueKey;
+}
+/**
+ * X<T> t   -->  LX<TT;>;
+ */
+public char[] genericSignature() {
+    if ((this.modifiers & AccGenericSignature) == 0) return null;
+    return this.type.genericTypeSignature();
+}
+
 public final int getAccessFlags() {
 	return modifiers & AccJustFlag;
 }
 
+/**
+ * Compute the tagbits for standard annotations. For source types, these could require
+ * lazily resolving corresponding annotation nodes, in case of forward references.
+ * @see org.eclipse.jdt.internal.compiler.lookup.Binding#getAnnotationTagBits()
+ */
+public long getAnnotationTagBits() {
+	FieldBinding originalField = this.original();
+	if ((originalField.tagBits & TagBits.AnnotationResolved) == 0 && originalField.declaringClass instanceof SourceTypeBinding) {
+		TypeDeclaration typeDecl = ((SourceTypeBinding)originalField.declaringClass).scope.referenceContext;
+		FieldDeclaration fieldDecl = typeDecl.declarationOf(originalField);
+		ASTNode.resolveAnnotations(isStatic() ? typeDecl.staticInitializerScope : typeDecl.initializerScope, fieldDecl.annotations, originalField);
+	}
+	return originalField.tagBits;
+}
+
 /* Answer true if the receiver has default visibility
 */
 
@@ -207,4 +260,26 @@
 public final boolean isVolatile() {
 	return (modifiers & AccVolatile) != 0;
 }
+/**
+ * Returns the original field (as opposed to parameterized instances)
+ */
+public FieldBinding original() {
+	return this;
+}
+public FieldDeclaration sourceField() {
+	SourceTypeBinding sourceType;
+	try {
+		sourceType = (SourceTypeBinding) declaringClass;
+	} catch (ClassCastException e) {
+		return null;		
+	}
+
+	FieldDeclaration[] fields = sourceType.scope.referenceContext.fields;
+	if (fields != null) {
+		for (int i = fields.length; --i >= 0;)
+			if (this == fields[i].binding)
+				return fields[i];
+	}
+	return null;		
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImportBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImportBinding.java
index 6eb0985..05c2992 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImportBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImportBinding.java
@@ -18,7 +18,7 @@
 	public boolean onDemand;
 	public ImportReference reference;
 
-	Binding resolvedImport; // must ensure the import is resolved
+	public Binding resolvedImport; // must ensure the import is resolved
 	
 public ImportBinding(char[][] compoundName, boolean isOnDemand, Binding binding, ImportReference reference) {
 	this.compoundName = compoundName;
@@ -30,9 +30,12 @@
 * Answer the receiver's binding type from Binding.BindingID.
 */
 
-public final int bindingType() {
+public final int kind() {
 	return IMPORT;
 }
+public boolean isStatic() {
+	return this.reference != null && this.reference.isStatic();
+}
 public char[] readableName() {
 	if (onDemand)
 		return CharOperation.concat(CharOperation.concatWith(compoundName, '.'), ".*".toCharArray()); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java
index e9703ba..462f95e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java
@@ -11,6 +11,8 @@
 package org.eclipse.jdt.internal.compiler.lookup;
 
 public interface InvocationSite {
+	
+	TypeBinding[] genericTypeArguments();
 	boolean isSuperAccess();
 	boolean isTypeAccess();
 	void setDepth(int depth);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
index cacc605..541448f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
@@ -13,7 +13,6 @@
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ast.CaseStatement;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.util.Util;
 
 public final class LocalTypeBinding extends NestedTypeBinding {
 	final static char[] LocalTypePrefix = { '$', 'L', 'o', 'c', 'a', 'l', '$' };
@@ -65,7 +64,7 @@
 
 ArrayBinding createArrayType(int dimensionCount) {
 	if (localArrayBindings == null) {
-		localArrayBindings = new ArrayBinding[] {new ArrayBinding(this, dimensionCount)};
+		localArrayBindings = new ArrayBinding[] {new ArrayBinding(this, dimensionCount, scope.environment())};
 		return localArrayBindings[0];
 	}
 
@@ -77,33 +76,63 @@
 
 	// no matching array
 	System.arraycopy(localArrayBindings, 0, localArrayBindings = new ArrayBinding[length + 1], 0, length); 
-	return localArrayBindings[length] = new ArrayBinding(this, dimensionCount);
+	return localArrayBindings[length] = new ArrayBinding(this, dimensionCount, scope.environment());
 }
 
-public char[] readableName() {
+public char[] readableName() /*java.lang.Object,  p.X<T> */ {
+    char[] readableName;
 	if (isAnonymousType()) {
 		if (superInterfaces == NoSuperInterfaces)
-			return ("<"+Util.bind("binding.subclass",new String(superclass.readableName())) + ">").toCharArray(); //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+			readableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, superclass.readableName(), TypeConstants.ANONYM_SUFFIX);
 		else
-			return ("<"+Util.bind("binding.implementation",new String(superInterfaces[0].readableName())) + ">").toCharArray();			 //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+			readableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, superInterfaces[0].readableName(), TypeConstants.ANONYM_SUFFIX);
 	} else if (isMemberType()) {
-		return CharOperation.concat(enclosingType().readableName(), sourceName, '.');
+		readableName = CharOperation.concat(enclosingType().readableName(), this.sourceName, '.');
 	} else {
-		return sourceName;
+		readableName = this.sourceName;
+	}    
+	TypeVariableBinding[] typeVars;
+	if ((typeVars = this.typeVariables()) != NoTypeVariables) {
+	    StringBuffer nameBuffer = new StringBuffer(10);
+	    nameBuffer.append(readableName).append('<');
+	    for (int i = 0, length = typeVars.length; i < length; i++) {
+	        if (i > 0) nameBuffer.append(',');
+	        nameBuffer.append(typeVars[i].readableName());
+	    }
+	    nameBuffer.append('>');
+	    int nameLength = nameBuffer.length();
+		readableName = new char[nameLength];
+		nameBuffer.getChars(0, nameLength, readableName, 0);
 	}
+	return readableName;
 }
 
-public char[] shortReadableName() {
+public char[] shortReadableName() /*Object*/ {
+    char[] shortReadableName;
 	if (isAnonymousType()) {
 		if (superInterfaces == NoSuperInterfaces)
-			return ("<"+Util.bind("binding.subclass",new String(superclass.shortReadableName())) + ">").toCharArray(); //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+			shortReadableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, superclass.shortReadableName(), TypeConstants.ANONYM_SUFFIX);
 		else
-			return ("<"+Util.bind("binding.implementation",new String(superInterfaces[0].shortReadableName())) + ">").toCharArray();			 //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+			shortReadableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, superInterfaces[0].shortReadableName(), TypeConstants.ANONYM_SUFFIX);
 	} else if (isMemberType()) {
-		return CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
+		shortReadableName = CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
 	} else {
-		return sourceName;
+		shortReadableName = sourceName;
 	}
+	TypeVariableBinding[] typeVars;
+	if ((typeVars = this.typeVariables()) != NoTypeVariables) {
+	    StringBuffer nameBuffer = new StringBuffer(10);
+	    nameBuffer.append(shortReadableName).append('<');
+	    for (int i = 0, length = typeVars.length; i < length; i++) {
+	        if (i > 0) nameBuffer.append(',');
+	        nameBuffer.append(typeVars[i].shortReadableName());
+	    }
+	    nameBuffer.append('>');
+		int nameLength = nameBuffer.length();
+		shortReadableName = new char[nameLength];
+		nameBuffer.getChars(0, nameLength, shortReadableName, 0);	    
+	}
+	return shortReadableName;
 }
 
 // Record that the type is a local member type
@@ -117,11 +146,10 @@
 
 public char[] sourceName() {
 	if (isAnonymousType()) {
-		//return readableName();
 		if (superInterfaces == NoSuperInterfaces)
-			return ("<"+Util.bind("binding.subclass",new String(superclass.sourceName())) + ">").toCharArray(); //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+			return CharOperation.concat(TypeConstants.ANONYM_PREFIX, superclass.sourceName(), TypeConstants.ANONYM_SUFFIX);
 		else
-			return ("<"+Util.bind("binding.implementation",new String(superInterfaces[0].sourceName())) + ">").toCharArray();			 //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+			return CharOperation.concat(TypeConstants.ANONYM_PREFIX, superInterfaces[0].sourceName(), TypeConstants.ANONYM_SUFFIX);
 			
 	} else
 		return sourceName;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
index 0ab99f2..9084ae4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
@@ -10,8 +10,11 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
 
 public class LocalVariableBinding extends VariableBinding {
 
@@ -30,14 +33,11 @@
 	public int initializationCount = 0;
 
 	// for synthetic local variables	
+	// if declaration slot is not positionned, the variable will not be listed in attribute
+	// note that the name of a variable should be chosen so as not to conflict with user ones (usually starting with a space char is all needed)
 	public LocalVariableBinding(char[] name, TypeBinding type, int modifiers, boolean isArgument) {
-
-		this.name = name;
-		this.type = type;
-		this.modifiers = modifiers;
+		super(name, type, modifiers, isArgument ? Constant.NotAConstant : null);
 		this.isArgument = isArgument;
-		if (isArgument)
-			this.constant = Constant.NotAConstant;
 	}
 	
 	// regular local variable or argument
@@ -50,11 +50,56 @@
 	/* API
 	* Answer the receiver's binding type from Binding.BindingID.
 	*/
-	public final int bindingType() {
+	public final int kind() {
 
 		return LOCAL;
 	}
 	
+	/*
+	 * declaringUniqueKey # scopeIndex / varName
+	 * p.X { void foo() { int local; } } --> Lp/X;.foo()V#1/local
+	 */
+	public char[] computeUniqueKey() {
+		StringBuffer buffer = new StringBuffer();
+		
+		// declaring method or type
+		BlockScope scope = this.declaringScope;
+		MethodScope methodScope = scope instanceof MethodScope ? (MethodScope) scope : scope.enclosingMethodScope();
+		ReferenceContext referenceContext = methodScope.referenceContext;
+		if (referenceContext instanceof AbstractMethodDeclaration) {
+			MethodBinding methodBinding = ((AbstractMethodDeclaration) referenceContext).binding;
+			if (methodBinding != null) {
+				buffer.append(methodBinding.computeUniqueKey());
+			}
+		} else if (referenceContext instanceof TypeDeclaration) {
+			TypeBinding typeBinding = ((TypeDeclaration) referenceContext).binding;
+			if (typeBinding != null) {
+				buffer.append(typeBinding.computeUniqueKey());
+			}
+		}
+
+		// scope index
+		getScopeKey(scope, buffer);
+
+		// variable name
+		buffer.append('#');
+		buffer.append(this.name);
+		
+		int length = buffer.length();
+		char[] uniqueKey = new char[length];
+		buffer.getChars(0, length, uniqueKey, 0);
+		return uniqueKey;
+	}
+	
+	private void getScopeKey(BlockScope scope, StringBuffer buffer) {
+		int scopeIndex = scope.scopeIndex();
+		if (scopeIndex != -1) {
+			getScopeKey((BlockScope)scope.parent, buffer);
+			buffer.append('#');
+			buffer.append(scopeIndex);
+		}
+	}
+	
 	// Answer whether the variable binding is a secret variable added for code gen purposes
 	public boolean isSecret() {
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
index a7a9c9c..686be8a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
@@ -10,51 +10,63 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
-import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.env.*;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage;
-import org.eclipse.jdt.internal.compiler.util.Util;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 
 public class LookupEnvironment implements BaseTypes, ProblemReasons, TypeConstants {
-	public CompilerOptions options;
-	public ProblemReporter problemReporter;
-	public ITypeRequestor typeRequestor;
-
-	PackageBinding defaultPackage;
-	ImportBinding[] defaultImports;
-	HashtableOfPackage knownPackages;
+	final static int BUILD_FIELDS_AND_METHODS = 4;
+	final static int BUILD_TYPE_HIERARCHY = 1;
+	final static int CHECK_AND_SET_IMPORTS = 2;
+	final static int CONNECT_TYPE_HIERARCHY = 3;
 	static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound);
 	static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR, NotFound);
+	
+	/**
+	 * Map from typeBinding -> accessRestriction rule
+	 */
+	private Map accessRestrictions;
+	ImportBinding[] defaultImports;
 
-	private INameEnvironment nameEnvironment;
-	private MethodVerifier verifier;
-	private ArrayBinding[][] uniqueArrayBindings;
-
-	private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4];
-	private int lastUnitIndex = -1;
+	PackageBinding defaultPackage;
+	HashtableOfPackage knownPackages;
 	private int lastCompletedUnitIndex = -1;
-	public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units
+	private int lastUnitIndex = -1;
+
+	public INameEnvironment nameEnvironment;
+	public CompilerOptions options;
+	public ProblemReporter problemReporter;
+
+	// shared byte[]'s used by ClassFile to avoid allocating MBs during a build
+	public boolean sharedArraysUsed = true; // set to false once actual arrays are allocated
+	public byte[] sharedClassFileContents = null;
+	public byte[] sharedClassFileHeader = null;
 
 	// indicate in which step on the compilation we are.
 	// step 1 : build the reference binding
 	// step 2 : conect the hierarchy (connect bindings)
 	// step 3 : build fields and method bindings.
 	private int stepCompleted;
-	final static int BUILD_TYPE_HIERARCHY = 1;
-	final static int CHECK_AND_SET_IMPORTS = 2;
-	final static int CONNECT_TYPE_HIERARCHY = 3;
-	final static int BUILD_FIELDS_AND_METHODS = 4;
+	public ITypeRequestor typeRequestor;
+	private ArrayBinding[][] uniqueArrayBindings;
+	private SimpleLookupTable uniqueParameterizedTypeBindings;
+	private SimpleLookupTable uniqueRawTypeBindings;
+	private SimpleLookupTable uniqueWildcardBindings;
+	
+	public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units
 
-	// shared byte[]'s used by ClassFile to avoid allocating MBs during a build
-	public boolean sharedArraysUsed = true; // set to false once actual arrays are allocated
-	public byte[] sharedClassFileHeader = null;
-	public byte[] sharedClassFileContents = null;
+	private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4];
+	private MethodVerifier verifier;
 
 public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions options, ProblemReporter problemReporter, INameEnvironment nameEnvironment) {
 	this.typeRequestor = typeRequestor;
@@ -66,10 +78,16 @@
 	this.knownPackages = new HashtableOfPackage();
 	this.uniqueArrayBindings = new ArrayBinding[5][];
 	this.uniqueArrayBindings[0] = new ArrayBinding[50]; // start off the most common 1 dimension array @ 50
+	this.uniqueParameterizedTypeBindings = new SimpleLookupTable(3);
+	this.uniqueRawTypeBindings = new SimpleLookupTable(3);
+	this.uniqueWildcardBindings = new SimpleLookupTable(3);
+	this.accessRestrictions = new HashMap(3);
 }
-/* Ask the oracle for a type which corresponds to the compoundName.
-* Answer null if the name cannot be found.
-*/
+
+/**
+ * Ask the name environment for a type which corresponds to the compoundName.
+ * Answer null if the name cannot be found.
+ */
 
 public ReferenceBinding askForType(char[][] compoundName) {
 	NameEnvironmentAnswer answer = nameEnvironment.findType(compoundName);
@@ -78,13 +96,13 @@
 
 	if (answer.isBinaryType())
 		// the type was found as a .class file
-		typeRequestor.accept(answer.getBinaryType(), computePackageFrom(compoundName));
+		typeRequestor.accept(answer.getBinaryType(), computePackageFrom(compoundName), answer.getAccessRestriction());
 	else if (answer.isCompilationUnit())
 		// the type was found as a .java file, try to build it then search the cache
-		typeRequestor.accept(answer.getCompilationUnit());
+		typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction());
 	else if (answer.isSourceType())
 		// the type was found as a source model
-		typeRequestor.accept(answer.getSourceTypes(), computePackageFrom(compoundName));
+		typeRequestor.accept(answer.getSourceTypes(), computePackageFrom(compoundName), answer.getAccessRestriction());
 
 	return getCachedType(compoundName);
 }
@@ -104,13 +122,13 @@
 
 	if (answer.isBinaryType())
 		// the type was found as a .class file
-		typeRequestor.accept(answer.getBinaryType(), packageBinding);
+		typeRequestor.accept(answer.getBinaryType(), packageBinding, answer.getAccessRestriction());
 	else if (answer.isCompilationUnit())
 		// the type was found as a .java file, try to build it then search the cache
-		typeRequestor.accept(answer.getCompilationUnit());
+		typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction());
 	else if (answer.isSourceType())
 		// the type was found as a source model
-		typeRequestor.accept(answer.getSourceTypes(), packageBinding);
+		typeRequestor.accept(answer.getSourceTypes(), packageBinding, answer.getAccessRestriction());
 
 	return packageBinding.getType0(name);
 }
@@ -121,9 +139,9 @@
 * NOTE: This method can be called multiple times as additional source files are needed
 */
 
-public void buildTypeBindings(CompilationUnitDeclaration unit) {
+public void buildTypeBindings(CompilationUnitDeclaration unit, AccessRestriction accessRestriction) {
 	CompilationUnitScope scope = new CompilationUnitScope(unit, this);
-	scope.buildTypeBindings();
+	scope.buildTypeBindings(accessRestriction);
 
 	int unitsLength = units.length;
 	if (++lastUnitIndex >= unitsLength)
@@ -135,21 +153,21 @@
 * Answer the created BinaryTypeBinding or null if the type is already in the cache.
 */
 
-public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType) {
-	return cacheBinaryType(binaryType, true);
+public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, AccessRestriction accessRestriction) {
+	return cacheBinaryType(binaryType, true, accessRestriction);
 }
 /* Cache the binary type since we know it is needed during this compile.
 *
 * Answer the created BinaryTypeBinding or null if the type is already in the cache.
 */
 
-public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, boolean needFieldsAndMethods) {
+public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, boolean needFieldsAndMethods, AccessRestriction accessRestriction) {
 	char[][] compoundName = CharOperation.splitOn('/', binaryType.getName());
 	ReferenceBinding existingType = getCachedType(compoundName);
 
 	if (existingType == null || existingType instanceof UnresolvedReferenceBinding)
 		// only add the binary type if its not already in the cache
-		return createBinaryTypeFrom(binaryType, computePackageFrom(compoundName), needFieldsAndMethods);
+		return createBinaryTypeFrom(binaryType, computePackageFrom(compoundName), needFieldsAndMethods, accessRestriction);
 	return null; // the type already exists & can be retrieved from the cache
 }
 /*
@@ -233,6 +251,61 @@
 		parsedUnit.scope.buildFieldsAndMethods();
 	this.unitBeingCompleted = null;
 }
+public TypeBinding computeBoxingType(TypeBinding type) {
+	TypeBinding boxedType;
+	switch (type.id) {
+		case TypeIds.T_JavaLangBoolean :
+			return BooleanBinding;
+		case TypeIds.T_JavaLangByte :
+			return ByteBinding;
+		case TypeIds.T_JavaLangCharacter :
+			return CharBinding;
+		case TypeIds.T_JavaLangShort :
+			return ShortBinding;
+		case TypeIds.T_JavaLangDouble :
+			return DoubleBinding;
+		case TypeIds.T_JavaLangFloat :
+			return FloatBinding;
+		case TypeIds.T_JavaLangInteger :
+			return IntBinding;
+		case TypeIds.T_JavaLangLong :
+			return LongBinding;
+
+		case TypeIds.T_int :
+			boxedType = getType(JAVA_LANG_INTEGER);
+			if (boxedType != null) return boxedType;
+			return new ProblemReferenceBinding(	JAVA_LANG_INTEGER, NotFound);				
+		case TypeIds.T_byte :
+			boxedType = getType(JAVA_LANG_BYTE);
+			if (boxedType != null) return boxedType;
+			return new ProblemReferenceBinding(	JAVA_LANG_BYTE, NotFound);				
+		case TypeIds.T_short :
+			boxedType = getType(JAVA_LANG_SHORT);
+			if (boxedType != null) return boxedType;
+			return new ProblemReferenceBinding(	JAVA_LANG_SHORT, NotFound);				
+		case TypeIds.T_char :
+			boxedType = getType(JAVA_LANG_CHARACTER);
+			if (boxedType != null) return boxedType;
+			return new ProblemReferenceBinding(	JAVA_LANG_CHARACTER, NotFound);				
+		case TypeIds.T_long :
+			boxedType = getType(JAVA_LANG_LONG);
+			if (boxedType != null) return boxedType;
+			return new ProblemReferenceBinding(	JAVA_LANG_LONG, NotFound);				
+		case TypeIds.T_float :
+			boxedType = getType(JAVA_LANG_FLOAT);
+			if (boxedType != null) return boxedType;
+			return new ProblemReferenceBinding(	JAVA_LANG_FLOAT, NotFound);				
+		case TypeIds.T_double :
+			boxedType = getType(JAVA_LANG_DOUBLE);
+			if (boxedType != null) return boxedType;
+			return new ProblemReferenceBinding(	JAVA_LANG_DOUBLE, NotFound);				
+		case TypeIds.T_boolean :
+			boxedType = getType(JAVA_LANG_BOOLEAN);
+			if (boxedType != null) return boxedType;
+			return new ProblemReferenceBinding(	JAVA_LANG_BOOLEAN, NotFound);				
+	}
+	return type;
+}	
 private PackageBinding computePackageFrom(char[][] constantPoolName) {
 	if (constantPoolName.length == 1)
 		return defaultPackage;
@@ -252,10 +325,10 @@
 	}
 	return packageBinding;
 }
+
 /* Used to guarantee array type identity.
 */
-
-ArrayBinding createArrayType(TypeBinding type, int dimensionCount) {
+public ArrayBinding createArrayType(TypeBinding type, int dimensionCount) {
 	if (type instanceof LocalTypeBinding) // cache local type arrays with the local type itself
 		return ((LocalTypeBinding) type).createArrayType(dimensionCount);
 
@@ -280,7 +353,7 @@
 	while (++index < length) {
 		ArrayBinding currentBinding = arrayBindings[index];
 		if (currentBinding == null) // no matching array, but space left
-			return arrayBindings[index] = new ArrayBinding(type, dimensionCount);
+			return arrayBindings[index] = new ArrayBinding(type, dimensionCount, this);
 		if (currentBinding.leafComponentType == type)
 			return currentBinding;
 	}
@@ -291,26 +364,26 @@
 		(arrayBindings = new ArrayBinding[length * 2]), 0,
 		length); 
 	uniqueArrayBindings[dimIndex] = arrayBindings;
-	return arrayBindings[length] = new ArrayBinding(type, dimensionCount);
+	return arrayBindings[length] = new ArrayBinding(type, dimensionCount, this);
 }
-public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding) {
-	return createBinaryTypeFrom(binaryType, packageBinding, true);
+public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+	return createBinaryTypeFrom(binaryType, packageBinding, true, accessRestriction);
 }
-public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, boolean needFieldsAndMethods) {
+public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, boolean needFieldsAndMethods, AccessRestriction accessRestriction) {
 	BinaryTypeBinding binaryBinding = new BinaryTypeBinding(packageBinding, binaryType, this);
-
+	
 	// resolve any array bindings which reference the unresolvedType
 	ReferenceBinding cachedType = packageBinding.getType0(binaryBinding.compoundName[binaryBinding.compoundName.length - 1]);
-	if (cachedType != null) {
+	if (cachedType != null) { // update reference to unresolved binding after having read classfile (knows whether generic for raw conversion)
+		// TODO (kent) suspect the check below is no longer required, since we should not be requesting a binary which is already in the cache
 		if (cachedType.isBinaryBinding()) // sanity check before the cast... at this point the cache should ONLY contain unresolved types
 			return (BinaryTypeBinding) cachedType;
 
-		UnresolvedReferenceBinding unresolvedType = (UnresolvedReferenceBinding) cachedType;
-		unresolvedType.resolvedType = binaryBinding;
-		updateArrayCache(unresolvedType, binaryBinding);
+		((UnresolvedReferenceBinding) cachedType).setResolvedType(binaryBinding, this);
 	}
 
 	packageBinding.addType(binaryBinding);
+	setAccessRestriction(binaryBinding, accessRestriction);
 	binaryBinding.cachePartsFrom(binaryType, needFieldsAndMethods);
 	return binaryBinding;
 }
@@ -348,13 +421,127 @@
 	}
 	return packageBinding;
 }
-/* Answer the type for the compoundName if it exists in the cache.
-* Answer theNotFoundType if it could not be resolved the first time
-* it was looked up, otherwise answer null.
-*
-* NOTE: Do not use for nested types... the answer is NOT the same for a.b.C or a.b.C.D.E
-* assuming C is a type in both cases. In the a.b.C.D.E case, null is the answer.
-*/
+
+public ParameterizedTypeBinding createParameterizedType(ReferenceBinding genericType, TypeBinding[] typeArguments, ReferenceBinding enclosingType) {
+
+	// cached info is array of already created parameterized types for this type
+	ParameterizedTypeBinding[] cachedInfo = (ParameterizedTypeBinding[])this.uniqueParameterizedTypeBindings.get(genericType);
+	int argLength = typeArguments == null ? 0: typeArguments.length;
+	boolean needToGrow = false;
+	if (cachedInfo != null){
+		nextCachedType : 
+			// iterate existing parameterized for reusing one with same type arguments if any
+			for (int i = 0, max = cachedInfo.length; i < max; i++){
+			    ParameterizedTypeBinding cachedType = cachedInfo[i];
+			    if (cachedType.type != genericType) continue nextCachedType; // remain of unresolved type
+			    if (cachedType.enclosingType() != enclosingType) continue nextCachedType;
+				TypeBinding[] cachedArguments = cachedType.arguments;
+				int cachedArgLength = cachedArguments == null ? 0 : cachedArguments.length;
+				if (argLength != cachedArgLength) continue nextCachedType; // would be an error situation (from unresolved binaries)
+				for (int j = 0; j < cachedArgLength; j++){
+					if (typeArguments[j] != cachedArguments[j]) continue nextCachedType;
+				}
+				// all arguments match, reuse current
+				return cachedType;
+		}
+		needToGrow = true;
+	} else {
+		cachedInfo = new ParameterizedTypeBinding[1];
+		this.uniqueParameterizedTypeBindings.put(genericType, cachedInfo);
+	}
+	// grow cache ?
+	if (needToGrow){
+		int length = cachedInfo.length;
+		System.arraycopy(cachedInfo, 0, cachedInfo = new ParameterizedTypeBinding[length+1], 0, length);
+		this.uniqueParameterizedTypeBindings.put(genericType, cachedInfo);
+	}
+	// add new binding
+	ParameterizedTypeBinding parameterizedType = new ParameterizedTypeBinding(genericType,typeArguments, enclosingType, this);
+	cachedInfo[cachedInfo.length-1] = parameterizedType;
+	return parameterizedType;
+}
+
+public RawTypeBinding createRawType(ReferenceBinding genericType, ReferenceBinding enclosingType) {
+	// cached info is array of already created raw types for this type
+	RawTypeBinding[] cachedInfo = (RawTypeBinding[])this.uniqueRawTypeBindings.get(genericType);
+	boolean needToGrow = false;
+	if (cachedInfo != null){
+		nextCachedType : 
+			// iterate existing parameterized for reusing one with same type arguments if any
+			for (int i = 0, max = cachedInfo.length; i < max; i++){
+			    RawTypeBinding cachedType = cachedInfo[i];
+			    if (cachedType.type != genericType) continue nextCachedType; // remain of unresolved type
+			    if (cachedType.enclosingType() != enclosingType) continue nextCachedType;
+				// all enclosing type match, reuse current
+				return cachedType;
+		}
+		needToGrow = true;
+	} else {
+		cachedInfo = new RawTypeBinding[1];
+		this.uniqueRawTypeBindings.put(genericType, cachedInfo);
+	}
+	// grow cache ?
+	if (needToGrow){
+		int length = cachedInfo.length;
+		System.arraycopy(cachedInfo, 0, cachedInfo = new RawTypeBinding[length+1], 0, length);
+		this.uniqueRawTypeBindings.put(genericType, cachedInfo);
+	}
+	// add new binding
+	RawTypeBinding rawType = new RawTypeBinding(genericType, enclosingType, this);
+	cachedInfo[cachedInfo.length-1] = rawType;
+	return rawType;
+	
+}
+
+public WildcardBinding createWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, int kind) {
+	
+	// cached info is array of already created wildcard  types for this type
+	WildcardBinding[] cachedInfo = (WildcardBinding[])this.uniqueWildcardBindings.get(genericType);
+	boolean needToGrow = false;
+	if (cachedInfo != null){
+		nextCachedType : 
+			// iterate existing wildcards for reusing one with same information if any
+			for (int i = 0, max = cachedInfo.length; i < max; i++){
+			    WildcardBinding cachedType = cachedInfo[i];
+			    if (cachedType.genericType != genericType) continue nextCachedType; // remain of unresolved type
+			    if (cachedType.rank != rank) continue nextCachedType;
+			    if (cachedType.kind != kind) continue nextCachedType;
+			    if (cachedType.bound != bound) continue nextCachedType;
+				// all match, reuse current
+				return cachedType;
+		}
+		needToGrow = true;
+	} else {
+		cachedInfo = new WildcardBinding[1];
+		this.uniqueWildcardBindings.put(genericType, cachedInfo);
+	}
+	// grow cache ?
+	if (needToGrow){
+		int length = cachedInfo.length;
+		System.arraycopy(cachedInfo, 0, cachedInfo = new WildcardBinding[length+1], 0, length);
+		this.uniqueWildcardBindings.put(genericType, cachedInfo);
+	}
+	// add new binding
+	WildcardBinding wildcard = new WildcardBinding(genericType, rank, bound, kind, this);
+	cachedInfo[cachedInfo.length-1] = wildcard;
+	return wildcard;
+}
+
+/**
+ * Returns the access restriction associated to a given type, or null if none
+ */
+public AccessRestriction getAccessRestriction(TypeBinding type) {
+	return (AccessRestriction) this.accessRestrictions.get(type);
+}
+
+/**
+ *  Answer the type for the compoundName if it exists in the cache.
+ * Answer theNotFoundType if it could not be resolved the first time
+ * it was looked up, otherwise answer null.
+ *
+ * NOTE: Do not use for nested types... the answer is NOT the same for a.b.C or a.b.C.D.E
+ * assuming C is a type in both cases. In the a.b.C.D.E case, null is the answer.
+ */
 
 public ReferenceBinding getCachedType(char[][] compoundName) {
 	if (compoundName.length == 1) {
@@ -405,7 +592,7 @@
 	return null;
 }
 /* Answer the type corresponding to the compoundName.
-* Ask the oracle for the type if its not in the cache.
+* Ask the name environment for the type if its not in the cache.
 * Answer null if the type cannot be found... likely a fatal error.
 */
 
@@ -444,14 +631,24 @@
 
 	if (referenceBinding == null || referenceBinding == TheNotFoundType)
 		return null;
-	if (referenceBinding instanceof UnresolvedReferenceBinding)
-		referenceBinding = ((UnresolvedReferenceBinding) referenceBinding).resolve(this);
+	referenceBinding = BinaryTypeBinding.resolveType(referenceBinding, this, false); // no raw conversion for now
 
 	// compoundName refers to a nested type incorrectly (for example, package1.A$B)
 	if (referenceBinding.isNestedType())
 		return new ProblemReferenceBinding(compoundName, InternalNameProvided);
 	return referenceBinding;
 }
+private TypeBinding[] getTypeArgumentsFromSignature(SignatureWrapper wrapper, TypeVariableBinding[] staticVariables, ReferenceBinding enclosingType, ReferenceBinding genericType) {
+	java.util.ArrayList args = new java.util.ArrayList(2);
+	int rank = 0;
+	do {
+		args.add(getTypeFromVariantTypeSignature(wrapper, staticVariables, enclosingType, genericType, rank++));
+	} while (wrapper.signature[wrapper.start] != '>');
+	wrapper.start++; // skip '>'
+	TypeBinding[] typeArguments = new TypeBinding[args.size()];
+	args.toArray(typeArguments);
+	return typeArguments;
+}
 /* Answer the type corresponding to the name from the binary file.
 * Does not ask the oracle for the type if its not found in the cache... instead an
 * unresolved type is returned which must be resolved before used.
@@ -461,7 +658,7 @@
 * NOTE: Aborts compilation if the class file cannot be found.
 */
 
-ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int end) {
+ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int end, boolean isParameterized) {
 	if (end == -1)
 		end = signature.length;
 
@@ -474,6 +671,9 @@
 	} else if (binding == TheNotFoundType) {
 		problemReporter.isClassPathCorrect(compoundName, null);
 		return null; // will not get here since the above error aborts the compilation
+	} else if (!isParameterized && binding.isGenericType()) {
+	    // check raw type, only for resolved types
+        binding = createRawType(binding, binding.enclosingType());
 	}
 	return binding;
 }
@@ -486,7 +686,7 @@
 * NOTE: Aborts compilation if the class file cannot be found.
 */
 
-TypeBinding getTypeFromSignature(char[] signature, int start, int end) {
+TypeBinding getTypeFromSignature(char[] signature, int start, int end, boolean isParameterized, TypeBinding enclosingType) {
 	int dimension = 0;
 	while (signature[start] == '[') {
 		start++;
@@ -527,19 +727,111 @@
 				binding = ShortBinding;
 				break;
 			default :
-				throw new Error(Util.bind("error.undefinedBaseType",String.valueOf(signature[start]))); //$NON-NLS-1$
+				problemReporter.corruptedSignature(enclosingType, signature, start);
+				// will never reach here, since error will cause abort
 		}
 	} else {
-		binding = getTypeFromConstantPoolName(signature, start + 1, end);
+		binding = getTypeFromConstantPoolName(signature, start + 1, end, isParameterized); // skip leading 'L' or 'T'
 	}
 
 	if (dimension == 0)
 		return binding;
 	return createArrayType(binding, dimension);
 }
+TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariableBinding[] staticVariables, ReferenceBinding enclosingType) {
+	// TypeVariableSignature = 'T' Identifier ';'
+	// ArrayTypeSignature = '[' TypeSignature
+	// ClassTypeSignature = 'L' Identifier TypeArgs(optional) ';'
+	//   or ClassTypeSignature '.' 'L' Identifier TypeArgs(optional) ';'
+	// TypeArgs = '<' VariantTypeSignature VariantTypeSignatures '>'
+	int dimension = 0;
+	while (wrapper.signature[wrapper.start] == '[') {
+		wrapper.start++;
+		dimension++;
+	}
+
+	if (wrapper.signature[wrapper.start] == 'T') {
+	    int varStart = wrapper.start + 1;
+	    int varEnd = wrapper.computeEnd();
+		for (int i = staticVariables.length; --i >= 0;)
+			if (CharOperation.equals(staticVariables[i].sourceName, wrapper.signature, varStart, varEnd))
+				return dimension == 0 ? (TypeBinding) staticVariables[i] : createArrayType(staticVariables[i], dimension);
+	    ReferenceBinding initialType = enclosingType;
+		do {
+		    if (enclosingType instanceof BinaryTypeBinding) { // per construction can only be binary type binding
+				TypeVariableBinding[] enclosingVariables = ((BinaryTypeBinding)enclosingType).typeVariables; // do not trigger resolution of variables
+				for (int i = enclosingVariables.length; --i >= 0;)
+					if (CharOperation.equals(enclosingVariables[i].sourceName, wrapper.signature, varStart, varEnd))
+						return dimension == 0 ? (TypeBinding) enclosingVariables[i] : createArrayType(enclosingVariables[i], dimension);
+		    }
+		} while ((enclosingType = enclosingType.enclosingType()) != null);
+		problemReporter.undefinedTypeVariableSignature(CharOperation.subarray(wrapper.signature, varStart, varEnd), initialType);
+		return null; // cannot reach this, since previous problem will abort compilation
+	}
+	boolean isParameterized;
+	TypeBinding type = getTypeFromSignature(wrapper.signature, wrapper.start, wrapper.computeEnd(), isParameterized = (wrapper.end == wrapper.bracket), enclosingType);
+	if (!isParameterized)
+		return dimension == 0 ? type : createArrayType(type, dimension);
+
+	// type must be a ReferenceBinding at this point, cannot be a BaseTypeBinding or ArrayTypeBinding
+	ReferenceBinding actualType = (ReferenceBinding) type;
+	TypeBinding[] typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, actualType);
+	ParameterizedTypeBinding parameterizedType = createParameterizedType(actualType, typeArguments, null);
+
+	while (wrapper.signature[wrapper.start] == '.') {
+		wrapper.start++; // skip '.'
+		char[] memberName = wrapper.nextWord();
+		BinaryTypeBinding.resolveType(parameterizedType, this, false);
+		ReferenceBinding memberType = parameterizedType.type.getMemberType(memberName);
+		if (wrapper.signature[wrapper.start] == '<') {
+			wrapper.start++; // skip '<'
+			typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, memberType);
+		} else {
+			typeArguments = null;
+		}
+		parameterizedType = createParameterizedType(memberType, typeArguments, parameterizedType);
+	}
+	wrapper.start++; // skip ';'
+	return dimension == 0 ? (TypeBinding) parameterizedType : createArrayType(parameterizedType, dimension);
+}
+TypeBinding getTypeFromVariantTypeSignature(
+	SignatureWrapper wrapper,
+	TypeVariableBinding[] staticVariables,
+	ReferenceBinding enclosingType,
+	ReferenceBinding genericType,
+	int rank) {
+	// VariantTypeSignature = '-' TypeSignature
+	//   or '+' TypeSignature
+	//   or TypeSignature
+	//   or '*'
+	switch (wrapper.signature[wrapper.start]) {
+		case '-' :
+			// ? super aType
+			wrapper.start++;
+			TypeBinding bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType);
+			return createWildcard(genericType, rank, bound, Wildcard.SUPER);
+		case '+' :
+			// ? extends aType
+			wrapper.start++;
+			bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType);
+			return createWildcard(genericType, rank, bound, Wildcard.EXTENDS);
+		case '*' :
+			// ?
+			wrapper.start++;
+			return createWildcard(genericType, rank, null, Wildcard.UNBOUND);
+		default :
+			return getTypeFromTypeSignature(wrapper, staticVariables, enclosingType);
+	}
+}
+public boolean isBoxingCompatibleWith(TypeBinding left, TypeBinding right) {
+	if (options.sourceLevel < ClassFileConstants.JDK1_5 || left.isBaseType() == right.isBaseType())
+		return false;
+
+	TypeBinding convertedType = computeBoxingType(left);
+	return convertedType == right || convertedType.isCompatibleWith(right);
+}
 /* Ask the oracle if a package exists named name in the package named compoundName.
 */
-
 boolean isPackage(char[][] compoundName, char[] name) {
 	if (compoundName == null || compoundName.length == 0)
 		return nameEnvironment.isPackage(null, name);
@@ -549,40 +841,66 @@
 
 public MethodVerifier methodVerifier() {
 	if (verifier == null)
-		verifier = new MethodVerifier(this);
+		verifier = this.options.sourceLevel < ClassFileConstants.JDK1_5
+			? new MethodVerifier(this)
+			: new MethodVerifier15(this);
 	return verifier;
 }
 public void reset() {
 	this.defaultPackage = new PackageBinding(this); // assume the default package always exists
 	this.defaultImports = null;
 	this.knownPackages = new HashtableOfPackage();
+	this.accessRestrictions = new HashMap(3);
 
 	this.verifier = null;
-	for (int i = this.uniqueArrayBindings.length; --i >= 0;)
-		this.uniqueArrayBindings[i] = null;
-	this.uniqueArrayBindings[0] = new ArrayBinding[50]; // start off the most common 1 dimension array @ 50
-
+	for (int i = this.uniqueArrayBindings.length; --i >= 0;) {
+		ArrayBinding[] arrayBindings = this.uniqueArrayBindings[i];
+		if (arrayBindings != null)
+			for (int j = arrayBindings.length; --j >= 0;)
+				arrayBindings[j] = null;
+	}
+	this.uniqueParameterizedTypeBindings = new SimpleLookupTable(3);
+	this.uniqueRawTypeBindings = new SimpleLookupTable(3);
+	this.uniqueWildcardBindings = new SimpleLookupTable(3);
+	
 	for (int i = this.units.length; --i >= 0;)
 		this.units[i] = null;
 	this.lastUnitIndex = -1;
 	this.lastCompletedUnitIndex = -1;
 	this.unitBeingCompleted = null; // in case AbortException occurred
-	
+
 	// name environment has a longer life cycle, and must be reset in
 	// the code which created it.
 }
-void updateArrayCache(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType) {
-	nextDimension : for (int i = 0, length = uniqueArrayBindings.length; i < length; i++) {
-		ArrayBinding[] arrayBindings = uniqueArrayBindings[i];
-		if (arrayBindings != null) {
-			for (int j = 0, max = arrayBindings.length; j < max; j++) {
-				ArrayBinding currentBinding = arrayBindings[j];
-				if (currentBinding == null)
-					continue nextDimension;
-				if (currentBinding.leafComponentType == unresolvedType) {
-					currentBinding.leafComponentType = resolvedType;
-					continue nextDimension;
-				}
+/**
+ * Associate a given type with some access restriction
+ * (did not store the restriction directly into binding, since sparse information)
+ */
+public void setAccessRestriction(ReferenceBinding type, AccessRestriction accessRestriction) {
+	if (accessRestriction == null) return;
+	type.modifiers |= CompilerModifiers.AccRestrictedAccess;
+	this.accessRestrictions.put(type, accessRestriction);
+}
+
+void updateCaches(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType) {
+	// walk all the unique collections & replace the unresolvedType with the resolvedType
+	// must prevent 2 entries so == still works (1 containing the unresolvedType and the other containing the resolvedType)
+	if (this.uniqueParameterizedTypeBindings.get(unresolvedType) != null) { // update the key
+		Object[] keys = this.uniqueParameterizedTypeBindings.keyTable;
+		for (int i = 0, l = keys.length; i < l; i++) {
+			if (keys[i] == unresolvedType) {
+				keys[i] = resolvedType; // hashCode is based on compoundName so this works - cannot be raw since type of parameterized type
+				break;
+			}
+		}
+	}
+
+	if (this.uniqueWildcardBindings.get(unresolvedType) != null) { // update the key
+		Object[] keys = this.uniqueWildcardBindings.keyTable;
+		for (int i = 0, l = keys.length; i < l; i++) {
+			if (keys[i] == unresolvedType) {
+				keys[i] = resolvedType; // hashCode is based on compoundName so this works
+				break;
 			}
 		}
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
index 0441fb3..7f2443f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
@@ -11,30 +11,34 @@
 package org.eclipse.jdt.internal.compiler.lookup;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
 
 public class MethodBinding extends Binding implements BaseTypes, TypeConstants {
+	
 	public int modifiers;
 	public char[] selector;
 	public TypeBinding returnType;
 	public TypeBinding[] parameters;
 	public ReferenceBinding[] thrownExceptions;
 	public ReferenceBinding declaringClass;
-
+	public TypeVariableBinding[] typeVariables = NoTypeVariables;
 	char[] signature;
-
+	public long tagBits;
+	
 protected MethodBinding() {
 	// for creating problem or synthetic method
 }
-public MethodBinding(int modifiers, char[] selector, TypeBinding returnType, TypeBinding[] args, ReferenceBinding[] exceptions, ReferenceBinding declaringClass) {
+public MethodBinding(int modifiers, char[] selector, TypeBinding returnType, TypeBinding[] parameters, ReferenceBinding[] thrownExceptions, ReferenceBinding declaringClass) {
 	this.modifiers = modifiers;
 	this.selector = selector;
 	this.returnType = returnType;
-	this.parameters = (args == null || args.length == 0) ? NoParameters : args;
-	this.thrownExceptions = (exceptions == null || exceptions.length == 0) ? NoExceptions : exceptions;
+	this.parameters = (parameters == null || parameters.length == 0) ? NoParameters : parameters;
+	this.thrownExceptions = (thrownExceptions == null || thrownExceptions.length == 0) ? NoExceptions : thrownExceptions;
 	this.declaringClass = declaringClass;
-
+	
 	// propagate the strictfp & deprecated modifiers
 	if (this.declaringClass != null) {
 		if (this.declaringClass.isStrictfp())
@@ -44,8 +48,8 @@
 			this.modifiers |= AccDeprecatedImplicitly;
 	}
 }
-public MethodBinding(int modifiers, TypeBinding[] args, ReferenceBinding[] exceptions, ReferenceBinding declaringClass) {
-	this(modifiers, ConstructorDeclaration.ConstantPoolName, VoidBinding, args, exceptions, declaringClass);
+public MethodBinding(int modifiers, TypeBinding[] parameters, ReferenceBinding[] thrownExceptions, ReferenceBinding declaringClass) {
+	this(modifiers, TypeConstants.INIT, VoidBinding, parameters, thrownExceptions, declaringClass);
 }
 // special API used to change method declaring class for runtime visibility check
 public MethodBinding(MethodBinding initialMethodBinding, ReferenceBinding declaringClass) {
@@ -58,7 +62,6 @@
 }
 /* Answer true if the argument types & the receiver's parameters are equal
 */
-
 public final boolean areParametersEqual(MethodBinding method) {
 	TypeBinding[] args = method.parameters;
 	if (parameters == args)
@@ -73,12 +76,65 @@
 			return false;
 	return true;
 }
+public final boolean areParametersCompatibleWith(TypeBinding[] arguments) {
+	int paramLength = this.parameters.length;
+	int argLength = arguments.length;
+	int lastIndex = argLength;
+	if (isVarargs()) {
+		lastIndex = paramLength - 1;
+		if (paramLength == argLength) { // accept X[] but not X or X[][]
+			TypeBinding varArgType = parameters[lastIndex]; // is an ArrayBinding by definition
+			TypeBinding lastArgument = arguments[lastIndex];
+			if (varArgType != lastArgument && !lastArgument.isCompatibleWith(varArgType))
+				return false;
+		} else if (paramLength < argLength) { // all remainig argument types must be compatible with the elementsType of varArgType
+			TypeBinding varArgType = ((ArrayBinding) parameters[lastIndex]).elementsType();
+			for (int i = lastIndex; i < argLength; i++)
+				if (varArgType != arguments[i] && !arguments[i].isCompatibleWith(varArgType))
+					return false;
+		} else if (lastIndex != argLength) { // can call foo(int i, X ... x) with foo(1) but NOT foo();
+			return false;
+		}
+		// now compare standard arguments from 0 to lastIndex
+	}
+	for (int i = 0; i < lastIndex; i++)
+		if (parameters[i] != arguments[i] && !arguments[i].isCompatibleWith(parameters[i]))
+			return false;
+	return true;
+}
+
+/* Answer true if the argument types & the receiver's parameters have the same erasure
+*/
+public final boolean areParameterErasuresEqual(MethodBinding method) {
+	TypeBinding[] args = method.parameters;
+	if (parameters == args)
+		return true;
+
+	int length = parameters.length;
+	if (length != args.length)
+		return false;
+
+	for (int i = 0; i < length; i++)
+		if (parameters[i] != args[i] && parameters[i].erasure() != args[i].erasure())
+			return false;
+	return true;
+}
 /* API
 * Answer the receiver's binding type from Binding.BindingID.
 */
 
-public final int bindingType() {
-	return METHOD;
+public final int kind() {
+	return Binding.METHOD;
+}
+/* Answer true if the receiver is visible to the invocationPackage.
+*/
+
+public final boolean canBeSeenBy(PackageBinding invocationPackage) {
+	if (isPublic()) return true;
+	if (isPrivate()) return false;
+
+	// isProtected() or isDefault()
+	return invocationPackage == declaringClass.getPackage();
 }
 /* Answer true if the receiver is visible to the type provided by the scope.
 * InvocationSite implements isSuperAccess() to provide additional information
@@ -111,7 +167,7 @@
 			temp = temp.enclosingType();
 		}
 
-		ReferenceBinding outerDeclaringClass = declaringClass;
+		ReferenceBinding outerDeclaringClass = (ReferenceBinding)declaringClass.erasure();
 		temp = outerDeclaringClass.enclosingType();
 		while (temp != null) {
 			outerDeclaringClass = temp;
@@ -173,7 +229,15 @@
 	if (isPrivate()) {
 		// answer true if the receiverType is the declaringClass
 		// AND the invocationType and the declaringClass have a common enclosingType
-		if (receiverType != declaringClass) return false;
+		receiverCheck: {
+			if (receiverType != declaringClass) {
+				// special tolerance for type variable direct bounds
+				if (receiverType.isTypeVariable() && ((TypeVariableBinding) receiverType).isErasureBoundTo(declaringClass.erasure())) {
+					break receiverCheck;
+				}
+				return false;
+			}
+		}
 
 		if (invocationType != declaringClass) {
 			ReferenceBinding outerInvocationType = invocationType;
@@ -183,7 +247,7 @@
 				temp = temp.enclosingType();
 			}
 
-			ReferenceBinding outerDeclaringClass = declaringClass;
+			ReferenceBinding outerDeclaringClass = (ReferenceBinding)declaringClass.erasure();
 			temp = outerDeclaringClass.enclosingType();
 			while (temp != null) {
 				outerDeclaringClass = temp;
@@ -208,6 +272,34 @@
 	} while ((type = type.superclass()) != null);
 	return false;
 }
+/*
+ * declaringUniqueKey dot selector genericSignature
+ * p.X { <T> void bar(X<T> t) } --> Lp/X;.bar<T:Ljava/lang/Object;>(LX<TT;>;)V
+ */
+public char[] computeUniqueKey() {
+	return computeUniqueKey(this);
+}
+protected char[] computeUniqueKey(MethodBinding methodBinding) {
+	// declaring class 
+	char[] declaringKey = this.declaringClass.computeUniqueKey();
+	int declaringLength = declaringKey.length;
+	
+	// selector
+	int selectorLength = this.selector == TypeConstants.INIT ? 0 : this.selector.length;
+	
+	// generic signature
+	char[] sig = methodBinding.genericSignature();
+	if (sig == null) sig = methodBinding.signature();
+	int signatureLength = sig.length;
+	
+	// compute unique key
+	char[] uniqueKey = new char[declaringLength + 1 + selectorLength + signatureLength];
+	System.arraycopy(declaringKey, 0, uniqueKey, 0, declaringLength);
+	uniqueKey[declaringLength] = '.';
+	System.arraycopy(this.selector, 0, uniqueKey, declaringLength+1, selectorLength);
+	System.arraycopy(sig, 0, uniqueKey, declaringLength + 1 + selectorLength, signatureLength);
+	return uniqueKey;
+}
 /* 
  * Answer the declaring class to use in the constant pool
  * may not be a reference binding (see subtypes)
@@ -224,10 +316,88 @@
 public final char[] constantPoolName() {
 	return selector;
 }
+/**
+ *<typeParam1 ... typeParamM>(param1 ... paramN)returnType thrownException1 ... thrownExceptionP
+ * T foo(T t) throws X<T>   --->   (TT;)TT;LX<TT;>;
+ * void bar(X<T> t)   -->   (LX<TT;>;)V
+ * <T> void bar(X<T> t)   -->  <T:Ljava.lang.Object;>(LX<TT;>;)V
+ */
+public char[] genericSignature() {
+	if ((this.modifiers & AccGenericSignature) == 0) return null;
+	StringBuffer sig = new StringBuffer(10);
+	if (this.typeVariables != NoTypeVariables) {
+		sig.append('<');
+		for (int i = 0, length = this.typeVariables.length; i < length; i++) {
+			sig.append(this.typeVariables[i].genericSignature());
+		}
+		sig.append('>');
+	}
+	sig.append('(');
+	for (int i = 0, length = this.parameters.length; i < length; i++) {
+		sig.append(this.parameters[i].genericTypeSignature());
+	}
+	sig.append(')');
+	if (this.returnType != null)
+		sig.append(this.returnType.genericTypeSignature());
+	
+	// only append thrown exceptions if any is generic/parameterized
+	boolean needExceptionSignatures = false;
+	int length = this.thrownExceptions.length;
+	for (int i = 0; i < length; i++) {
+		if((this.thrownExceptions[i].modifiers & AccGenericSignature) != 0) {
+			needExceptionSignatures = true;
+			break;
+		}
+	}
+	if (needExceptionSignatures) {
+		for (int i = 0; i < length; i++) {
+			sig.append(this.thrownExceptions[i].genericTypeSignature());
+		}
+	}
+	int sigLength = sig.length();
+	char[] genericSignature = new char[sigLength];
+	sig.getChars(0, sigLength, genericSignature, 0);	
+	return genericSignature;
+}
 public final int getAccessFlags() {
 	return modifiers & AccJustFlag;
 }
 
+/**
+ * Compute the tagbits for standard annotations. For source types, these could require
+ * lazily resolving corresponding annotation nodes, in case of forward references.
+ * @see org.eclipse.jdt.internal.compiler.lookup.Binding#getAnnotationTagBits()
+ */
+public long getAnnotationTagBits() {
+	MethodBinding originalMethod = this.original();
+	if ((originalMethod.tagBits & TagBits.AnnotationResolved) == 0 && originalMethod.declaringClass instanceof SourceTypeBinding) {
+		TypeDeclaration typeDecl = ((SourceTypeBinding)originalMethod.declaringClass).scope.referenceContext;
+		AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(originalMethod);
+		ASTNode.resolveAnnotations(methodDecl.scope, methodDecl.annotations, originalMethod);
+	}
+	return originalMethod.tagBits;
+}
+
+public TypeVariableBinding getTypeVariable(char[] variableName) {
+	for (int i = this.typeVariables.length; --i >= 0;)
+		if (CharOperation.equals(this.typeVariables[i].sourceName, variableName))
+			return this.typeVariables[i];
+	return null;
+}
+/**
+ * Returns true if method got substituted parameter types
+ * (see ParameterizedMethodBinding)
+ */
+public boolean hasSubstitutedParameters() {
+	return false;
+}
+
+/* Answer true if the return type got substituted.
+ */
+public boolean hasSubstitutedReturnType() {
+	return false;
+}
+
 /* Answer true if the receiver is an abstract method
 */
 public final boolean isAbstract() {
@@ -243,10 +413,7 @@
 /* Answer true if the receiver is a constructor
 */
 public final boolean isConstructor() {
-	return selector == ConstructorDeclaration.ConstantPoolName;
-}
-protected boolean isConstructorRelated() {
-	return isConstructor();
+	return selector == TypeConstants.INIT;
 }
 
 /* Answer true if the receiver has default visibility
@@ -363,9 +530,9 @@
 	return (modifiers & AccSynthetic) != 0;
 }
 
-/* Answer true if the receiver is a vararg method
+/* Answer true if the receiver method has varargs
 */
-public final boolean isVararg() {
+public final boolean isVarargs() {
 	return (modifiers & AccVarargs) != 0;
 }
 
@@ -376,6 +543,13 @@
 		(modifiers & AccDeprecatedImplicitly) != 0;
 }
 
+/**
+ * Returns the original method (as opposed to parameterized instances)
+ */
+public MethodBinding original() {
+	return this;
+}
+
 public char[] readableName() /* foo(int, Thread) */ {
 	StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
 	if (isConstructor())
@@ -412,7 +586,10 @@
 		}
 	}
 	buffer.append(')');
-	return buffer.toString().toCharArray();
+	int nameLength = buffer.length();
+	char[] shortReadableName = new char[nameLength];
+	buffer.getChars(0, nameLength, shortReadableName, 0);	    
+	return shortReadableName;
 }
 
 protected final void setSelector(char[] selector) {
@@ -434,9 +611,13 @@
 	buffer.append('(');
 	
 	TypeBinding[] targetParameters = this.parameters;
-	boolean considerSynthetics = isConstructorRelated() && declaringClass.isNestedType();
-	if (considerSynthetics) {
-		
+	boolean isConstructor = isConstructor();
+	if (isConstructor && declaringClass.isEnum()) { // insert String name,int ordinal 
+		buffer.append(ConstantPool.JavaLangStringSignature);
+		buffer.append(BaseTypes.IntBinding.signature());
+	}
+	boolean needSynthetics = isConstructor && declaringClass.isNestedType();
+	if (needSynthetics) {
 		// take into account the synthetic argument type signatures as well
 		ReferenceBinding[] syntheticArgumentTypes = declaringClass.syntheticEnclosingInstanceTypes();
 		int count = syntheticArgumentTypes == null ? 0 : syntheticArgumentTypes.length;
@@ -444,8 +625,8 @@
 			buffer.append(syntheticArgumentTypes[i].signature());
 		}
 		
-		if (this instanceof SyntheticAccessMethodBinding) {
-			targetParameters = ((SyntheticAccessMethodBinding)this).targetMethod.parameters;
+		if (this instanceof SyntheticMethodBinding) {
+			targetParameters = ((SyntheticMethodBinding)this).targetMethod.parameters;
 		}
 	}
 
@@ -454,7 +635,7 @@
 			buffer.append(targetParameters[i].signature());
 		}
 	}
-	if (considerSynthetics) {
+	if (needSynthetics) {
 		SyntheticArgumentBinding[] syntheticOuterArguments = declaringClass.syntheticOuterLocalVariables();
 		int count = syntheticOuterArguments == null ? 0 : syntheticOuterArguments.length;
 		for (int i = 0; i < count; i++) {
@@ -466,8 +647,13 @@
 		}
 	}
 	buffer.append(')');
-	buffer.append(returnType.signature());
-	return signature = buffer.toString().toCharArray();
+	if (this.returnType != null)
+		buffer.append(this.returnType.signature());
+	int nameLength = buffer.length();
+	signature = new char[nameLength];
+	buffer.getChars(0, nameLength, signature, 0);	    
+	
+	return signature;
 }
 public final int sourceEnd() {
 	AbstractMethodDeclaration method = sourceMethod();
@@ -475,7 +661,7 @@
 		return 0;
 	return method.sourceEnd;
 }
-AbstractMethodDeclaration sourceMethod() {
+public AbstractMethodDeclaration sourceMethod() {
 	SourceTypeBinding sourceType;
 	try {
 		sourceType = (SourceTypeBinding) declaringClass;
@@ -495,6 +681,7 @@
 		return 0;
 	return method.sourceStart;
 }
+
 /* During private access emulation, the binding can be requested to loose its
  * private visibility when the class file is dumped.
  */
@@ -535,4 +722,14 @@
 	}
 	return s;
 }
+/**
+ * Returns the method to use during tiebreak (usually the method itself).
+ * For generic method invocations, tiebreak needs to use generic method with erasure substitutes.
+ */
+public MethodBinding tiebreakMethod() {
+	return this;
+}
+public TypeVariableBinding[] typeVariables() {
+	return this.typeVariables;
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
index 92b806b..67cf2dd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
@@ -16,6 +16,7 @@
 import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
 import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo;
@@ -84,15 +85,11 @@
 		int unexpectedModifiers =
 			~(AccPublic | AccPrivate | AccProtected | AccStrictfp);
 		if ((realModifiers & unexpectedModifiers) != 0)
-			problemReporter().illegalModifierForMethod(
-				methodBinding.declaringClass,
-				(AbstractMethodDeclaration) referenceContext);
+			problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext);
 		else if (
 			(((AbstractMethodDeclaration) referenceContext).modifiers & AccStrictfp) != 0)
 			// must check the parse node explicitly
-			problemReporter().illegalModifierForMethod(
-				methodBinding.declaringClass,
-				(AbstractMethodDeclaration) referenceContext);
+			problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext);
 
 		// check for incompatible modifiers in the visibility bits, isolate the visibility bits
 		int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
@@ -104,19 +101,19 @@
 			// need to keep the less restrictive
 			if ((accessorBits & AccPublic) != 0) {
 				if ((accessorBits & AccProtected) != 0)
-					modifiers ^= AccProtected;
+					modifiers &= ~AccProtected;
 				if ((accessorBits & AccPrivate) != 0)
-					modifiers ^= AccPrivate;
+					modifiers &= ~AccPrivate;
 			}
 			if ((accessorBits & AccProtected) != 0)
 				if ((accessorBits & AccPrivate) != 0)
-					modifiers ^= AccPrivate;
+					modifiers &= ~AccPrivate;
 		}
 
 		// if the receiver's declaring class is a private nested type, then make sure the receiver is not private (causes problems for inner type emulation)
 		if (methodBinding.declaringClass.isPrivate())
 			if ((modifiers & AccPrivate) != 0)
-				modifiers ^= AccPrivate;
+				modifiers &= ~AccPrivate;
 
 		methodBinding.modifiers = modifiers;
 	}
@@ -134,12 +131,15 @@
 		// after this point, tests on the 16 bits reserved.
 		int realModifiers = modifiers & AccJustFlag;
 
-		// set the requested modifiers for a method in an interface
-		if (methodBinding.declaringClass.isInterface()) {
-			if ((realModifiers & ~(AccPublic | AccAbstract)) != 0)
-				problemReporter().illegalModifierForInterfaceMethod(
-					methodBinding.declaringClass,
-					(AbstractMethodDeclaration) referenceContext);
+		// set the requested modifiers for a method in an interface/annotation
+		if ((methodBinding.declaringClass.modifiers & AccInterface) != 0) {
+			if ((realModifiers & ~(AccPublic | AccAbstract)) != 0) {
+				if ((methodBinding.declaringClass.modifiers & AccAnnotation) != 0) {
+					problemReporter().illegalModifierForAnnotationMember((AbstractMethodDeclaration) referenceContext);
+				} else {
+					problemReporter().illegalModifierForInterfaceMethod((AbstractMethodDeclaration) referenceContext);
+				}
+			}
 			return;
 		}
 
@@ -156,9 +156,7 @@
 					| AccNative
 					| AccStrictfp);
 		if ((realModifiers & unexpectedModifiers) != 0)
-			problemReporter().illegalModifierForMethod(
-				methodBinding.declaringClass,
-				(AbstractMethodDeclaration) referenceContext);
+			problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext);
 
 		// check for incompatible modifiers in the visibility bits, isolate the visibility bits
 		int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
@@ -170,13 +168,13 @@
 			// need to keep the less restrictive
 			if ((accessorBits & AccPublic) != 0) {
 				if ((accessorBits & AccProtected) != 0)
-					modifiers ^= AccProtected;
+					modifiers &= ~AccProtected;
 				if ((accessorBits & AccPrivate) != 0)
-					modifiers ^= AccPrivate;
+					modifiers &= ~AccPrivate;
 			}
 			if ((accessorBits & AccProtected) != 0)
 				if ((accessorBits & AccPrivate) != 0)
-					modifiers ^= AccPrivate;
+					modifiers &= ~AccPrivate;
 		}
 
 		// check for modifiers incompatible with abstract modifier
@@ -300,19 +298,38 @@
 		SourceTypeBinding declaringClass = referenceType().binding;
 		int modifiers = method.modifiers | AccUnresolved;
 		if (method.isConstructor()) {
-			if (method.isDefaultConstructor()) {
+			if (method.isDefaultConstructor())
 				modifiers |= AccIsDefaultConstructor;
-			}
 			method.binding = new MethodBinding(modifiers, null, null, declaringClass);
 			checkAndSetModifiersForConstructor(method.binding);
 		} else {
-			if (declaringClass.isInterface())
+			if ((declaringClass.modifiers & AccInterface) != 0) // interface or annotation type
 				modifiers |= AccPublic | AccAbstract;
 			method.binding =
 				new MethodBinding(modifiers, method.selector, null, null, null, declaringClass);
 			checkAndSetModifiersForMethod(method.binding);
 		}
 		this.isStatic = method.binding.isStatic();
+
+		Argument[] argTypes = method.arguments;
+		int argLength = argTypes == null ? 0 : argTypes.length;
+		if (argLength > 0 && environment().options.sourceLevel >= ClassFileConstants.JDK1_5) {
+			if (argTypes[--argLength].isVarArgs())
+				method.binding.modifiers |= AccVarargs;
+			while (--argLength >= 0) {
+				if (argTypes[argLength].isVarArgs())
+					problemReporter().illegalVararg(argTypes[argLength], method);
+			}
+		}
+		
+		TypeParameter[] typeParameters = method.typeParameters();
+	    // do not construct type variables if source < 1.5
+		if (typeParameters == null || environment().options.sourceLevel < ClassFileConstants.JDK1_5) {
+		    method.binding.typeVariables = NoTypeVariables;
+		} else {
+			method.binding.typeVariables = createTypeVariables(typeParameters, method.binding);
+			method.binding.modifiers |= AccGenericSignature;
+		}
 		return method.binding;
 	}
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
index 05ebfa1..e47cdd3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
@@ -10,13 +10,13 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
-import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.env.IConstants;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
 
-public final class MethodVerifier implements TagBits, TypeConstants {
+public class MethodVerifier implements TagBits, TypeConstants {
 	SourceTypeBinding type;
 	HashtableOfObject inheritedMethods;
 	HashtableOfObject currentMethods;
@@ -40,7 +40,7 @@
 		- defining a static class or interface inside a non-static nested class
 		- defining an interface as a local type (local types can only be classes)
 */
-public MethodVerifier(LookupEnvironment environment) {
+MethodVerifier(LookupEnvironment environment) {
 	this.type = null;  // Initialized with the public method verify(SourceTypeBinding)
 	this.inheritedMethods = null;
 	this.currentMethods = null;
@@ -48,7 +48,10 @@
 	this.errorException = null;
 	this.environment = environment;
 }
-private boolean areParametersEqual(MethodBinding one, MethodBinding two) {
+boolean areMethodsEqual(MethodBinding one, MethodBinding two) {
+	return areParametersEqual(one, two);
+}
+boolean areParametersEqual(MethodBinding one, MethodBinding two) {
 	TypeBinding[] oneArgs = one.parameters;
 	TypeBinding[] twoArgs = two.parameters;
 	if (oneArgs == twoArgs) return true;
@@ -60,42 +63,79 @@
 		if (!areTypesEqual(oneArgs[i], twoArgs[i])) return false;
 	return true;
 }
-private boolean areTypesEqual(TypeBinding one, TypeBinding two) {
+boolean areReturnTypesEqual(MethodBinding one, MethodBinding two) {
+	return areTypesEqual(one.returnType, two.returnType);
+}
+boolean canSkipInheritedMethods() {
+	if (this.type.superclass() != null && this.type.superclass().isAbstract())
+		return false;
+	return this.type.superInterfaces() == NoSuperInterfaces;
+}
+boolean canSkipInheritedMethods(MethodBinding one, MethodBinding two) {
+	return two == null // already know one is not null
+		|| one.declaringClass == two.declaringClass;
+}
+boolean areTypesEqual(TypeBinding one, TypeBinding two) {
 	if (one == two) return true;
-	if (one instanceof ReferenceBinding && two instanceof ReferenceBinding)
-		// can compare unresolved to resolved reference bindings
-		return CharOperation.equals(((ReferenceBinding) one).compoundName, ((ReferenceBinding) two).compoundName);
+
+	// its possible that an UnresolvedReferenceBinding can be compared to its resolved type
+	// when they're both UnresolvedReferenceBindings then they must be identical like all other types
+	// all wrappers of UnresolvedReferenceBindings are converted as soon as the type is resolved
+	// so its not possible to have 2 arrays where one is UnresolvedX[] and the other is X[]
+	if (one instanceof UnresolvedReferenceBinding)
+		return ((UnresolvedReferenceBinding) one).resolvedType == two;
+	if (two instanceof UnresolvedReferenceBinding)
+		return ((UnresolvedReferenceBinding) two).resolvedType == one;
 	return false; // all other type bindings are identical
 }
-private void checkAbstractMethod(MethodBinding abstractMethod) {
-	if (mustImplementAbstractMethod(abstractMethod)) {
+void checkAbstractMethod(MethodBinding abstractMethod) {
+	if (mustImplementAbstractMethod(abstractMethod.declaringClass)) {
 		TypeDeclaration typeDeclaration = this.type.scope.referenceContext;
 		if (typeDeclaration != null) {
 			MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(abstractMethod);
 			missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, abstractMethod);
 		} else {
-			this.problemReporter().abstractMethodMustBeImplemented(this.type, abstractMethod);
+			problemReporter().abstractMethodMustBeImplemented(this.type, abstractMethod);
 		}
 	}
 }
-private void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBinding[] methods, int length) {
-	currentMethod.modifiers |= CompilerModifiers.AccOverriding;
+void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBinding[] methods, int length) {
+	boolean isAnnotationMember = this.type.isAnnotationType();
 	nextMethod : for (int i = length; --i >= 0;) {
 		MethodBinding inheritedMethod = methods[i];
-		if (!currentMethod.isAbstract() && inheritedMethod.isAbstract())
-			currentMethod.modifiers |= CompilerModifiers.AccImplementing;
+		if (currentMethod.isStatic() != inheritedMethod.isStatic()) {  // Cannot override a static method or hide an instance method
+			problemReporter(currentMethod).staticAndInstanceConflict(currentMethod, inheritedMethod);
+			continue nextMethod;
+		}
 
-		if (!areTypesEqual(currentMethod.returnType, inheritedMethod.returnType)) {
-			this.problemReporter(currentMethod).incompatibleReturnType(currentMethod, inheritedMethod);
-		} else if (currentMethod.isStatic() != inheritedMethod.isStatic()) {  // Cannot override a static method or hide an instance method
-			this.problemReporter(currentMethod).staticAndInstanceConflict(currentMethod, inheritedMethod);
+		if (inheritedMethod.isAbstract()) {
+			if (inheritedMethod.declaringClass.isInterface()) {
+				currentMethod.modifiers |= CompilerModifiers.AccImplementing;
+			} else {
+				currentMethod.modifiers |= CompilerModifiers.AccImplementing | CompilerModifiers.AccOverriding;
+			}
+// with the above change an abstract method is tagged as implementing the inherited abstract method
+//		if (!currentMethod.isAbstract() && inheritedMethod.isAbstract()) {
+//			if ((currentMethod.modifiers & CompilerModifiers.AccOverriding) == 0)
+//				currentMethod.modifiers |= CompilerModifiers.AccImplementing;
+		} else {
+			currentMethod.modifiers |= CompilerModifiers.AccOverriding;
+		}
+
+		if (isAnnotationMember) {
+			// annotation cannot override any method
+			problemReporter().annotationCannotOverrideMethod(currentMethod, inheritedMethod);
+			return; // do not repoort against subsequent inherited methods
+		}		
+		if (!areReturnTypesEqual(currentMethod, inheritedMethod)) {
+			problemReporter(currentMethod).incompatibleReturnType(currentMethod, inheritedMethod);
 		} else {
 			if (currentMethod.thrownExceptions != NoExceptions)
-				this.checkExceptions(currentMethod, inheritedMethod);
+				checkExceptions(currentMethod, inheritedMethod);
 			if (inheritedMethod.isFinal())
-				this.problemReporter(currentMethod).finalMethodCannotBeOverridden(currentMethod, inheritedMethod);
-			if (!this.isAsVisible(currentMethod, inheritedMethod))
-				this.problemReporter(currentMethod).visibilityConflict(currentMethod, inheritedMethod);
+				problemReporter(currentMethod).finalMethodCannotBeOverridden(currentMethod, inheritedMethod);
+			if (!isAsVisible(currentMethod, inheritedMethod))
+				problemReporter(currentMethod).visibilityConflict(currentMethod, inheritedMethod);
 			if (environment.options.reportDeprecationWhenOverridingDeprecatedMethod && inheritedMethod.isViewedAsDeprecated()) {
 				if (!currentMethod.isViewedAsDeprecated() || environment.options.reportDeprecationInsideDeprecatedCode) {
 					// check against the other inherited methods to see if they hide this inheritedMethod
@@ -105,9 +145,10 @@
 							if (i != j && methods[j].declaringClass.implementsInterface(declaringClass, false))
 								continue nextMethod;
 
-					this.problemReporter(currentMethod).overridesDeprecatedMethod(currentMethod, inheritedMethod);
+					problemReporter(currentMethod).overridesDeprecatedMethod(currentMethod, inheritedMethod);
 				}
 			}
+			checkForBridgeMethod(currentMethod, inheritedMethod);
 		}
 	}
 }
@@ -117,24 +158,27 @@
 Assumes all exceptions are valid and throwable.
 Unchecked exceptions (compatible with runtime & error) are ignored (see the spec on pg. 203).
 */
-private void checkExceptions(MethodBinding newMethod, MethodBinding inheritedMethod) {
+void checkExceptions(MethodBinding newMethod, MethodBinding inheritedMethod) {
 	ReferenceBinding[] newExceptions = resolvedExceptionTypesFor(newMethod);
 	ReferenceBinding[] inheritedExceptions = resolvedExceptionTypesFor(inheritedMethod);
 	for (int i = newExceptions.length; --i >= 0;) {
 		ReferenceBinding newException = newExceptions[i];
 		int j = inheritedExceptions.length;
-		while (--j > -1 && !this.isSameClassOrSubclassOf(newException, inheritedExceptions[j])){/*empty*/}
+		while (--j > -1 && !isSameClassOrSubclassOf(newException, inheritedExceptions[j])){/*empty*/}
 		if (j == -1)
-			if (!(newException.isCompatibleWith(this.runtimeException()) || newException.isCompatibleWith(this.errorException())))
-				this.problemReporter(newMethod).incompatibleExceptionInThrowsClause(this.type, newMethod, inheritedMethod, newException);
+			if (!(newException.isCompatibleWith(runtimeException()) || newException.isCompatibleWith(errorException())))
+				problemReporter(newMethod).incompatibleExceptionInThrowsClause(this.type, newMethod, inheritedMethod, newException);
 	}
 }
-private void checkInheritedMethods(MethodBinding[] methods, int length) {
-	TypeBinding returnType = methods[0].returnType;
+void checkForBridgeMethod(MethodBinding currentMethod, MethodBinding inheritedMethod) {
+	// no op before 1.5
+}
+void checkInheritedMethods(MethodBinding[] methods, int length) {
+	MethodBinding first = methods[0];
 	int index = length;
-	while (--index > 0 && areTypesEqual(returnType, methods[index].returnType)){/*empty*/}
+	while (--index > 0 && areReturnTypesEqual(first, methods[index])){/*empty*/}
 	if (index > 0) {  // All inherited methods do NOT have the same vmSignature
-		this.problemReporter().inheritedMethodsHaveIncompatibleReturnTypes(this.type, methods, length);
+		problemReporter().inheritedMethodsHaveIncompatibleReturnTypes(this.type, methods, length);
 		return;
 	}
 
@@ -150,13 +194,13 @@
 	if (concreteMethod == null) {
 		if (this.type.isClass() && !this.type.isAbstract()) {
 			for (int i = length; --i >= 0;) {
-				if (mustImplementAbstractMethod(methods[i])) {
+				if (mustImplementAbstractMethod(methods[i].declaringClass)) {
 					TypeDeclaration typeDeclaration = this.type.scope.referenceContext;
 					if (typeDeclaration != null) {
 						MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(methods[0]);
 						missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
 					} else {
-						this.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
+						problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
 					}
 					return;
 				}
@@ -174,13 +218,13 @@
 	// Remember that interfaces can only define public instance methods
 	if (concreteMethod.isStatic())
 		// Cannot inherit a static method which is specified as an instance method by an interface
-		this.problemReporter().staticInheritedMethodConflicts(type, concreteMethod, abstractMethods);	
+		problemReporter().staticInheritedMethodConflicts(type, concreteMethod, abstractMethods);	
 	if (!concreteMethod.isPublic())
 		// Cannot reduce visibility of a public method specified by an interface
-		this.problemReporter().inheritedMethodReducesVisibility(type, concreteMethod, abstractMethods);
+		problemReporter().inheritedMethodReducesVisibility(type, concreteMethod, abstractMethods);
 	if (concreteMethod.thrownExceptions != NoExceptions)
 		for (int i = abstractMethods.length; --i >= 0;)
-			this.checkExceptions(concreteMethod, abstractMethods[i]);
+			checkExceptions(concreteMethod, abstractMethods[i]);
 }
 /*
 For each inherited method identifier (message pattern - vm signature minus the return type)
@@ -200,10 +244,9 @@
 				else
 					complain about missing implementation only if type is NOT an interface or abstract
 */
-private void checkMethods() {
-	boolean mustImplementAbstractMethods = this.type.isClass() && !this.type.isAbstract();
-	boolean skipInheritedMethods = mustImplementAbstractMethods && this.type.superInterfaces() == NoSuperInterfaces
-		&& this.type.superclass() != null && !this.type.superclass().isAbstract(); // have a single concrete superclass so only check overridden methods
+void checkMethods() {
+	boolean mustImplementAbstractMethods = ((this.type.modifiers & IConstants.AccInterface) == 0) && !this.type.isAbstract();
+	boolean skipInheritedMethods = mustImplementAbstractMethods && canSkipInheritedMethods(); // have a single concrete superclass so only check overridden methods
 	char[][] methodSelectors = this.inheritedMethods.keyTable;
 	nextSelector : for (int s = methodSelectors.length; --s >= 0;) {
 		if (methodSelectors[s] == null) continue nextSelector;
@@ -226,54 +269,68 @@
 				while (index >= 0) matchingInherited[index--] = null; // clear the previous contents of the matching methods
 				MethodBinding currentMethod = current[i];
 				for (int j = 0, length2 = inherited.length; j < length2; j++) {
-					if (inherited[j] != null && areParametersEqual(currentMethod, inherited[j])) {
-						matchingInherited[++index] = inherited[j];
-						inherited[j] = null; // do not want to find it again
+					MethodBinding inheritedMethod = inherited[j];
+					if (inheritedMethod != null) {
+						inheritedMethod = computeSubstituteMethod(inheritedMethod, currentMethod);
+						if (areMethodsEqual(currentMethod, inheritedMethod)) {
+							matchingInherited[++index] = inheritedMethod;
+							inherited[j] = null; // do not want to find it again
+						}
 					}
 				}
 				if (index >= 0)
-					this.checkAgainstInheritedMethods(currentMethod, matchingInherited, index + 1); // pass in the length of matching
+					checkAgainstInheritedMethods(currentMethod, matchingInherited, index + 1); // pass in the length of matching
 			}
 		}
 
 		for (int i = 0, length = inherited.length; i < length; i++) {
 			while (index >= 0) matchingInherited[index--] = null; // clear the previous contents of the matching methods
-			if (inherited[i] != null) {
-				matchingInherited[++index] = inherited[i];
+			MethodBinding inheritedMethod = inherited[i];
+			if (inheritedMethod != null) {
+				matchingInherited[++index] = inheritedMethod;
 				for (int j = i + 1; j < length; j++) {
-					if (inherited[j] != null && areParametersEqual(inherited[i], inherited[j])) {
-						matchingInherited[++index] = inherited[j];
+					MethodBinding otherInheritedMethod = inherited[j];
+					if (canSkipInheritedMethods(inheritedMethod, otherInheritedMethod))
+						continue;
+					otherInheritedMethod = computeSubstituteMethod(otherInheritedMethod, inheritedMethod);
+					if (areMethodsEqual(inheritedMethod, otherInheritedMethod)) {
+						matchingInherited[++index] = otherInheritedMethod;
 						inherited[j] = null; // do not want to find it again
 					}
 				}
 			}
 			if (index > 0)
-				this.checkInheritedMethods(matchingInherited, index + 1); // pass in the length of matching
+				checkInheritedMethods(matchingInherited, index + 1); // pass in the length of matching
 			else if (mustImplementAbstractMethods && index == 0 && matchingInherited[0].isAbstract())
 				checkAbstractMethod(matchingInherited[0]);
 		}
 	}
 }
-private void checkPackagePrivateAbstractMethod(MethodBinding abstractMethod) {
+void checkPackagePrivateAbstractMethod(MethodBinding abstractMethod) {
+	// check that the inherited abstract method (package private visibility) is implemented within the same package
+	PackageBinding necessaryPackage = abstractMethod.declaringClass.fPackage;
+	if (necessaryPackage == this.type.fPackage) return; // not a problem
+
 	ReferenceBinding superType = this.type.superclass();
 	char[] selector = abstractMethod.selector;
 	do {
 		if (!superType.isValidBinding()) return;
 		if (!superType.isAbstract()) return; // closer non abstract super type will be flagged instead
 
-		MethodBinding[] methods = superType.getMethods(selector);
-		nextMethod : for (int m = methods.length; --m >= 0;) {
-			MethodBinding method = methods[m];
-			if (!areTypesEqual(method.returnType, abstractMethod.returnType) || !areParametersEqual(method, abstractMethod))
-				continue nextMethod;
-			if (method.isPrivate() || method.isConstructor() || method.isDefaultAbstract())
-				continue nextMethod;
-			if (superType.fPackage == abstractMethod.declaringClass.fPackage) return; // found concrete implementation of abstract method in same package
+		if (necessaryPackage == superType.fPackage) {
+			MethodBinding[] methods = superType.getMethods(selector);
+			nextMethod : for (int m = methods.length; --m >= 0;) {
+				MethodBinding method = methods[m];
+				if (method.isPrivate() || method.isConstructor() || method.isDefaultAbstract())
+					continue nextMethod;
+				if (doesMethodOverride(method, abstractMethod))
+					return; // found concrete implementation of abstract method in same package
+			}
 		}
 	} while ((superType = superType.superclass()) != abstractMethod.declaringClass);
 
 	// non visible abstract methods cannot be overridden so the type must be defined abstract
-	this.problemReporter().abstractMethodCannotBeOverridden(this.type, abstractMethod);
+	problemReporter().abstractMethodCannotBeOverridden(this.type, abstractMethod);
 }
 /*
 Binding creation is responsible for reporting:
@@ -287,7 +344,10 @@
 	- check the type of any array is not void
 	- check that each exception type is Throwable or a subclass of it
 */
-private void computeInheritedMethods() {
+void computeInheritedMethods() {
+	// only want to remember inheritedMethods that can have an impact on the current type
+	// if an inheritedMethod has been 'replaced' by a supertype's method then skip it
+
 	this.inheritedMethods = new HashtableOfObject(51); // maps method selectors to an array of methods... must search to match paramaters & return type
 	ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[3][];
 	int lastPosition = -1;
@@ -295,79 +355,86 @@
 	if (itsInterfaces != NoSuperInterfaces)
 		interfacesToVisit[++lastPosition] = itsInterfaces;
 
-	ReferenceBinding superType = this.type.isClass()
-		? this.type.superclass()
+	ReferenceBinding superType = (this.type.modifiers & IConstants.AccInterface) == 0
+		? this.type.superclass() // class or enum
 		: this.type.scope.getJavaLangObject(); // check interface methods against Object
-	MethodBinding[] nonVisibleDefaultMethods = null;
-	int nonVisibleCount = 0;
+	HashtableOfObject nonVisibleDefaultMethods = new HashtableOfObject(3); // maps method selectors to an array of methods
+	boolean allSuperclassesAreAbstract = true;
 
-	while (superType != null) {
-		if (superType.isValidBinding()) {
-			if ((itsInterfaces = superType.superInterfaces()) != NoSuperInterfaces) {
-				if (++lastPosition == interfacesToVisit.length)
-					System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
-				interfacesToVisit[lastPosition] = itsInterfaces;
+	while (superType != null && superType.isValidBinding()) {
+	    if (allSuperclassesAreAbstract) {
+		    if (superType.isAbstract()) {
+				// only need to include superinterfaces if immediate superclasses are abstract
+				if ((itsInterfaces = superType.superInterfaces()) != NoSuperInterfaces) {
+					if (++lastPosition == interfacesToVisit.length)
+						System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+					interfacesToVisit[lastPosition] = itsInterfaces;
+				}
+			} else {
+			    allSuperclassesAreAbstract = false;
 			}
+		}
 
-			MethodBinding[] methods = superType.unResolvedMethods();
-			nextMethod : for (int m = methods.length; --m >= 0;) {
-				MethodBinding method = methods[m];
-				if (!(method.isPrivate() || method.isConstructor() || method.isDefaultAbstract())) {
-					MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(method.selector);
-					if (existingMethods != null) {
-						for (int i = 0, length = existingMethods.length; i < length; i++) {
-							if (areTypesEqual(method.returnType, existingMethods[i].returnType) && areParametersEqual(method, existingMethods[i])) {
-								if (method.isDefault() && method.isAbstract() && method.declaringClass.fPackage != type.fPackage)
-									checkPackagePrivateAbstractMethod(method);
-								continue nextMethod;
-							}
-						}
+		MethodBinding[] methods = superType.unResolvedMethods();
+		nextMethod : for (int m = methods.length; --m >= 0;) {
+			MethodBinding inheritedMethod = methods[m];
+			if (inheritedMethod.isPrivate() || inheritedMethod.isConstructor() || inheritedMethod.isDefaultAbstract())
+				continue nextMethod;
+			MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(inheritedMethod.selector);
+			if (existingMethods != null) {
+				for (int i = 0, length = existingMethods.length; i < length; i++) {
+					if (existingMethods[i].declaringClass != inheritedMethod.declaringClass && doesMethodOverride(existingMethods[i], inheritedMethod)) {
+						if (inheritedMethod.isDefault() && inheritedMethod.isAbstract())
+							checkPackagePrivateAbstractMethod(inheritedMethod);
+						continue nextMethod;
 					}
-					if (nonVisibleDefaultMethods != null)
-						for (int i = 0; i < nonVisibleCount; i++)
-							if (CharOperation.equals(method.selector, nonVisibleDefaultMethods[i].selector)
-								&& areTypesEqual(method.returnType, nonVisibleDefaultMethods[i].returnType)
-								&& areParametersEqual(method, nonVisibleDefaultMethods[i])) 
-									continue nextMethod;
+				}
+			}
+			MethodBinding[] nonVisible = (MethodBinding[]) nonVisibleDefaultMethods.get(inheritedMethod.selector);
+			if (nonVisible != null)
+				for (int i = 0, l = nonVisible.length; i < l; i++)
+					if (doesMethodOverride(nonVisible[i], inheritedMethod))
+						continue nextMethod;
 
-					if (!method.isDefault() || method.declaringClass.fPackage == type.fPackage) {
-						if (existingMethods == null)
-							existingMethods = new MethodBinding[1];
-						else
-							System.arraycopy(existingMethods, 0,
-								(existingMethods = new MethodBinding[existingMethods.length + 1]), 0, existingMethods.length - 1);
-						existingMethods[existingMethods.length - 1] = method;
-						this.inheritedMethods.put(method.selector, existingMethods);
-					} else {
-						if (nonVisibleDefaultMethods == null)
-							nonVisibleDefaultMethods = new MethodBinding[10];
-						else if (nonVisibleCount == nonVisibleDefaultMethods.length)
-							System.arraycopy(nonVisibleDefaultMethods, 0,
-								(nonVisibleDefaultMethods = new MethodBinding[nonVisibleCount * 2]), 0, nonVisibleCount);
-						nonVisibleDefaultMethods[nonVisibleCount++] = method;
+			if (!inheritedMethod.isDefault() || inheritedMethod.declaringClass.fPackage == type.fPackage) {
+				if (existingMethods == null) {
+					existingMethods = new MethodBinding[] {inheritedMethod};
+				} else {
+					int length = existingMethods.length;
+					System.arraycopy(existingMethods, 0, existingMethods = new MethodBinding[length + 1], 0, length);
+					existingMethods[length] = inheritedMethod;
+				}
+				this.inheritedMethods.put(inheritedMethod.selector, existingMethods);
+			} else {
+				if (nonVisible == null) {
+					nonVisible = new MethodBinding[] {inheritedMethod};
+				} else {
+					int length = nonVisible.length;
+					System.arraycopy(nonVisible, 0, nonVisible = new MethodBinding[length + 1], 0, length);
+					nonVisible[length] = inheritedMethod;
+				}
+				nonVisibleDefaultMethods.put(inheritedMethod.selector, nonVisible);
 
-						if (method.isAbstract() && !this.type.isAbstract()) // non visible abstract methods cannot be overridden so the type must be defined abstract
-							this.problemReporter().abstractMethodCannotBeOverridden(this.type, method);
+				if (inheritedMethod.isAbstract() && !this.type.isAbstract()) // non visible abstract methods cannot be overridden so the type must be defined abstract
+					problemReporter().abstractMethodCannotBeOverridden(this.type, inheritedMethod);
 
-						MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(method.selector);
-						if (current != null) { // non visible methods cannot be overridden so a warning is issued
-							foundMatch : for (int i = 0, length = current.length; i < length; i++) {
-								if (areTypesEqual(method.returnType, current[i].returnType) && areParametersEqual(method, current[i])) {
-									this.problemReporter().overridesPackageDefaultMethod(current[i], method);
-									break foundMatch;
-								}
-							}
+				MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(inheritedMethod.selector);
+				if (current != null) { // non visible methods cannot be overridden so a warning is issued
+					foundMatch : for (int i = 0, length = current.length; i < length; i++) {
+						if (doesMethodOverride(current[i], inheritedMethod)) {
+							problemReporter().overridesPackageDefaultMethod(current[i], inheritedMethod);
+							break foundMatch;
 						}
 					}
 				}
 			}
-			superType = superType.superclass();
 		}
+		superType = superType.superclass();
 	}
 
 	for (int i = 0; i <= lastPosition; i++) {
 		ReferenceBinding[] interfaces = interfacesToVisit[i];
-		for (int j = 0, length = interfaces.length; j < length; j++) {
+		for (int j = 0, l = interfaces.length; j < l; j++) {
 			superType = interfaces[j];
 			if ((superType.tagBits & InterfaceVisited) == 0) {
 				superType.tagBits |= InterfaceVisited;
@@ -379,16 +446,21 @@
 					}
 
 					MethodBinding[] methods = superType.unResolvedMethods();
-					for (int m = methods.length; --m >= 0;) { // Interface methods are all abstract public
-						MethodBinding method = methods[m];
-						MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(method.selector);
-						if (existingMethods == null)
-							existingMethods = new MethodBinding[1];
-						else
-							System.arraycopy(existingMethods, 0,
-								(existingMethods = new MethodBinding[existingMethods.length + 1]), 0, existingMethods.length - 1);
-						existingMethods[existingMethods.length - 1] = method;
-						this.inheritedMethods.put(method.selector, existingMethods);
+					nextMethod : for (int m = methods.length; --m >= 0;) { // Interface methods are all abstract public
+						MethodBinding inheritedMethod = methods[m];
+						MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(inheritedMethod.selector);
+						if (existingMethods == null) {
+							existingMethods = new MethodBinding[] {inheritedMethod};
+						} else {
+							int length = existingMethods.length;
+							// look to see if any of the existingMethods implement this inheritedMethod
+							for (int e = 0; e < length; e++)
+								if (isInterfaceMethodImplemented(inheritedMethod, existingMethods[e], superType))
+									continue nextMethod; // skip interface method with the same signature if visible to its declaringClass
+							System.arraycopy(existingMethods, 0, existingMethods = new MethodBinding[length + 1], 0, length);
+							existingMethods[length] = inheritedMethod;
+						}
+						this.inheritedMethods.put(inheritedMethod.selector, existingMethods);
 					}
 				}
 			}
@@ -402,7 +474,7 @@
 			interfaces[j].tagBits &= ~InterfaceVisited;
 	}
 }
-private void computeMethods() {
+void computeMethods() {
 	MethodBinding[] methods = type.methods();
 	int size = methods.length;
 	this.currentMethods = new HashtableOfObject(size == 0 ? 1 : size); // maps method selectors to an array of methods... must search to match paramaters & return type
@@ -420,12 +492,18 @@
 		}
 	}
 }
-private ReferenceBinding errorException() {
+MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) {
+	return inheritedMethod;
+}
+public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) {
+	return areReturnTypesEqual(method, inheritedMethod) && areParametersEqual(method, inheritedMethod);
+}
+ReferenceBinding errorException() {
 	if (errorException == null)
 		this.errorException = this.type.scope.getJavaLangError();
 	return errorException;
 }
-private boolean isAsVisible(MethodBinding newMethod, MethodBinding inheritedMethod) {
+boolean isAsVisible(MethodBinding newMethod, MethodBinding inheritedMethod) {
 	if (inheritedMethod.modifiers == newMethod.modifiers) return true;
 
 	if (newMethod.isPublic()) return true;		// Covers everything
@@ -436,17 +514,20 @@
 
 	return !newMethod.isPrivate();		// The inheritedMethod cannot be private since it would not be visible
 }
-private boolean isSameClassOrSubclassOf(ReferenceBinding testClass, ReferenceBinding superclass) {
+boolean isInterfaceMethodImplemented(MethodBinding inheritedMethod, MethodBinding existingMethod, ReferenceBinding superType) {
+	// skip interface method with the same signature if visible to its declaringClass
+	return areParametersEqual(existingMethod, inheritedMethod) && existingMethod.declaringClass.implementsInterface(superType, true);
+}
+boolean isSameClassOrSubclassOf(ReferenceBinding testClass, ReferenceBinding superclass) {
 	do {
 		if (testClass == superclass) return true;
 	} while ((testClass = testClass.superclass()) != null);
 	return false;
 }
-private boolean mustImplementAbstractMethod(MethodBinding abstractMethod) {
+boolean mustImplementAbstractMethod(ReferenceBinding declaringClass) {
 	// if the type's superclass is an abstract class, then all abstract methods must be implemented
 	// otherwise, skip it if the type's superclass must implement any of the inherited methods
 	ReferenceBinding superclass = this.type.superclass();
-	ReferenceBinding declaringClass = abstractMethod.declaringClass;
 	if (declaringClass.isClass()) {
 		while (superclass.isAbstract() && superclass != declaringClass)
 			superclass = superclass.superclass(); // find the first concrete superclass or the abstract declaringClass
@@ -461,10 +542,10 @@
 	}
 	return superclass.isAbstract();		// if it is a concrete class then we have already reported problem against it
 }
-private ProblemReporter problemReporter() {
+ProblemReporter problemReporter() {
 	return this.type.scope.problemReporter();
 }
-private ProblemReporter problemReporter(MethodBinding currentMethod) {
+ProblemReporter problemReporter(MethodBinding currentMethod) {
 	ProblemReporter reporter = problemReporter();
 	if (currentMethod.declaringClass == type)	// only report against the currentMethod if its implemented by the type
 		reporter.referenceContext = currentMethod.sourceMethod();
@@ -477,23 +558,21 @@
 
 	if (!(method.declaringClass instanceof BinaryTypeBinding))
 		return TypeConstants.NoExceptions; // safety check
-	BinaryTypeBinding binaryType = (BinaryTypeBinding) method.declaringClass;
 
 	for (int i = exceptions.length; --i >= 0;)
-		if (exceptions[i] instanceof UnresolvedReferenceBinding)
-			exceptions[i] = (ReferenceBinding) binaryType.resolveType(exceptions[i]);
+		exceptions[i] = BinaryTypeBinding.resolveType(exceptions[i], this.environment, true);
 	return exceptions;
 }
-private ReferenceBinding runtimeException() {
+ReferenceBinding runtimeException() {
 	if (runtimeException == null)
 		this.runtimeException = this.type.scope.getJavaLangRuntimeException();
 	return runtimeException;
 }
-public void verify(SourceTypeBinding someType) {
+void verify(SourceTypeBinding someType) {
 	this.type = someType;
-	this.computeMethods();
-	this.computeInheritedMethods();
-	this.checkMethods();
+	computeMethods();
+	computeInheritedMethods();
+	checkMethods();
 }
 public String toString() {
 	StringBuffer buffer = new StringBuffer(10);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
new file mode 100644
index 0000000..c12a487
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
@@ -0,0 +1,221 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+
+class MethodVerifier15 extends MethodVerifier {
+
+MethodVerifier15(LookupEnvironment environment) {
+	super(environment);
+}
+boolean areMethodsEqual(MethodBinding one, MethodBinding substituteTwo) {
+	TypeBinding[] oneParams = one.parameters;
+	TypeBinding[] twoParams = substituteTwo.parameters;
+	boolean checkParameters = false;
+	if (oneParams != twoParams) {
+		int length = oneParams.length;
+		if (length != twoParams.length) return false; // no match
+
+		for (int i = 0; i < length; i++) {
+			if (oneParams[i] != twoParams[i]) {
+				checkParameters |= oneParams[i].leafComponentType().isParameterizedType();
+				if (!areTypesEqual(oneParams[i], twoParams[i])) {
+					while (!checkParameters && ++i < length)
+						checkParameters |= oneParams[i].leafComponentType().isParameterizedType();
+					if (one.areParameterErasuresEqual(substituteTwo)) // at least one parameter may cause a name clash
+						detectNameClash(one, substituteTwo, checkParameters);
+					return false; // no match but needed to check for a name clash
+				}
+			}
+		}
+	}
+	return !detectNameClash(one, substituteTwo, checkParameters);
+}
+boolean areReturnTypesEqual(MethodBinding one, MethodBinding substituteTwo) {
+	if (one.returnType == substituteTwo.returnType) return true;
+
+	// methods from classes are always before methods from interfaces
+	if (one.declaringClass.isClass() || one.declaringClass.implementsInterface(substituteTwo.declaringClass, true))
+		return one.returnType.isCompatibleWith(substituteTwo.returnType);
+
+	if (substituteTwo.declaringClass.implementsInterface(one.declaringClass, true))
+		return substituteTwo.returnType.isCompatibleWith(one.returnType);
+
+	// unrelated interfaces... one must be a subtype of the other
+	return one.returnType.isCompatibleWith(substituteTwo.returnType)
+		|| substituteTwo.returnType.isCompatibleWith(one.returnType);
+}
+boolean areTypesEqual(TypeBinding one, TypeBinding two) {
+	if (one == two) return true;
+
+	switch (one.kind()) {
+		case Binding.PARAMETERIZED_TYPE :
+		case Binding.RAW_TYPE :
+			return one.isEquivalentTo(two);
+//		case Binding.TYPE_PARAMETER : // won't work for variables from different classes - need substitution
+	}
+
+	// Can skip this since we resolved each method before comparing it, see computeSubstituteMethod()
+	//	if (one instanceof UnresolvedReferenceBinding)
+	//		return ((UnresolvedReferenceBinding) one).resolvedType == two;
+	//	if (two instanceof UnresolvedReferenceBinding)
+	//		return ((UnresolvedReferenceBinding) two).resolvedType == one;
+	return false; // all other type bindings are identical
+}
+boolean canSkipInheritedMethods() {
+	if (this.type.superclass() != null)
+		if (this.type.superclass().isAbstract() || this.type.superclass().isParameterizedType())
+			return false;
+	return this.type.superInterfaces() == NoSuperInterfaces;
+}
+boolean canSkipInheritedMethods(MethodBinding one, MethodBinding two) {
+	return two == null // already know one is not null
+		|| (one.declaringClass == two.declaringClass && !one.declaringClass.isParameterizedType());
+}
+void checkForBridgeMethod(MethodBinding currentMethod, MethodBinding inheritedMethod) {
+	MethodBinding originalInherited = inheritedMethod.original();
+	if (inheritedMethod != originalInherited) {
+		MethodBinding[] toCheck = (MethodBinding[]) this.currentMethods.get(currentMethod.selector);
+		if (toCheck.length > 1) {
+			// must check to see if a bridge method will collide with another current method (see 77861)
+			for (int i = 0, length = toCheck.length; i < length; i++) {
+				if (currentMethod != toCheck[i] && toCheck[i].areParameterErasuresEqual(originalInherited)) {
+					problemReporter(toCheck[i]).methodNameClash(toCheck[i], originalInherited); // bridge method will collide
+					return;
+				}
+			}
+		}
+	}
+
+	// so the parameters are equal and the return type is compatible b/w the currentMethod & the substituted inheritedMethod
+	if (originalInherited.returnType != currentMethod.returnType) {
+		TypeBinding originalReturnType = originalInherited.returnType.leafComponentType();
+		switch (originalReturnType.kind()) {
+			case Binding.GENERIC_TYPE :
+				// TODO (philippe) - we need this hack until SourceTypeBindings stop acting as ParameterizedTypes
+				if (originalReturnType != originalInherited.declaringClass || !inheritedMethod.returnType.leafComponentType().isParameterizedType())
+					break;
+			case Binding.PARAMETERIZED_TYPE :
+				if (!currentMethod.returnType.leafComponentType().isParameterizedType()) {
+					if (currentMethod.returnType.leafComponentType().isRawType() && inheritedMethod.returnType.leafComponentType().isRawType())
+						break;
+					problemReporter(currentMethod).unsafeReturnTypeOverride(currentMethod, originalInherited, ((MethodDeclaration) currentMethod.sourceMethod()).returnType);
+				}
+				break;
+			case Binding.TYPE_PARAMETER : // see 81618
+				if (((TypeVariableBinding) originalReturnType).declaringElement == originalInherited) {
+					TypeBinding returnType = currentMethod.returnType.leafComponentType();
+					if (!returnType.isTypeVariable() || ((TypeVariableBinding) returnType).declaringElement != currentMethod)
+						problemReporter(currentMethod).unsafeReturnTypeOverride(currentMethod, originalInherited, ((MethodDeclaration) currentMethod.sourceMethod()).returnType);
+				}
+				break;
+		}
+	}
+	this.type.addSyntheticBridgeMethod(originalInherited, currentMethod);
+}
+void checkInheritedMethods(MethodBinding[] methods, int length) {
+	int count = length;
+	nextMethod : for (int i = 0, l = length - 1; i < l;) {
+		MethodBinding method = methods[i++];
+		for (int j = i; j <= l; j++) {
+			if (method.declaringClass == methods[j].declaringClass && doesMethodOverride(method, methods[j])) {
+				// found an inherited ParameterizedType that defines duplicate methods
+				problemReporter().duplicateInheritedMethods(this.type, method, methods[j]);
+				count--;
+				methods[i - 1] = null;
+				continue nextMethod;
+			}
+		}
+	}
+	if (count < length) {
+		if (count == 1) return; // no need to continue since only 1 inherited method is left
+		MethodBinding[] newMethods = new MethodBinding[count];
+		for (int i = length; --i >= 0;)
+			if (methods[i] != null)
+				newMethods[--count] = methods[i];
+		methods = newMethods;
+		length = newMethods.length;
+	}
+
+	super.checkInheritedMethods(methods, length);
+}
+MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) {
+	if (inheritedMethod == null) return null;
+
+	// due to hierarchy & compatibility checks, we need to ensure these 2 methods are resolved
+	// should we push these tests to where they're needed? returnType.isCompatibleWith && parameter isEquivalentTo ?
+	if (currentMethod.declaringClass instanceof BinaryTypeBinding)
+		((BinaryTypeBinding) currentMethod.declaringClass).resolveTypesFor(currentMethod);
+	if (inheritedMethod.declaringClass instanceof BinaryTypeBinding)
+		((BinaryTypeBinding) inheritedMethod.declaringClass).resolveTypesFor(inheritedMethod);
+
+	TypeVariableBinding[] inheritedTypeVariables = inheritedMethod.typeVariables();
+	if (inheritedTypeVariables == NoTypeVariables) return inheritedMethod;
+	TypeVariableBinding[] typeVariables = currentMethod == null ? NoTypeVariables : currentMethod.typeVariables;
+
+	int inheritedLength = inheritedTypeVariables.length;
+	int length = typeVariables.length;
+	TypeBinding[] arguments = new TypeBinding[inheritedLength];
+	if (inheritedLength <= length) {
+		System.arraycopy(typeVariables, 0, arguments, 0, inheritedLength);
+	} else {
+		System.arraycopy(typeVariables, 0, arguments, 0, length);
+		for (int i = length; i < inheritedLength; i++)
+			arguments[i] = inheritedTypeVariables[i].erasure();
+	}
+	ParameterizedGenericMethodBinding substitute =
+		new ParameterizedGenericMethodBinding(inheritedMethod, arguments, this.environment);
+	for (int i = 0; i < inheritedLength; i++)
+	    if (!inheritedTypeVariables[i].boundCheck(substitute, arguments[i]))
+	    	return inheritedMethod; // incompatible due to bound check
+   return substitute;
+}
+boolean detectNameClash(MethodBinding one, MethodBinding substituteTwo, boolean checkParameters) {
+	if (doTypeVariablesClash(one, substituteTwo) || (checkParameters && doParametersClash(one, substituteTwo))) {
+		if (this.type == one.declaringClass)
+		 	problemReporter(one).methodNameClash(one, substituteTwo);
+		else
+			problemReporter().inheritedMethodsHaveNameClash(this.type, one, substituteTwo);
+		return true;
+	}
+	return false;
+}
+public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) {
+	return super.doesMethodOverride(method, computeSubstituteMethod(inheritedMethod, method));
+}
+boolean doParametersClash(MethodBinding one, MethodBinding substituteTwo) {
+	// must check each parameter pair to see if parameterized types are compatible
+	TypeBinding[] oneParams = one.parameters;
+	TypeBinding[] twoParams = substituteTwo.parameters;
+	for (int i = 0, l = oneParams.length; i < l; i++) {
+		if (oneParams[i] == twoParams[i]) continue;
+		if (!oneParams[i].leafComponentType().isParameterizedType()) continue;
+
+		if (!twoParams[i].leafComponentType().isParameterizedType()
+			|| !oneParams[i].isEquivalentTo(twoParams[i])
+			|| !twoParams[i].isEquivalentTo(oneParams[i])) {
+				return true;
+		}
+	}
+	return false;
+}
+boolean doTypeVariablesClash(MethodBinding one, MethodBinding substituteTwo) {
+	TypeBinding[] currentVars = one.typeVariables;
+	TypeBinding[] inheritedVars = substituteTwo.original().typeVariables;
+	return currentVars.length != inheritedVars.length && currentVars.length > 0;
+}
+boolean isInterfaceMethodImplemented(MethodBinding inheritedMethod, MethodBinding existingMethod, ReferenceBinding superType) {
+	inheritedMethod = computeSubstituteMethod(inheritedMethod, existingMethod);
+	return inheritedMethod.returnType == existingMethod.returnType
+		&& super.isInterfaceMethodImplemented(inheritedMethod, existingMethod, superType);
+}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
index 8143f9b..2b78a5d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
@@ -91,7 +91,7 @@
 		if (synthLocal == null) return null;
 	
 		if (synthLocal.matchingField == null)
-			synthLocal.matchingField = addSyntheticField(actualOuterLocalVariable);
+			synthLocal.matchingField = addSyntheticFieldForInnerclass(actualOuterLocalVariable);
 		return synthLocal;
 	}
 
@@ -103,7 +103,7 @@
 		if (synthLocal == null) return null;
 	
 		if (synthLocal.matchingField == null)
-			synthLocal.matchingField = addSyntheticField(targetEnclosingType);
+			synthLocal.matchingField = addSyntheticFieldForInnerclass(targetEnclosingType);
 		return synthLocal;
 	}
 
@@ -209,7 +209,7 @@
 		if (!onlyExactMatch){
 			for (int i = enclosingInstances.length; --i >= 0;)
 				if (enclosingInstances[i].actualOuterLocalVariable == null)
-					if (targetEnclosingType.isSuperclassOf((ReferenceBinding) enclosingInstances[i].type))
+					if (((ReferenceBinding)enclosingInstances[i].type).findSuperTypeErasingTo(targetEnclosingType) != null)
 						return enclosingInstances[i];
 		}
 		return null;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
index ee68a49..9f29f95 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
@@ -17,7 +17,7 @@
 public class PackageBinding extends Binding implements TypeConstants {
 	public char[][] compoundName;
 	PackageBinding parent;
-	LookupEnvironment environment;
+	public LookupEnvironment environment;
 	HashtableOfType knownTypes;
 	HashtableOfPackage knownPackages;
 protected PackageBinding() {
@@ -59,8 +59,15 @@
 * Answer the receiver's binding type from Binding.BindingID.
 */
 
-public final int bindingType() {
-	return PACKAGE;
+public final int kind() {
+	return Binding.PACKAGE;
+}
+/*
+ * slash separated name
+ * org.eclipse.jdt.core --> org/eclipse/jdt/core
+ */
+public char[] computeUniqueKey() {
+	return CharOperation.concatWith(compoundName, '/');
 }
 private PackageBinding findPackage(char[] name) {
 	if (!environment.isPackage(this.compoundName, name))
@@ -112,22 +119,22 @@
 */
 
 ReferenceBinding getType(char[] name) {
-	ReferenceBinding binding = getType0(name);
-	if (binding == null) {
-		if ((binding = environment.askForType(this, name)) == null) {
+	ReferenceBinding typeBinding = getType0(name);
+	if (typeBinding == null) {
+		if ((typeBinding = environment.askForType(this, name)) == null) {
 			// not found so remember a problem type binding in the cache for future lookups
 			addNotFoundType(name);
 			return null;
 		}
 	}
 
-	if (binding == LookupEnvironment.TheNotFoundType)
+	if (typeBinding == LookupEnvironment.TheNotFoundType)
 		return null;
-	if (binding instanceof UnresolvedReferenceBinding)
-		binding = ((UnresolvedReferenceBinding) binding).resolve(environment);
-	if (binding.isNestedType())
+
+	typeBinding = BinaryTypeBinding.resolveType(typeBinding, environment, false); // no raw conversion for now
+	if (typeBinding.isNestedType())
 		return new ProblemReferenceBinding(name, InternalNameProvided);
-	return binding;
+	return typeBinding;
 }
 /* Answer the type named name if it exists in the cache.
 * Answer theNotFoundType if it could not be resolved the first time
@@ -155,8 +162,7 @@
 public Binding getTypeOrPackage(char[] name) {
 	ReferenceBinding typeBinding = getType0(name);
 	if (typeBinding != null && typeBinding != LookupEnvironment.TheNotFoundType) {
-		if (typeBinding instanceof UnresolvedReferenceBinding)
-			typeBinding = ((UnresolvedReferenceBinding) typeBinding).resolve(environment);
+		typeBinding = BinaryTypeBinding.resolveType(typeBinding, environment, false); // no raw conversion for now
 		if (typeBinding.isNestedType())
 			return new ProblemReferenceBinding(name, InternalNameProvided);
 		return typeBinding;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedFieldBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedFieldBinding.java
new file mode 100644
index 0000000..d494449
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedFieldBinding.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+
+/**
+ * Binding denoting a field after type substitution got performed.
+ * On parameterized type bindings, all fields got substituted, regardless whether
+ * their signature did involve generics or not, so as to get the proper declaringClass for
+ * these fields.
+ */
+public class ParameterizedFieldBinding extends FieldBinding {
+    
+    public FieldBinding originalField;
+    
+	public ParameterizedFieldBinding(ParameterizedTypeBinding parameterizedDeclaringClass, FieldBinding originalField) {
+	    super (
+	            originalField.name, 
+	            originalField.isStatic() ? originalField.type : parameterizedDeclaringClass.substitute(originalField.type), 
+	            originalField.modifiers, 
+	            parameterizedDeclaringClass, 
+	            null);
+	    this.originalField = originalField;
+	}
+	/**
+	 * @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);
+	}	
+}
+
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
new file mode 100644
index 0000000..bf283be
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
@@ -0,0 +1,379 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+
+/**
+ * Binding denoting a generic method after type parameter substitutions got performed.
+ * On parameterized type bindings, all methods got substituted, regardless whether
+ * their signature did involve generics or not, so as to get the proper declaringClass for
+ * these methods.
+ */
+public class ParameterizedGenericMethodBinding extends ParameterizedMethodBinding implements Substitution {
+
+    public TypeBinding[] typeArguments; 
+    private LookupEnvironment environment;
+    public boolean inferredReturnType;
+    public boolean wasInferred; // only set to true for instances resulting from method invocation inferrence
+    public boolean isRaw; // set to true for method behaving as raw for substitution purpose
+    public MethodBinding tiebreakMethod;
+    
+    /**
+     * Create method of parameterized type, substituting original parameters with type arguments.
+     */
+	public ParameterizedGenericMethodBinding(MethodBinding originalMethod, TypeBinding[] typeArguments, LookupEnvironment environment) {
+
+	    this.environment = environment;
+		this.modifiers = originalMethod.modifiers;
+		this.selector = originalMethod.selector;
+		this.declaringClass = originalMethod.declaringClass;
+	    this.typeVariables = NoTypeVariables;
+	    this.typeArguments = typeArguments;
+	    this.isRaw = false;
+	    this.originalMethod = originalMethod;
+	    this.parameters = Scope.substitute(this, originalMethod.parameters);
+	    this.thrownExceptions = Scope.substitute(this, originalMethod.thrownExceptions);
+	    this.returnType = this.substitute(originalMethod.returnType);
+	    this.wasInferred = true;// resulting from method invocation inferrence
+	}
+	
+	/**
+	 * Create raw generic method for raw type (double substitution from type vars with raw type arguments, and erasure of method variables)
+	 * Only invoked for non-static generic methods of raw type
+	 */
+	public ParameterizedGenericMethodBinding(MethodBinding originalMethod, RawTypeBinding rawType, LookupEnvironment environment) {
+
+		TypeVariableBinding[] originalVariables = originalMethod.typeVariables;
+		int length = originalVariables.length;
+		TypeBinding[] rawArguments = new TypeBinding[length];
+		for (int i = 0; i < length; i++) {
+			rawArguments[i] = originalVariables[i].erasure();
+		}		
+	    this.isRaw = true;
+	    this.environment = environment;
+		this.modifiers = originalMethod.modifiers;
+		this.selector = originalMethod.selector;
+		this.declaringClass = rawType == null ? originalMethod.declaringClass : rawType;
+	    this.typeVariables = NoTypeVariables;
+	    this.typeArguments = rawArguments;
+	    this.originalMethod = originalMethod;
+		boolean ignoreRawTypeSubstitution = rawType == null || originalMethod.isStatic();
+	    this.parameters = Scope.substitute(this, ignoreRawTypeSubstitution
+	    									? originalMethod.parameters // no substitution if original was static
+	    									: Scope.substitute(rawType, originalMethod.parameters));
+	    this.thrownExceptions = Scope.substitute(this, 	ignoreRawTypeSubstitution 
+	    									? originalMethod.thrownExceptions // no substitution if original was static
+	    									: Scope.substitute(rawType, originalMethod.thrownExceptions));
+	    this.returnType = this.substitute(ignoreRawTypeSubstitution 
+	    									? originalMethod.returnType // no substitution if original was static
+	    									: rawType.substitute(originalMethod.returnType));
+	    this.wasInferred = false; // not resulting from method invocation inferrence
+	}
+	
+	/**
+	 * Perform inference of generic method type parameters and/or expected type
+	 */	
+	public static MethodBinding computeCompatibleMethod(MethodBinding originalMethod, TypeBinding[] arguments, Scope scope, InvocationSite invocationSite) {
+		
+		ParameterizedGenericMethodBinding methodSubstitute;
+		TypeVariableBinding[] typeVariables = originalMethod.typeVariables;
+		TypeBinding[] substitutes = invocationSite.genericTypeArguments();
+		
+		if (substitutes != null) {
+			if (substitutes.length != typeVariables.length) {
+		        // incompatible due to wrong arity
+		        return new ProblemMethodBinding(originalMethod, originalMethod.selector, substitutes, TypeParameterArityMismatch);
+			}
+			methodSubstitute = new ParameterizedGenericMethodBinding(originalMethod, substitutes, scope.environment());
+		} else {
+			// perform type inference based on argument types and expected type
+			
+			// collect substitutes by pattern matching parameters and arguments
+			TypeBinding[] parameters = originalMethod.parameters;
+			int varLength = typeVariables.length;
+			HashMap collectedSubstitutes = new HashMap(varLength);
+			for (int i = 0; i < varLength; i++)
+				collectedSubstitutes.put(typeVariables[i], new TypeBinding[1]);
+			
+			// collect argument type mapping, handling varargs
+			if (originalMethod.isVarargs()) {
+				int paramLength = parameters.length;
+				int minArgLength = paramLength - 1;
+				int argLength = arguments.length;
+				// process mandatory arguments
+				for (int i = 0; i < minArgLength; i++)
+					parameters[i].collectSubstitutes(arguments[i], collectedSubstitutes);
+				// process optional arguments
+				if (minArgLength < argLength) {
+					TypeBinding varargType = parameters[minArgLength]; // last arg type - as is ?
+					if (paramLength != argLength // argument is passed as is ?
+							||  (arguments[minArgLength] != NullBinding
+									&& (arguments[minArgLength].dimensions() != varargType.dimensions()))) { 
+						varargType = ((ArrayBinding)varargType).elementsType(); // eliminate one array dimension
+					}
+					for (int i = minArgLength; i < argLength; i++)
+						varargType.collectSubstitutes(arguments[i], collectedSubstitutes);
+				}
+			} else {
+				int paramLength = parameters.length;
+				for (int i = 0; i < paramLength; i++)
+					parameters[i].collectSubstitutes(arguments[i], collectedSubstitutes);
+			}
+			boolean needReturnTypeInference = false;
+			if (collectedSubstitutes.isEmpty()) {
+				// raw generic method inferred
+				methodSubstitute = new ParameterizedGenericMethodBinding(originalMethod, (RawTypeBinding)null, scope.environment());
+			} else {
+				substitutes = new TypeBinding[varLength];
+				for (int i = 0; i < varLength; i++) {
+					TypeBinding[] variableSubstitutes = (TypeBinding[]) collectedSubstitutes.get(typeVariables[i]);
+					TypeBinding mostSpecificSubstitute = scope.lowerUpperBound(variableSubstitutes);
+					if (mostSpecificSubstitute == null)
+						return null; // incompatible
+					if (mostSpecificSubstitute == VoidBinding) {
+						needReturnTypeInference = true;
+					    mostSpecificSubstitute = typeVariables[i];
+					}				
+					substitutes[i] = mostSpecificSubstitute;
+				}
+				// apply inferred variable substitutions
+				methodSubstitute = new ParameterizedGenericMethodBinding(originalMethod, substitutes, scope.environment());
+			}
+	
+			if (needReturnTypeInference && invocationSite instanceof MessageSend) {
+				MessageSend message = (MessageSend) invocationSite;
+				TypeBinding expectedType = message.expectedType;
+				if (expectedType == null) {
+					// 15.12.2.8 - if no expected type, then assume Object
+					// actually it rather seems to handle the returned variable case by expecting its erasure instead
+					if (methodSubstitute.returnType.isTypeVariable()) {
+						expectedType = methodSubstitute.returnType.erasure();
+					} else {
+						expectedType =scope.getJavaLangObject(); 
+					}
+				}
+				methodSubstitute.inferFromExpectedType(expectedType, scope);
+			}
+		}
+		// check bounds
+		if (!methodSubstitute.isRaw) {
+			for (int i = 0, length = typeVariables.length; i < length; i++) {
+			    TypeVariableBinding typeVariable = typeVariables[i];
+			    TypeBinding substitute = substitutes[i];
+			    if (!typeVariable.boundCheck(methodSubstitute, substitute))
+			        // incompatible due to bound check
+			        return new ProblemMethodBinding(methodSubstitute, originalMethod.selector, new TypeBinding[]{substitutes[i], typeVariables[i] }, ParameterBoundMismatch);
+			}
+		}
+
+		return methodSubstitute;
+	}
+
+	/*
+	 * parameterizedDeclaringUniqueKey dot selector originalMethodGenericSignature percent typeArguments
+	 * p.X<U> { <T> void bar(T t, U u) { new X<String>().bar(this, "") } } --> Lp/X<Ljava/lang/String;>;.bar<T:Ljava/lang/Object;>(TT;TU;)V%<Lp/X;>
+	 */
+	public char[] computeUniqueKey() {
+		if (this.isRaw)
+			return super.computeUniqueKey();
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(super.computeUniqueKey());
+		buffer.append('%');
+		buffer.append('<');
+		int length = this.typeArguments.length;
+		for (int i = 0; i < length; i++) {
+			TypeBinding typeArgument = this.typeArguments[i];
+			buffer.append(typeArgument.computeUniqueKey());
+		}
+		buffer.append('>');
+		int resultLength = buffer.length();
+		char[] result = new char[resultLength];
+		buffer.getChars(0, resultLength, result, 0);	
+		return result;
+		
+	}
+	
+	/**
+	 * Returns true if some parameters got substituted.
+	 * NOTE: generic method invocation delegates to its declaring method (could be a parameterized one)
+	 */
+	public boolean hasSubstitutedParameters() {
+		// generic parameterized method can represent either an invocation or a raw generic method
+		if (this.wasInferred) 
+			return this.originalMethod.hasSubstitutedParameters();
+		return super.hasSubstitutedParameters();
+	}
+	/**
+	 * Returns true if the return type got substituted.
+	 * NOTE: generic method invocation delegates to its declaring method (could be a parameterized one)
+	 */
+	public boolean hasSubstitutedReturnType() {
+		if (this.wasInferred) 
+			return this.originalMethod.hasSubstitutedReturnType();
+		return super.hasSubstitutedReturnType();
+	}
+	
+	public void inferFromExpectedType(TypeBinding expectedType, Scope scope) {
+	    if (this.returnType == expectedType) 
+	        return;
+	    if ((this.returnType.tagBits & TagBits.HasTypeVariable) == 0) 
+	        return;
+	    Map substitutes = new HashMap(1);
+	    int length = this.typeArguments.length;
+	    TypeVariableBinding[] originalVariables = this.original().typeVariables;
+	    boolean hasUnboundParameters = false;
+	    for (int i = 0; i < length; i++) {
+	        if (this.typeArguments[i] == originalVariables[i]) {
+	            hasUnboundParameters = true;
+	        	substitutes.put(originalVariables[i], new TypeBinding[1]);
+	        } else {
+	        	substitutes.put(originalVariables[i], new TypeBinding[] { this.typeArguments[i] });
+	        }
+	    }
+	    if (!hasUnboundParameters)
+	        return;
+	    returnType.collectSubstitutes(expectedType, substitutes);
+	    if (substitutes.isEmpty()) {
+	    	// raw generic method inferred
+	    	this.isRaw = true;
+	    	for (int i = 0; i < length; i++) {
+	    		this.typeArguments[i] = originalVariables[i].erasure();
+	    	}
+	    } else {
+			for (int i = 0; i < length; i++) {
+				TypeBinding[] variableSubstitutes = (TypeBinding[]) substitutes.get(originalVariables[i]);
+				TypeBinding mostSpecificSubstitute = scope.lowerUpperBound(variableSubstitutes);
+				if (mostSpecificSubstitute == null) {
+				    return; // TODO (philippe) should report no way to infer type
+				}
+				if (mostSpecificSubstitute == VoidBinding) {
+					// 15.12.2.8 - any remaining variable is assumed to be its erasure
+					mostSpecificSubstitute = originalVariables[i].erasure();
+				}				
+				this.typeArguments[i] = mostSpecificSubstitute;
+			}
+	    }
+		TypeBinding oldReturnType = this.returnType;
+		this.returnType = this.substitute(this.returnType);
+		this.inferredReturnType = this.returnType != oldReturnType;
+	    this.parameters = Scope.substitute(this, this.parameters);
+	    this.thrownExceptions = Scope.substitute(this, this.thrownExceptions);
+	}
+	
+    /**
+	 * Returns a type, where original type was substituted using the receiver
+	 * parameterized method.
+	 */
+	public TypeBinding substitute(TypeBinding originalType) {
+	    
+		switch (originalType.kind()) {
+			
+			case Binding.TYPE_PARAMETER:
+		        TypeVariableBinding originalVariable = (TypeVariableBinding) originalType;
+		        TypeVariableBinding[] variables = this.originalMethod.typeVariables;
+		        int length = variables.length;
+		        // check this variable can be substituted given parameterized type
+		        if (originalVariable.rank < length && variables[originalVariable.rank] == originalVariable) {
+					return this.typeArguments[originalVariable.rank];
+		        }
+		        if (this.declaringClass instanceof Substitution) {
+		        	return ((Substitution)this.declaringClass).substitute(originalType);
+		        }
+		        break;
+	   		       
+			case Binding.PARAMETERIZED_TYPE:
+				ParameterizedTypeBinding originalParameterizedType = (ParameterizedTypeBinding) originalType;
+				ReferenceBinding originalEnclosing = originalType.enclosingType();
+				ReferenceBinding substitutedEnclosing = originalEnclosing;
+				if (originalEnclosing != null) {
+					substitutedEnclosing = (ReferenceBinding) this.substitute(originalEnclosing);
+				}
+				if (this.isRaw) {
+					return this.environment.createRawType(originalParameterizedType.type, substitutedEnclosing);					
+				}
+				TypeBinding[] originalArguments = originalParameterizedType.arguments;
+				TypeBinding[] substitutedArguments = originalArguments;
+				if (originalArguments != null) {
+					substitutedArguments = Scope.substitute(this, originalArguments);
+				}
+				if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) {
+					identicalVariables: { // if substituted with original variables, then answer the generic type itself
+						if (substitutedEnclosing != originalEnclosing) break identicalVariables;
+						TypeVariableBinding[] originalVariables = originalParameterizedType.type.typeVariables();
+						length = originalVariables.length;
+						for (int i = 0; i < length; i++) {
+							if (substitutedArguments[i] != originalVariables[i]) break identicalVariables;
+						}
+						return originalParameterizedType.type;
+					}
+					return this.environment.createParameterizedType(
+							originalParameterizedType.type, substitutedArguments, substitutedEnclosing);
+				}
+				break;   		        
+		        
+			case Binding.ARRAY_TYPE:
+				TypeBinding originalLeafComponentType = originalType.leafComponentType();
+				TypeBinding substitute = substitute(originalLeafComponentType); // substitute could itself be array type
+				if (substitute != originalLeafComponentType) {
+					return this.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalType.dimensions());
+				}
+				break;
+				
+			case Binding.WILDCARD_TYPE:
+		        WildcardBinding wildcard = (WildcardBinding) originalType;
+		        if (wildcard.kind != Wildcard.UNBOUND) {
+			        TypeBinding originalBound = wildcard.bound;
+			        TypeBinding substitutedBound = substitute(originalBound);
+			        if (substitutedBound != originalBound) {
+		        		return this.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, wildcard.kind);
+			        }
+		        }
+		        break;
+	
+	
+			case Binding.GENERIC_TYPE:
+			    // treat as if parameterized with its type variables
+				ReferenceBinding originalGenericType = (ReferenceBinding) originalType;
+				originalEnclosing = originalType.enclosingType();
+				substitutedEnclosing = originalEnclosing;
+				if (originalEnclosing != null) {
+					substitutedEnclosing = (ReferenceBinding) this.substitute(originalEnclosing);
+				}
+				if (this.isRaw) {
+					return this.environment.createRawType(originalGenericType, substitutedEnclosing);					
+				}				
+				TypeVariableBinding[] originalVariables = originalGenericType.typeVariables();
+				length = originalVariables.length;
+				System.arraycopy(originalVariables, 0, originalArguments = new TypeBinding[length], 0, length);
+				substitutedArguments = Scope.substitute(this, originalArguments);
+				if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) {
+					return this.environment.createParameterizedType(
+							originalGenericType, substitutedArguments, substitutedEnclosing);
+				}
+				break;
+	    }
+	    return originalType;
+	}
+	/**
+	 * Returns the method to use during tiebreak (usually the method itself).
+	 * For generic method invocations, tiebreak needs to use generic method with erasure substitutes.
+	 */
+	public MethodBinding tiebreakMethod() {
+		if (this.tiebreakMethod == null) {
+			this.tiebreakMethod = new ParameterizedGenericMethodBinding(this.originalMethod, (RawTypeBinding)null, this.environment);
+		} 
+		return this.tiebreakMethod;
+	}	
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
new file mode 100644
index 0000000..bbe65e7
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+
+/**
+ * Binding denoting a method after type parameter substitutions got performed.
+ * On parameterized type bindings, all methods got substituted, regardless whether
+ * 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;
+
+	/**
+	 * Create method of parameterized type, substituting original parameters/exception/return type with type arguments.
+	 */
+	public ParameterizedMethodBinding(ParameterizedTypeBinding parameterizedDeclaringClass, MethodBinding originalMethod, boolean isStatic) {
+
+		super(
+				originalMethod.modifiers,
+				originalMethod.selector,
+				isStatic // no substitution if original was static
+						? originalMethod.returnType
+						: parameterizedDeclaringClass.substitute(originalMethod.returnType),
+				isStatic // no substitution if original was static
+					? originalMethod.parameters
+					: Scope.substitute(parameterizedDeclaringClass, originalMethod.parameters),
+				isStatic // no substitution if original was static
+					? originalMethod.thrownExceptions
+					: Scope.substitute(parameterizedDeclaringClass, originalMethod.thrownExceptions),
+				parameterizedDeclaringClass);
+		this.originalMethod = originalMethod;
+		this.typeVariables = originalMethod.typeVariables;
+	}
+
+	public ParameterizedMethodBinding() {
+		// no init
+	}
+
+	/*
+	 * parameterizedDeclaringUniqueKey dot selector originalMethodGenericSignature
+	 * p.X<U> { void bar(U u) { new X<String>().bar("") } } --> Lp/X<Ljava/lang/String;>;.bar(TU;)V
+	 */
+	public char[] computeUniqueKey() {
+		return computeUniqueKey(original());
+	}
+
+	/**
+	 * The type of x.getClass() is substituted from 'Class<? extends Object>' into: 'Class<? extends |X|> where |X| is X's erasure.
+	 */
+	public static ParameterizedMethodBinding instantiateGetClass(TypeBinding receiverType, MethodBinding originalMethod, Scope scope) {
+		ParameterizedMethodBinding method = new ParameterizedMethodBinding();
+		method.modifiers = originalMethod.modifiers;
+		method.selector = originalMethod.selector;
+		method.declaringClass = originalMethod.declaringClass;
+		method.typeVariables = NoTypeVariables;
+		method.originalMethod = originalMethod;
+		method.parameters = originalMethod.parameters;
+		method.thrownExceptions = originalMethod.thrownExceptions;
+		ReferenceBinding genericClassType = scope.getJavaLangClass();
+		method.returnType = scope.createParameterizedType(
+			genericClassType,
+			new TypeBinding[] {  scope.environment().createWildcard(genericClassType, 0, receiverType.erasure(), Wildcard.EXTENDS) },
+			null);
+		return method;
+	}
+
+	/**
+	 * Returns true if some parameters got substituted.
+	 */
+	public boolean hasSubstitutedParameters() {
+		return this.parameters != originalMethod.parameters;
+	}
+
+	/**
+	 * Returns true if the return type got substituted.
+	 */
+	public boolean hasSubstitutedReturnType() {
+		return this.returnType != originalMethod.returnType;
+	}
+
+	/**
+	 * Returns the original method (as opposed to parameterized instances)
+	 */
+	public MethodBinding original() {
+		return this.originalMethod.original();
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
new file mode 100644
index 0000000..e516714
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
@@ -0,0 +1,863 @@
+/*******************************************************************************
+ * Copyright (c) 2000-2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import java.util.Map;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+
+/**
+ * A parameterized type encapsulates a type with type arguments,
+ */
+public class ParameterizedTypeBinding extends ReferenceBinding implements Substitution {
+
+	public ReferenceBinding type; 
+	public TypeBinding[] arguments;
+	public LookupEnvironment environment; 
+	public char[] genericTypeSignature;
+	public ReferenceBinding superclass;
+	public ReferenceBinding[] superInterfaces;	
+	public FieldBinding[] fields;	
+	public ReferenceBinding[] memberTypes;
+	public MethodBinding[] methods;
+	private ReferenceBinding enclosingType;
+	
+	public ParameterizedTypeBinding(ReferenceBinding type, TypeBinding[] arguments,  ReferenceBinding enclosingType, LookupEnvironment environment){
+
+		this.environment = environment;
+		initialize(type, arguments);
+		this.enclosingType = enclosingType; // never unresolved, never lazy per construction
+
+		if (type instanceof UnresolvedReferenceBinding)
+			((UnresolvedReferenceBinding) type).addWrapper(this);
+		if (arguments != null) {
+			for (int i = 0, l = arguments.length; i < l; i++)
+				if (arguments[i] instanceof UnresolvedReferenceBinding)
+					((UnresolvedReferenceBinding) arguments[i]).addWrapper(this);
+		}
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#canBeInstantiated()
+	 */
+	public boolean canBeInstantiated() {
+		return ((this.tagBits & HasDirectWildcard) == 0) // cannot instantiate param type with wildcard arguments
+							&& super.canBeInstantiated();
+	}
+	public int kind() {
+		return PARAMETERIZED_TYPE;
+	}	
+	
+	/**
+	 * Collect the substitutes into a map for certain type variables inside the receiver type
+	 * e.g.   Collection<T>.findSubstitute(T, Collection<List<X>>):   T --> List<X>
+	 */
+	public void collectSubstitutes(TypeBinding otherType, Map substitutes) {
+		if (this.arguments == null) return;
+		if (otherType instanceof ReferenceBinding) {
+			// allow List<T> to match with LinkedList<String>
+			ReferenceBinding equivalent = this;
+	        ReferenceBinding otherEquivalent = ((ReferenceBinding)otherType).findSuperTypeErasingTo((ReferenceBinding)this.type.erasure());
+	        if (otherEquivalent == null) {
+	        	// allow LinkedList<String> to match List<T> (downcast scenario)
+		    	equivalent = this.findSuperTypeErasingTo((ReferenceBinding)otherType.erasure());
+	        	if (equivalent == null) return;
+	        	otherEquivalent = (ReferenceBinding)otherType;
+	        }
+	        TypeBinding[] elements;
+	        switch (equivalent.kind()) {
+	        	case Binding.GENERIC_TYPE :
+	        		elements = equivalent.typeVariables();
+	        		break;
+	        	case Binding.PARAMETERIZED_TYPE :
+	        		elements = ((ParameterizedTypeBinding)equivalent).arguments;
+	        		break;
+	        	default :
+	        		return;
+	        }
+	        TypeBinding[] otherElements;
+	        switch (otherEquivalent.kind()) {
+	        	case Binding.GENERIC_TYPE :
+	        		otherElements = otherEquivalent.typeVariables();
+	        		break;
+	        	case Binding.PARAMETERIZED_TYPE :
+	        		otherElements = ((ParameterizedTypeBinding)otherEquivalent).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 = elements.length; i < length; i++) {
+                elements[i].collectSubstitutes(otherElements[i], substitutes);
+	        }
+	    }
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#computeId()
+	 */
+	public void computeId() {
+		this.id = NoId;		
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#constantPoolName()
+	 */
+	public char[] constantPoolName() {
+		return this.type.constantPoolName(); // erasure
+	}
+
+	public ParameterizedMethodBinding createParameterizedMethod(MethodBinding originalMethod) {
+		return new ParameterizedMethodBinding(this, originalMethod, originalMethod.isStatic());
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName()
+	 */
+	public String debugName() {
+	    StringBuffer nameBuffer = new StringBuffer(10);
+		nameBuffer.append(this.type.sourceName());
+		if (this.arguments != null) {
+			nameBuffer.append('<');
+		    for (int i = 0, length = this.arguments.length; i < length; i++) {
+		        if (i > 0) nameBuffer.append(',');
+		        nameBuffer.append(this.arguments[i].debugName());
+		    }
+		    nameBuffer.append('>');
+		}
+	    return nameBuffer.toString();		
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#enclosingType()
+	 */
+	public ReferenceBinding enclosingType() {
+		if (this.isMemberType() && this.enclosingType == null) {
+			ReferenceBinding originalEnclosing = this.type.enclosingType();
+			this.enclosingType = originalEnclosing.isGenericType()
+													? this.environment.createRawType(originalEnclosing, originalEnclosing.enclosingType()) // TODO (need to propagate in depth on enclosing type)
+													: originalEnclosing;
+		}
+	    return this.enclosingType;
+	}
+
+	/**
+     * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#erasure()
+     */
+    public TypeBinding erasure() {
+        return this.type.erasure(); // erasure
+    }
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#fieldCount()
+	 */
+	public int fieldCount() {
+		return this.type.fieldCount(); // same as erasure (lazy)
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#fields()
+	 */
+	public FieldBinding[] fields() {
+		if (this.fields == null) {
+			try {
+				FieldBinding[] originalFields = this.type.fields();
+				int length = originalFields.length;
+				FieldBinding[] parameterizedFields = new FieldBinding[length];
+				for (int i = 0; i < length; i++)
+					// substitute all fields, so as to get updated declaring class at least
+					parameterizedFields[i] = new ParameterizedFieldBinding(this, originalFields[i]);
+				this.fields = parameterizedFields;	    
+			} finally {
+				// if the original fields cannot be retrieved (ex. AbortCompilation), then assume we do not have any fields
+				if (this.fields == null) 
+					this.fields = NoFields;
+			}
+		}
+		return this.fields;
+	}
+
+	/**
+	 * Ltype<param1 ... paramN>;
+	 * LY<TT;>;
+	 */
+	public char[] genericTypeSignature() {
+	    if (this.genericTypeSignature == null) {
+		    StringBuffer sig = new StringBuffer(10);
+			if (this.isMemberType() && this.enclosingType().isParameterizedType()) {
+			    char[] typeSig = this.enclosingType().genericTypeSignature();
+			    for (int i = 0; i < typeSig.length-1; i++) sig.append(typeSig[i]); // copy all but trailing semicolon
+			    sig.append('.').append(this.sourceName());
+			} else {
+			    char[] typeSig = this.type.signature();
+			    for (int i = 0; i < typeSig.length-1; i++) sig.append(typeSig[i]); // copy all but trailing semicolon
+			}	   	    
+			if (this.arguments != null) {
+			    sig.append('<');
+			    for (int i = 0, length = this.arguments.length; i < length; i++) {
+			        sig.append(this.arguments[i].genericTypeSignature());
+			    }
+			    sig.append('>'); //$NON-NLS-1$
+			}
+			sig.append(';');
+			int sigLength = sig.length();
+			this.genericTypeSignature = new char[sigLength];
+			sig.getChars(0, sigLength, this.genericTypeSignature, 0);			
+	    }
+		return this.genericTypeSignature;	    
+	}	
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getAnnotationTagBits()
+	 */
+	public long getAnnotationTagBits() {
+		return this.type.getAnnotationTagBits();
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getExactConstructor(TypeBinding[])
+	 */
+	public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
+		int argCount = argumentTypes.length;
+
+		if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
+			nextMethod : for (int m = methods.length; --m >= 0;) {
+				MethodBinding method = methods[m];
+				if (method.selector == TypeConstants.INIT && method.parameters.length == argCount) {
+					TypeBinding[] toMatch = method.parameters;
+					for (int p = 0; p < argCount; p++)
+						if (toMatch[p] != argumentTypes[p])
+							continue nextMethod;
+					return method;
+				}
+			}
+		} else {
+			MethodBinding[] constructors = getMethods(TypeConstants.INIT); // takes care of duplicates & default abstract methods
+			nextConstructor : for (int c = constructors.length; --c >= 0;) {
+				MethodBinding constructor = constructors[c];
+				TypeBinding[] toMatch = constructor.parameters;
+				if (toMatch.length == argCount) {
+					for (int p = 0; p < argCount; p++)
+						if (toMatch[p] != argumentTypes[p])
+							continue nextConstructor;
+					return constructor;
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getExactMethod(char[], TypeBinding[])
+	 */
+	public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
+		// sender from refScope calls recordTypeReference(this)
+		int argCount = argumentTypes.length;
+		int selectorLength = selector.length;
+		boolean foundNothing = true;
+		MethodBinding match = null;
+
+		if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
+			nextMethod : for (int m = methods.length; --m >= 0;) {
+				MethodBinding method = methods[m];
+				if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
+					foundNothing = false; // inner type lookups must know that a method with this name exists
+					if (method.parameters.length == argCount) {
+						TypeBinding[] toMatch = method.parameters;
+						for (int p = 0; p < argCount; p++)
+							if (toMatch[p] != argumentTypes[p])
+								continue nextMethod;
+						if (match != null) return null; // collision case
+						match = method;
+					}
+				}
+			}
+		} else {
+			MethodBinding[] matchingMethods = getMethods(selector); // takes care of duplicates & default abstract methods
+			foundNothing = matchingMethods == NoMethods;
+			nextMethod : for (int m = matchingMethods.length; --m >= 0;) {
+				MethodBinding method = matchingMethods[m];
+				TypeBinding[] toMatch = method.parameters;
+				if (toMatch.length == argCount) {
+					for (int p = 0; p < argCount; p++)
+						if (toMatch[p] != argumentTypes[p])
+							continue nextMethod;
+						if (match != null) return null; // collision case
+						match = method;
+				}
+			}
+		}
+		if (match != null) return match;
+
+		if (foundNothing) {
+			if (isInterface()) {
+				 if (superInterfaces().length == 1) {
+					if (refScope != null)
+						refScope.recordTypeReference(superInterfaces[0]);
+					return superInterfaces[0].getExactMethod(selector, argumentTypes, refScope);
+				 }
+			} else if (superclass() != null) {
+				if (refScope != null)
+					refScope.recordTypeReference(superclass);
+				return superclass.getExactMethod(selector, argumentTypes, refScope);
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getField(char[], boolean)
+	 */
+	public FieldBinding getField(char[] fieldName, boolean needResolve) {
+		fields(); // ensure fields have been initialized... must create all at once unlike methods
+		int fieldLength = fieldName.length;
+		for (int i = fields.length; --i >= 0;) {
+			FieldBinding field = fields[i];
+			if (field.name.length == fieldLength && CharOperation.equals(field.name, fieldName))
+				return field;
+		}
+		return null;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getMemberType(char[])
+	 */
+	public ReferenceBinding getMemberType(char[] typeName) {
+		memberTypes(); // ensure memberTypes have been initialized... must create all at once unlike methods
+		int typeLength = typeName.length;
+		for (int i = this.memberTypes.length; --i >= 0;) {
+			ReferenceBinding memberType = this.memberTypes[i];
+			if (memberType.sourceName.length == typeLength && CharOperation.equals(memberType.sourceName, typeName))
+				return memberType;
+		}
+		return null;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getMethods(char[])
+	 */
+	public MethodBinding[] getMethods(char[] selector) {
+		java.util.ArrayList matchingMethods = null;
+		if (this.methods != null) {
+			int selectorLength = selector.length;
+			for (int i = 0, length = this.methods.length; i < length; i++) {
+				MethodBinding method = this.methods[i];
+				if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
+					if (matchingMethods == null)
+						matchingMethods = new java.util.ArrayList(2);
+					matchingMethods.add(method);
+				}
+			}
+			if (matchingMethods != null) {
+				MethodBinding[] result = new MethodBinding[matchingMethods.size()];
+				matchingMethods.toArray(result);
+				return result;
+			}
+		}
+		if ((modifiers & AccUnresolved) == 0) return NoMethods; // have created all the methods and there are no matches
+
+		MethodBinding[] parameterizedMethods = null;
+		try {
+		    MethodBinding[] originalMethods = this.type.getMethods(selector);
+		    int length = originalMethods.length;
+		    if (length == 0) return NoMethods; 
+
+		    parameterizedMethods = new MethodBinding[length];
+		    for (int i = 0; i < length; i++)
+		    	// substitute methods, so as to get updated declaring class at least
+	            parameterizedMethods[i] = createParameterizedMethod(originalMethods[i]);
+		    if (this.methods == null) {
+		    	MethodBinding[] temp = new MethodBinding[length];
+		    	System.arraycopy(parameterizedMethods, 0, temp, 0, length);
+		    	this.methods = temp; // must be a copy of parameterizedMethods since it will be returned below
+		    } else {
+		    	MethodBinding[] temp = new MethodBinding[length + this.methods.length];
+		    	System.arraycopy(parameterizedMethods, 0, temp, 0, length);
+		    	System.arraycopy(this.methods, 0, temp, length, this.methods.length);
+		    	this.methods = temp;
+			}
+		    return parameterizedMethods;
+		} finally {
+			// if the original methods cannot be retrieved (ex. AbortCompilation), then assume we do not have any methods
+		    if (parameterizedMethods == null) 
+		        this.methods = parameterizedMethods = NoMethods;
+		}
+	}
+	public boolean hasMemberTypes() {
+	    return this.type.hasMemberTypes();
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#implementsMethod(MethodBinding)
+	 */
+	public boolean implementsMethod(MethodBinding method) {
+		return this.type.implementsMethod(method); // erasure
+	}
+
+	void initialize(ReferenceBinding someType, TypeBinding[] someArguments) {
+		this.type = someType;
+		this.sourceName = someType.sourceName;
+		this.compoundName = someType.compoundName;
+		this.fPackage = someType.fPackage;
+		this.fileName = someType.fileName;
+		// should not be set yet
+		// this.superclass = null;
+		// this.superInterfaces = null;
+		// this.fields = null;
+		// this.methods = null;		
+		this.modifiers = someType.modifiers | AccGenericSignature | AccUnresolved; // until methods() is sent
+		if (someArguments != null) {
+			this.arguments = someArguments;
+			for (int i = 0, length = someArguments.length; i < length; i++) {
+				TypeBinding someArgument = someArguments[i];
+				boolean isWildcardArgument = someArgument.isWildcard();
+				if (isWildcardArgument) {
+					this.tagBits |= HasDirectWildcard;
+				}
+				if (!isWildcardArgument || ((WildcardBinding) someArgument).kind != Wildcard.UNBOUND) {
+					this.tagBits |= IsBoundParameterizedType;
+				}
+			    this.tagBits |= someArgument.tagBits & (HasTypeVariable);
+			}
+		}	    
+		this.tagBits |= someType.tagBits & (IsLocalType| IsMemberType | IsNestedType);
+	}
+
+	protected void initializeArguments() {
+	    // do nothing for true parameterized types (only for raw types)
+	}
+	
+	public boolean isEquivalentTo(TypeBinding otherType) {
+		if (this == otherType) 
+		    return true;
+	    if (otherType == null) 
+	        return false;
+	    switch(otherType.kind()) {
+	
+	    	case Binding.WILDCARD_TYPE :
+	        	return ((WildcardBinding) otherType).boundCheck(this);
+	    		
+	    	case Binding.PARAMETERIZED_TYPE :
+	            if ((otherType.tagBits & HasDirectWildcard) == 0 && (!this.isMemberType() || !otherType.isMemberType())) 
+	            	return false; // should have been identical
+	            ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType;
+	            if (this.type != otherParamType.type) 
+	                return false;
+	            if (!isStatic()) { // static member types do not compare their enclosing
+		            ReferenceBinding enclosing = enclosingType();
+		            if (enclosing != null && !enclosing.isEquivalentTo(otherParamType.enclosingType()))
+		                return false;
+	            }
+	            int length = this.arguments == null ? 0 : this.arguments.length;
+	            TypeBinding[] otherArguments = otherParamType.arguments;
+	            int otherLength = otherArguments == null ? 0 : otherArguments.length;
+	            if (otherLength != length) 
+	                return false;
+	            for (int i = 0; i < length; i++) {
+	            	if (!this.arguments[i].isTypeArgumentContainedBy(otherArguments[i]))
+	            		return false;
+	            }
+	            return true;
+	    	
+	    	case Binding.RAW_TYPE :
+	            return erasure() == otherType.erasure();
+	    }
+        return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#isParameterizedType()
+	 */
+	public boolean isParameterizedType() {
+	    return true;
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#memberTypes()
+	 */
+	public ReferenceBinding[] memberTypes() {
+		if (this.memberTypes == null) {
+			try {
+				ReferenceBinding[] originalMemberTypes = this.type.memberTypes();
+				int length = originalMemberTypes.length;
+				ReferenceBinding[] parameterizedMemberTypes = new ReferenceBinding[length];
+				for (int i = 0; i < length; i++)
+					// substitute all member types, so as to get updated enclosing types
+					parameterizedMemberTypes[i] = this.environment.createParameterizedType(originalMemberTypes[i], null, this);
+				this.memberTypes = parameterizedMemberTypes;	    
+			} finally {
+				// if the original fields cannot be retrieved (ex. AbortCompilation), then assume we do not have any fields
+				if (this.memberTypes == null) 
+					this.memberTypes = NoMemberTypes;
+			}
+		}
+		return this.memberTypes;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#methods()
+	 */
+	public MethodBinding[] methods() {
+		if ((modifiers & AccUnresolved) == 0)
+			return this.methods;
+
+		try {
+		    MethodBinding[] originalMethods = this.type.methods();
+		    int length = originalMethods.length;
+		    MethodBinding[] parameterizedMethods = new MethodBinding[length];
+		    for (int i = 0; i < length; i++)
+		    	// substitute all methods, so as to get updated declaring class at least
+	            parameterizedMethods[i] = createParameterizedMethod(originalMethods[i]);
+		    this.methods = parameterizedMethods;
+		} finally {
+			// if the original methods cannot be retrieved (ex. AbortCompilation), then assume we do not have any methods
+		    if (this.methods == null) 
+		        this.methods = NoMethods;
+
+			modifiers &= ~AccUnresolved;
+		}		
+		return this.methods;
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#qualifiedSourceName()
+	 */
+	public char[] qualifiedSourceName() {
+		return this.type.qualifiedSourceName();
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.Binding#readableName()
+	 */
+	public char[] readableName() {
+	    StringBuffer nameBuffer = new StringBuffer(10);
+		if (this.isMemberType()) {
+			nameBuffer.append(CharOperation.concat(this.enclosingType().readableName(), sourceName, '.'));
+		} else {
+			nameBuffer.append(CharOperation.concatWith(this.type.compoundName, '.'));
+		}	    
+		if (this.arguments != null) {
+			nameBuffer.append('<');
+		    for (int i = 0, length = this.arguments.length; i < length; i++) {
+		        if (i > 0) nameBuffer.append(',');
+		        nameBuffer.append(this.arguments[i].readableName());
+		    }
+		    nameBuffer.append('>');
+		}
+		int nameLength = nameBuffer.length();
+		char[] readableName = new char[nameLength];
+		nameBuffer.getChars(0, nameLength, readableName, 0);		
+	    return readableName;
+	}
+
+	ReferenceBinding resolve() {
+		// TODO need flag to know that this has already been done... should it be on ReferenceBinding?
+		ReferenceBinding resolvedType = BinaryTypeBinding.resolveType(this.type, this.environment, false); // still part of parameterized type ref
+		if (this.arguments != null) {
+			int argLength = this.arguments.length;
+			for (int i = 0; i < argLength; i++)
+				BinaryTypeBinding.resolveType(this.arguments[i], this.environment, this, i);
+			// arity check
+			TypeVariableBinding[] refTypeVariables = resolvedType.typeVariables();
+			if (refTypeVariables == NoTypeVariables) { // check generic
+				this.environment.problemReporter.nonGenericTypeCannotBeParameterized(null, resolvedType, this.arguments);
+				return this; // cannot reach here as AbortCompilation is thrown
+			} else if (argLength != refTypeVariables.length) { // check arity
+				this.environment.problemReporter.incorrectArityForParameterizedType(null, resolvedType, this.arguments);
+				return this; // cannot reach here as AbortCompilation is thrown
+			}			
+			// check argument type compatibility
+			for (int i = 0; i < argLength; i++) {
+			    TypeBinding resolvedArgument = this.arguments[i];
+				if (!refTypeVariables[i].boundCheck(this, resolvedArgument)) {
+					this.environment.problemReporter.typeMismatchError(resolvedArgument, refTypeVariables[i], resolvedType, null);
+			    }
+			}
+		}
+		return this;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName()
+	 */
+	public char[] shortReadableName() {
+	    StringBuffer nameBuffer = new StringBuffer(10);
+		if (this.isMemberType()) {
+			nameBuffer.append(CharOperation.concat(this.enclosingType().shortReadableName(), sourceName, '.'));
+		} else {
+			nameBuffer.append(this.type.sourceName);
+		}	    
+		if (this.arguments != null) {
+			nameBuffer.append('<');
+		    for (int i = 0, length = this.arguments.length; i < length; i++) {
+		        if (i > 0) nameBuffer.append(',');
+		        nameBuffer.append(this.arguments[i].shortReadableName());
+		    }
+		    nameBuffer.append('>');
+		}
+		int nameLength = nameBuffer.length();
+		char[] shortReadableName = new char[nameLength];
+		nameBuffer.getChars(0, nameLength, shortReadableName, 0);	    
+	    return shortReadableName;
+	}
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#signature()
+	 */
+	public char[] signature() {
+	    if (this.signature == null) {
+	        this.signature = this.type.signature();  // erasure
+	    }
+		return this.signature; 
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#sourceName()
+	 */
+	public char[] sourceName() {
+		return this.type.sourceName();
+	}
+
+	/**
+	 * Returns a type, where original type was substituted using the receiver
+	 * parameterized type.
+	 */
+	public TypeBinding substitute(TypeBinding originalType) {
+		
+		switch (originalType.kind()) {
+			
+			case Binding.TYPE_PARAMETER:
+				TypeVariableBinding originalVariable = (TypeVariableBinding) originalType;
+				ParameterizedTypeBinding currentType = this;
+				while (true) {
+					if (currentType.arguments != null) {
+						TypeVariableBinding[] typeVariables = currentType.type.typeVariables();
+						int length = typeVariables.length;
+						// check this variable can be substituted given parameterized type
+						if (originalVariable.rank < length && typeVariables[originalVariable.rank] == originalVariable) {
+							return currentType.arguments[originalVariable.rank];
+						}
+					}
+					// recurse on enclosing type, as it may hold more substitutions to perform
+					ReferenceBinding enclosing = currentType.enclosingType();
+					if (!(enclosing instanceof ParameterizedTypeBinding))
+						break;
+					currentType = (ParameterizedTypeBinding) enclosing;
+				}
+				break;
+				
+			case Binding.PARAMETERIZED_TYPE:
+				ParameterizedTypeBinding originalParameterizedType = (ParameterizedTypeBinding) originalType;
+				ReferenceBinding originalEnclosing = originalType.enclosingType();
+				ReferenceBinding substitutedEnclosing = originalEnclosing;
+				if (originalEnclosing != null) {
+					substitutedEnclosing = (ReferenceBinding) this.substitute(originalEnclosing);
+				}
+				TypeBinding[] originalArguments = originalParameterizedType.arguments;
+				TypeBinding[] substitutedArguments = originalArguments;
+				if (originalArguments != null) {
+					substitutedArguments = Scope.substitute(this, originalArguments);
+				}
+				if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) {
+					identicalVariables: { // if substituted with original variables, then answer the generic type itself
+						if (substitutedEnclosing != originalEnclosing) break identicalVariables;
+						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 this.environment.createParameterizedType(
+							originalParameterizedType.type, substitutedArguments, substitutedEnclosing);
+				}
+				break;
+				
+			case Binding.ARRAY_TYPE:
+				TypeBinding originalLeafComponentType = originalType.leafComponentType();
+				TypeBinding substitute = substitute(originalLeafComponentType); // substitute could itself be array type
+				if (substitute != originalLeafComponentType) {
+					return this.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalType.dimensions());
+				}
+				break;
+
+			case Binding.WILDCARD_TYPE:
+		        WildcardBinding wildcard = (WildcardBinding) originalType;
+		        if (wildcard.kind != Wildcard.UNBOUND) {
+			        TypeBinding originalBound = wildcard.bound;
+			        TypeBinding substitutedBound = substitute(originalBound);
+			        if (substitutedBound != originalBound) {
+		        		return this.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, wildcard.kind);
+			        }
+		        }
+				break;
+
+			case Binding.GENERIC_TYPE:
+			    // treat as if parameterized with its type variables
+				ReferenceBinding originalGenericType = (ReferenceBinding) originalType;
+				originalEnclosing = originalType.enclosingType();
+				substitutedEnclosing = originalEnclosing;
+				if (originalEnclosing != null) {
+					substitutedEnclosing = (ReferenceBinding) this.substitute(originalEnclosing);
+				}
+				TypeVariableBinding[] originalVariables = originalGenericType.typeVariables();
+				int length = originalVariables.length;
+				System.arraycopy(originalVariables, 0, originalArguments = new TypeBinding[length], 0, length);
+				substitutedArguments = Scope.substitute(this, originalArguments);
+				if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) {
+					return this.environment.createParameterizedType(
+							originalGenericType, substitutedArguments, substitutedEnclosing);
+				}
+				break;
+		}
+		return originalType;
+	}	
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superclass()
+	 */
+	public ReferenceBinding superclass() {
+	    if (this.superclass == null) {
+	        // note: Object cannot be generic
+	        ReferenceBinding genericSuperclass = this.type.superclass();
+	        if (genericSuperclass == null) return null; // e.g. interfaces
+		    this.superclass = (ReferenceBinding) substitute(genericSuperclass);
+	    }
+		return this.superclass;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superInterfaces()
+	 */
+	public ReferenceBinding[] superInterfaces() {
+	    if (this.superInterfaces == null) {
+	    	this.superInterfaces = Scope.substitute(this, this.type.superInterfaces());
+	    }
+		return this.superInterfaces;
+	}
+
+	public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) {
+		boolean update = false;
+		if (this.type == unresolvedType) {
+			this.type = resolvedType; // cannot be raw since being parameterized below
+			update = true;
+		}
+		if (this.arguments != null) {
+			for (int i = 0, l = this.arguments.length; i < l; i++) {
+				if (this.arguments[i] == unresolvedType) {
+					this.arguments[i] = resolvedType.isGenericType() ? env.createRawType(resolvedType, resolvedType.enclosingType()) : resolvedType;
+					update = true;
+				}
+			}
+		}
+		if (update)
+			initialize(this.type, this.arguments);
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#syntheticEnclosingInstanceTypes()
+	 */
+	public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
+		return this.type.syntheticEnclosingInstanceTypes();
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#syntheticOuterLocalVariables()
+	 */
+	public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
+		return this.type.syntheticOuterLocalVariables();
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#qualifiedPackageName()
+	 */
+	public char[] qualifiedPackageName() {
+		return this.type.qualifiedPackageName();
+	}
+
+	/**
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+	    StringBuffer buffer = new StringBuffer(30);
+		if (isDeprecated()) buffer.append("deprecated "); //$NON-NLS-1$
+		if (isPublic()) buffer.append("public "); //$NON-NLS-1$
+		if (isProtected()) buffer.append("protected "); //$NON-NLS-1$
+		if (isPrivate()) buffer.append("private "); //$NON-NLS-1$
+		if (isAbstract() && isClass()) buffer.append("abstract "); //$NON-NLS-1$
+		if (isStatic() && isNestedType()) buffer.append("static "); //$NON-NLS-1$
+		if (isFinal()) buffer.append("final "); //$NON-NLS-1$
+	
+		buffer.append(isInterface() ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
+		buffer.append(this.debugName());
+	
+		buffer.append("\n\textends "); //$NON-NLS-1$
+		buffer.append((superclass != null) ? superclass.debugName() : "NULL TYPE"); //$NON-NLS-1$
+	
+		if (superInterfaces != null) {
+			if (superInterfaces != NoSuperInterfaces) {
+				buffer.append("\n\timplements : "); //$NON-NLS-1$
+				for (int i = 0, length = superInterfaces.length; i < length; i++) {
+					if (i  > 0)
+						buffer.append(", "); //$NON-NLS-1$
+					buffer.append((superInterfaces[i] != null) ? superInterfaces[i].debugName() : "NULL TYPE"); //$NON-NLS-1$
+				}
+			}
+		} else {
+			buffer.append("NULL SUPERINTERFACES"); //$NON-NLS-1$
+		}
+	
+		if (enclosingType() != null) {
+			buffer.append("\n\tenclosing type : "); //$NON-NLS-1$
+			buffer.append(enclosingType().debugName());
+		}
+	
+		if (fields != null) {
+			if (fields != NoFields) {
+				buffer.append("\n/*   fields   */"); //$NON-NLS-1$
+				for (int i = 0, length = fields.length; i < length; i++)
+				    buffer.append('\n').append((fields[i] != null) ? fields[i].toString() : "NULL FIELD"); //$NON-NLS-1$ 
+			}
+		} else {
+			buffer.append("NULL FIELDS"); //$NON-NLS-1$
+		}
+	
+		if (methods != null) {
+			if (methods != NoMethods) {
+				buffer.append("\n/*   methods   */"); //$NON-NLS-1$
+				for (int i = 0, length = methods.length; i < length; i++)
+					buffer.append('\n').append((methods[i] != null) ? methods[i].toString() : "NULL METHOD"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		} else {
+			buffer.append("NULL METHODS"); //$NON-NLS-1$
+		}
+	
+//		if (memberTypes != null) {
+//			if (memberTypes != NoMemberTypes) {
+//				buffer.append("\n/*   members   */"); //$NON-NLS-1$
+//				for (int i = 0, length = memberTypes.length; i < length; i++)
+//					buffer.append('\n').append((memberTypes[i] != null) ? memberTypes[i].toString() : "NULL TYPE"); //$NON-NLS-1$ //$NON-NLS-2$
+//			}
+//		} else {
+//			buffer.append("NULL MEMBER TYPES"); //$NON-NLS-1$
+//		}
+	
+		buffer.append("\n\n"); //$NON-NLS-1$
+		return buffer.toString();
+		
+	}
+	public TypeVariableBinding[] typeVariables() {
+		if (this.arguments == null) {
+			// retain original type variables if not substituted (member type of parameterized type)
+			return this.type.typeVariables();
+		} 
+		return NoTypeVariables;
+	}	
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemBinding.java
index c4fab5f..b1dd4db 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemBinding.java
@@ -38,7 +38,7 @@
 * Answer the receiver's binding type from Binding.BindingID.
 */
 
-public final int bindingType() {
+public final int kind() {
 	return VARIABLE | TYPE;
 }
 /* API
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
index 71f0547..e5ae8db 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
@@ -11,21 +11,23 @@
 package org.eclipse.jdt.internal.compiler.lookup;
 
 public class ProblemMethodBinding extends MethodBinding {
-	private int problemId;
-	public MethodBinding closestMatch;
-public ProblemMethodBinding(char[] selector, TypeBinding[] args, int problemId) {
+    
+	private int problemReason;
+	public MethodBinding closestMatch; // TODO (philippe) should rename into #alternateMatch
+	
+public ProblemMethodBinding(char[] selector, TypeBinding[] args, int problemReason) {
 	this.selector = selector;
 	this.parameters = (args == null || args.length == 0) ? NoParameters : args;
-	this.problemId = problemId;
+	this.problemReason = problemReason;
 }
-public ProblemMethodBinding(char[] selector, TypeBinding[] args, ReferenceBinding declaringClass, int problemId) {
+public ProblemMethodBinding(char[] selector, TypeBinding[] args, ReferenceBinding declaringClass, int problemReason) {
 	this.selector = selector;
 	this.parameters = (args == null || args.length == 0) ? NoParameters : args;
 	this.declaringClass = declaringClass;
-	this.problemId = problemId;
+	this.problemReason = problemReason;
 }
-public ProblemMethodBinding(MethodBinding closestMatch, char[] selector, TypeBinding[] args, int problemId) {
-	this(selector, args, problemId);
+public ProblemMethodBinding(MethodBinding closestMatch, char[] selector, TypeBinding[] args, int problemReason) {
+	this(selector, args, problemReason);
 	this.closestMatch = closestMatch;
 	if (closestMatch != null) this.declaringClass = closestMatch.declaringClass;
 }
@@ -35,6 +37,6 @@
 */
 
 public final int problemId() {
-	return problemId;
+	return this.problemReason;
 }
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
index b34f200..97570b7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
@@ -20,4 +20,10 @@
 	final int NonStaticReferenceInConstructorInvocation = 6;
 	final int NonStaticReferenceInStaticContext = 7;
 	final int ReceiverTypeNotVisible = 8;
+	final int IllegalSuperTypeVariable = 9;
+	final int ParameterBoundMismatch = 10; // for generic method
+	final int TypeParameterArityMismatch = 11; // for generic method
+	final int ParameterizedMethodTypeMismatch = 12; // for generic method
+	final int TypeArgumentsForRawGenericMethod = 13; // for generic method
+	final int InvalidTypeForStaticImport = 14;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
index 7225ba7..00d8a18 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
@@ -12,31 +12,32 @@
 
 public class ProblemReferenceBinding extends ReferenceBinding {
 	public ReferenceBinding original;
-	private int problemId;
+	private int problemReason;
+	public ReferenceBinding alternateMatch;
+	
 // NOTE: must only answer the subset of the name related to the problem
 
-public ProblemReferenceBinding(char[][] compoundName, int problemId) {
-	this(compoundName, null, problemId);
+public ProblemReferenceBinding(char[][] compoundName, int problemReason) {
+	this(compoundName, null, problemReason);
 }
-public ProblemReferenceBinding(char[] name, int problemId) {
-	this(new char[][] {name}, null, problemId);
+public ProblemReferenceBinding(char[] name, int problemReason) {
+	this(new char[][] {name}, null, problemReason);
 }
 
-public ProblemReferenceBinding(char[][] compoundName, ReferenceBinding original, int problemId) {
+public ProblemReferenceBinding(char[][] compoundName, ReferenceBinding original, int problemReason) {
 	this.compoundName = compoundName;
 	this.original = original;
-	this.problemId = problemId;
+	this.problemReason = problemReason;
 }
-public ProblemReferenceBinding(char[] name, ReferenceBinding original, int problemId) {
-	this(new char[][] {name}, original, problemId);
+public ProblemReferenceBinding(char[] name, ReferenceBinding original, int problemReason) {
+	this(new char[][] {name}, original, problemReason);
 }
 /* API
 * Answer the problem id associated with the receiver.
 * NoError if the receiver is a valid binding.
 */
-
-public final int problemId() {
-	return problemId;
+public int problemId() {
+	return this.problemReason;
 }
 
 /**
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java
new file mode 100644
index 0000000..ce950e2
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+
+/**
+ * Denote a raw type, i.e. a generic type referenced without any type arguments.
+ * e.g. X<T extends Exception> can be used a raw type 'X', in which case it
+ * 	will behave as X<Exception>
+ */
+public class RawTypeBinding extends ParameterizedTypeBinding {
+    
+    /**
+     * Raw type arguments are erasure of respective parameter bounds. But we may not have resolved
+     * these bounds yet if creating raw types while supertype hierarchies are being connected.
+     * Therefore, use 'null' instead, and access these in a lazy way later on (when substituting).
+     */
+	public RawTypeBinding(ReferenceBinding type, ReferenceBinding enclosingType, LookupEnvironment environment){
+		super(type, null, enclosingType, environment);
+		if (enclosingType == null || (enclosingType.modifiers & AccGenericSignature) == 0)
+			this.modifiers &= ~AccGenericSignature; // only need signature if enclosing needs one
+	}    
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding#createParameterizedMethod(org.eclipse.jdt.internal.compiler.lookup.MethodBinding)
+	 */
+	public ParameterizedMethodBinding createParameterizedMethod(MethodBinding originalMethod) {
+		if (originalMethod.typeVariables == NoTypeVariables || originalMethod.isStatic()) {
+			return super.createParameterizedMethod(originalMethod);
+		}
+		return new ParameterizedGenericMethodBinding(originalMethod, this, this.environment);
+	}
+	
+	public int kind() {
+		return RAW_TYPE;
+	}	
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName()
+	 */
+	public String debugName() {
+	    StringBuffer nameBuffer = new StringBuffer(10);
+		nameBuffer.append(this.type.sourceName()).append("#RAW"); //$NON-NLS-1$
+	    return nameBuffer.toString();		
+	}	
+
+	/**
+	 * Ltype<param1 ... paramN>;
+	 * LY<TT;>;
+	 */
+	public char[] genericTypeSignature() {
+
+	    if (this.genericTypeSignature == null) {
+		    StringBuffer sig = new StringBuffer(10);
+			if (this.isMemberType() && this.enclosingType().isParameterizedType()) {
+			    char[] typeSig = this.enclosingType().genericTypeSignature();
+			    for (int i = 0; i < typeSig.length-1; i++) sig.append(typeSig[i]); // copy all but trailing semicolon
+			    sig.append('.').append(this.sourceName()).append(';');
+				int sigLength = sig.length();
+				this.genericTypeSignature = new char[sigLength];
+				sig.getChars(0, sigLength, this.genericTypeSignature, 0);						    
+			} else {
+			     this.genericTypeSignature = this.type.signature(); // erasure
+			}
+	    }
+	   return this.genericTypeSignature;
+	}		
+	
+    public boolean isEquivalentTo(TypeBinding otherType) {
+	    if (this == otherType) return true;
+        if (otherType == null) return false;
+		if (otherType.isWildcard()) // wildcard
+			return ((WildcardBinding) otherType).boundCheck(this);
+        return otherType.erasure() == this.erasure();
+    }
+	/**
+	 * Raw type is not treated as a standard parameterized type
+	 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#isParameterizedType()
+	 */
+	public boolean isParameterizedType() {
+	    return false;
+	}	
+	public boolean isRawType() {
+	    return true;
+	}	
+	
+	protected void initializeArguments() {
+		TypeVariableBinding[] typeVariables = this.type.typeVariables();
+		int length = typeVariables.length;
+		TypeBinding[] typeArguments = new TypeBinding[length];
+		for (int i = 0; i < length; i++) {
+		    typeArguments[i] = typeVariables[i].erasure();
+		}
+		this.arguments = typeArguments;
+	}
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.Binding#readableName()
+	 */
+	public char[] readableName() /*java.lang.Object,  p.X<T> */ {
+	    char[] readableName;
+		if (isMemberType()) {
+			readableName = CharOperation.concat(enclosingType().readableName(), sourceName, '.');
+		} else {
+			readableName = CharOperation.concatWith(this.type.compoundName, '.');
+		}
+		return readableName;
+	}
+
+	/**
+	 * Returns a type, where original type was substituted using the receiver
+	 * raw type.
+	 * On raw types, all parameterized type denoting same original type are converted
+	 * to raw types. e.g. 
+	 * class X <T> {
+	 *   X<T> foo;
+	 *   X<String> bar;
+	 * } when used in raw fashion, then type of both foo and bar is raw type X.
+	 */
+	public TypeBinding substitute(TypeBinding originalType) {
+	    
+		switch (originalType.kind()) {
+			
+			case Binding.TYPE_PARAMETER:
+		        TypeVariableBinding originalVariable = (TypeVariableBinding) originalType;
+			    ParameterizedTypeBinding currentType = this;
+		        while (true) {
+			        TypeVariableBinding[] typeVariables = currentType.type.typeVariables();
+			        int length = typeVariables.length;
+			        // check this variable can be substituted given parameterized type
+			        if (originalVariable.rank < length && typeVariables[originalVariable.rank] == originalVariable) {
+					    // lazy init, since cannot do so during binding creation if during supertype connection
+					    if (currentType.arguments == null)  currentType.initializeArguments();
+					    if (currentType.arguments != null)
+				           return currentType.arguments[originalVariable.rank];
+			        }
+				    // recurse on enclosing type, as it may hold more substitutions to perform
+				    ReferenceBinding enclosing = currentType.enclosingType();
+				    if (!(enclosing instanceof ParameterizedTypeBinding))
+				        break;
+				    currentType = (ParameterizedTypeBinding) enclosing;
+		        }
+		        break;
+		        
+			case Binding.PARAMETERIZED_TYPE:
+				ReferenceBinding substitutedEnclosing = originalType.enclosingType();
+				if (substitutedEnclosing != null) {
+					substitutedEnclosing = (ReferenceBinding) this.substitute(substitutedEnclosing);
+				}				
+		        ParameterizedTypeBinding originalParameterizedType = (ParameterizedTypeBinding) originalType;
+				return this.environment.createRawType(originalParameterizedType.type, substitutedEnclosing);
+				
+			case Binding.GENERIC_TYPE:
+				substitutedEnclosing = originalType.enclosingType();
+				if (substitutedEnclosing != null) {
+					substitutedEnclosing = (ReferenceBinding) this.substitute(substitutedEnclosing);
+				}				
+	            return this.environment.createRawType((ReferenceBinding)originalType, substitutedEnclosing);
+	            
+			case Binding.WILDCARD_TYPE:
+		        WildcardBinding wildcard = (WildcardBinding) originalType;
+		        if (wildcard.kind != Wildcard.UNBOUND) {
+			        TypeBinding originalBound = wildcard.bound;
+			        TypeBinding substitutedBound = substitute(originalBound);
+			        if (substitutedBound != originalBound) {
+		        		return this.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, wildcard.kind);
+			        }
+		        }
+		        break;
+		        
+			case Binding.ARRAY_TYPE:
+				TypeBinding originalLeafComponentType = originalType.leafComponentType();
+				TypeBinding substitute = substitute(originalLeafComponentType); // substitute could itself be array type
+				if (substitute != originalLeafComponentType) {
+					return this.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalType.dimensions());
+				}
+				break;
+	    }
+	    return originalType;
+	}	
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName()
+	 */
+	public char[] shortReadableName() /*Object*/ {
+	    char[] shortReadableName;
+		if (isMemberType()) {
+			shortReadableName = CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
+		} else {
+			shortReadableName = this.type.sourceName;
+		}
+		return shortReadableName;
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
index 6cda282..f4912d1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
@@ -45,7 +45,7 @@
 */
 
 public boolean canBeInstantiated() {
-	return !(isAbstract() || isInterface());
+	return (this.modifiers & (AccAbstract | AccInterface | AccEnum | AccAnnotation)) == 0;
 }
 /* Answer true if the receiver is visible to the invocationPackage.
 */
@@ -91,7 +91,19 @@
 	if (isPrivate()) {
 		// answer true if the receiverType is the receiver or its enclosingType
 		// AND the invocationType and the receiver have a common enclosingType
-		if (!(receiverType == this || receiverType == enclosingType())) return false;
+		receiverCheck: {
+			if (!(receiverType == this || receiverType == enclosingType())) {
+				// special tolerance for type variable direct bounds
+				if (receiverType.isTypeVariable()) {
+					TypeVariableBinding typeVariable = (TypeVariableBinding) receiverType;
+					if (typeVariable.isErasureBoundTo(this.erasure()) || typeVariable.isErasureBoundTo(enclosingType().erasure())) {
+						break receiverCheck;
+					}
+				}
+				return false;
+			}
+		}
+		
 		
 		if (invocationType != this) {
 			ReferenceBinding outerInvocationType = invocationType;
@@ -101,7 +113,7 @@
 				temp = temp.enclosingType();
 			}
 
-			ReferenceBinding outerDeclaringClass = this;
+			ReferenceBinding outerDeclaringClass = (ReferenceBinding)this.erasure();
 			temp = outerDeclaringClass.enclosingType();
 			while (temp != null) {
 				outerDeclaringClass = temp;
@@ -168,7 +180,7 @@
 			temp = temp.enclosingType();
 		}
 
-		ReferenceBinding outerDeclaringClass = this;
+		ReferenceBinding outerDeclaringClass = (ReferenceBinding)this.erasure();
 		temp = outerDeclaringClass.enclosingType();
 		while (temp != null) {
 			outerDeclaringClass = temp;
@@ -181,96 +193,157 @@
 	return invocationType.fPackage == fPackage;
 }
 public void computeId() {
-	if (compoundName.length != 3) {
-		if (compoundName.length == 4 && CharOperation.equals(JAVA_LANG_REFLECT_CONSTRUCTOR, compoundName))
-			id = T_JavaLangReflectConstructor;
-		return;
-	}
+	
+	switch (compoundName.length) {
 
-	if (!CharOperation.equals(JAVA, compoundName[0]))
-		return;
-
-	// remaining types MUST be in java.*.*
-	if (!CharOperation.equals(LANG, compoundName[1])) {
-		if (CharOperation.equals(JAVA_IO_PRINTSTREAM, compoundName))
-			id = T_JavaIoPrintStream;
-		else if (CharOperation.equals(JAVA_IO_SERIALIZABLE, compoundName))
-		    id = T_JavaIoSerializable;
-		return;
-	}
-
-	// remaining types MUST be in java.lang.*
-	char[] typeName = compoundName[2];
-	if (typeName.length == 0) return; // just to be safe
-	switch (typeName[0]) {
-		case 'A' :
-			if (CharOperation.equals(typeName, JAVA_LANG_ASSERTIONERROR[2]))
-				id = T_JavaLangAssertionError;
-			return;
-		case 'B' :
-			if (CharOperation.equals(typeName, JAVA_LANG_BOOLEAN[2]))
-				id = T_JavaLangBoolean;
-			else if (CharOperation.equals(typeName, JAVA_LANG_BYTE[2]))
-				id = T_JavaLangByte;
-			return;
-		case 'C' :
-			if (CharOperation.equals(typeName, JAVA_LANG_CHARACTER[2]))
-				id = T_JavaLangCharacter;
-			else if (CharOperation.equals(typeName, JAVA_LANG_CLASS[2]))
-				id = T_JavaLangClass;
-			else if (CharOperation.equals(typeName, JAVA_LANG_CLASSNOTFOUNDEXCEPTION[2]))
-				id = T_JavaLangClassNotFoundException;
-			else if (CharOperation.equals(typeName, JAVA_LANG_CLONEABLE[2]))
-			    id = T_JavaLangCloneable;
-			return;
-		case 'D' :
-			if (CharOperation.equals(typeName, JAVA_LANG_DOUBLE[2]))
-				id = T_JavaLangDouble;
-			return;
-		case 'E' :
-			if (CharOperation.equals(typeName, JAVA_LANG_ERROR[2]))
-				id = T_JavaLangError;
-			else if (CharOperation.equals(typeName, JAVA_LANG_EXCEPTION[2]))
-				id = T_JavaLangException;
-			return;
-		case 'F' :
-			if (CharOperation.equals(typeName, JAVA_LANG_FLOAT[2]))
-				id = T_JavaLangFloat;
-			return;
-		case 'I' :
-			if (CharOperation.equals(typeName, JAVA_LANG_INTEGER[2]))
-				id = T_JavaLangInteger;
-			return;
-		case 'L' :
-			if (CharOperation.equals(typeName, JAVA_LANG_LONG[2]))
-				id = T_JavaLangLong;
-			return;
-		case 'N' :
-			if (CharOperation.equals(typeName, JAVA_LANG_NOCLASSDEFERROR[2]))
-				id = T_JavaLangNoClassDefError;
-			return;
-		case 'O' :
-			if (CharOperation.equals(typeName, JAVA_LANG_OBJECT[2]))
-				id = T_JavaLangObject;
-			return;
-		case 'S' :
-			if (CharOperation.equals(typeName, JAVA_LANG_STRING[2]))
-				id = T_JavaLangString;
-			else if (CharOperation.equals(typeName, JAVA_LANG_STRINGBUFFER[2]))
-				id = T_JavaLangStringBuffer;
-			else if (CharOperation.equals(typeName, JAVA_LANG_SYSTEM[2]))
-				id = T_JavaLangSystem;
-			else if (CharOperation.equals(typeName, JAVA_LANG_SHORT[2]))
-				id = T_JavaLangShort;
-			return;
-		case 'T' :
-			if (CharOperation.equals(typeName, JAVA_LANG_THROWABLE[2]))
-				id = T_JavaLangThrowable;
-			return;
-		case 'V' :
-			if (CharOperation.equals(typeName, JAVA_LANG_VOID[2]))
-				id = T_JavaLangVoid;
-			return;
+		case 3 :
+			if (!CharOperation.equals(JAVA, compoundName[0]))
+				return;
+		
+			// remaining types MUST be in java.*.*
+			if (!CharOperation.equals(LANG, compoundName[1])) {
+				if (CharOperation.equals(JAVA_IO_PRINTSTREAM, compoundName))
+					id = T_JavaIoPrintStream;
+				else if (CharOperation.equals(JAVA_UTIL_ITERATOR, compoundName))
+					id = T_JavaUtilIterator;
+				else if (CharOperation.equals(JAVA_IO_SERIALIZABLE, compoundName))
+				    id = T_JavaIoSerializable;
+				return;
+			}
+		
+			// remaining types MUST be in java.lang.*
+			char[] typeName = compoundName[2];
+			if (typeName.length == 0) return; // just to be safe
+			switch (typeName[0]) {
+				case 'A' :
+					if (CharOperation.equals(typeName, JAVA_LANG_ASSERTIONERROR[2]))
+						id = T_JavaLangAssertionError;
+					return;
+				case 'B' :
+					if (CharOperation.equals(typeName, JAVA_LANG_BOOLEAN[2]))
+						id = T_JavaLangBoolean;
+					else if (CharOperation.equals(typeName, JAVA_LANG_BYTE[2]))
+						id = T_JavaLangByte;
+					return;
+				case 'C' :
+					if (CharOperation.equals(typeName, JAVA_LANG_CHARACTER[2]))
+						id = T_JavaLangCharacter;
+					else if (CharOperation.equals(typeName, JAVA_LANG_CLASS[2]))
+						id = T_JavaLangClass;
+					else if (CharOperation.equals(typeName, JAVA_LANG_CLASSNOTFOUNDEXCEPTION[2]))
+						id = T_JavaLangClassNotFoundException;
+					else if (CharOperation.equals(typeName, JAVA_LANG_CLONEABLE[2]))
+					    id = T_JavaLangCloneable;
+					return;
+				case 'D' :
+					if (CharOperation.equals(typeName, JAVA_LANG_DOUBLE[2]))
+						id = T_JavaLangDouble;
+					else if (CharOperation.equals(typeName, JAVA_LANG_DEPRECATED[2]))
+						id = T_JavaLangDeprecated;
+					return;
+				case 'E' :
+					if (CharOperation.equals(typeName, JAVA_LANG_ERROR[2]))
+						id = T_JavaLangError;
+					else if (CharOperation.equals(typeName, JAVA_LANG_EXCEPTION[2]))
+						id = T_JavaLangException;
+					else if (CharOperation.equals(typeName, JAVA_LANG_ENUM[2]))
+						id = T_JavaLangEnum;
+					return;
+				case 'F' :
+					if (CharOperation.equals(typeName, JAVA_LANG_FLOAT[2]))
+						id = T_JavaLangFloat;
+					return;
+				case 'I' :
+					if (CharOperation.equals(typeName, JAVA_LANG_INTEGER[2]))
+						id = T_JavaLangInteger;
+					else if (CharOperation.equals(typeName, JAVA_LANG_ITERABLE[2]))
+						id = T_JavaLangIterable;
+					else if (CharOperation.equals(typeName, JAVA_LANG_ILLEGALARGUMENTEXCEPTION[2]))
+						id = T_JavaLangIllegalArgumentException;
+					return;
+				case 'L' :
+					if (CharOperation.equals(typeName, JAVA_LANG_LONG[2]))
+						id = T_JavaLangLong;
+					return;
+				case 'N' :
+					if (CharOperation.equals(typeName, JAVA_LANG_NOCLASSDEFERROR[2]))
+						id = T_JavaLangNoClassDefError;
+					return;
+				case 'O' :
+					if (CharOperation.equals(typeName, JAVA_LANG_OBJECT[2]))
+						id = T_JavaLangObject;
+					else if (CharOperation.equals(typeName, JAVA_LANG_OVERRIDE[2]))
+						id = T_JavaLangOverride;
+					return;
+				case 'S' :
+					if (CharOperation.equals(typeName, JAVA_LANG_STRING[2]))
+						id = T_JavaLangString;
+					else if (CharOperation.equals(typeName, JAVA_LANG_STRINGBUFFER[2]))
+						id = T_JavaLangStringBuffer;
+					else if (CharOperation.equals(typeName, JAVA_LANG_STRINGBUILDER[2])) 
+						id = T_JavaLangStringBuilder;
+					else if (CharOperation.equals(typeName, JAVA_LANG_SYSTEM[2]))
+						id = T_JavaLangSystem;
+					else if (CharOperation.equals(typeName, JAVA_LANG_SHORT[2]))
+						id = T_JavaLangShort;
+					else if (CharOperation.equals(typeName, JAVA_LANG_SUPPRESSWARNINGS[2]))
+						id = T_JavaLangSuppressWarnings;
+					return;
+				case 'T' :
+					if (CharOperation.equals(typeName, JAVA_LANG_THROWABLE[2]))
+						id = T_JavaLangThrowable;
+					return;
+				case 'V' :
+					if (CharOperation.equals(typeName, JAVA_LANG_VOID[2]))
+						id = T_JavaLangVoid;
+					return;
+			}
+		break;
+			
+		case 4:
+			if (!CharOperation.equals(JAVA, compoundName[0]))
+				return;
+			if (!CharOperation.equals(LANG, compoundName[1]))
+				return;
+			char[] packageName = compoundName[2];
+			if (packageName.length == 0) return; // just to be safe			
+			typeName = compoundName[3];
+			if (typeName.length == 0) return; // just to be safe			
+			if (CharOperation.equals(packageName, REFLECT)) {
+				if (CharOperation.equals(typeName, JAVA_LANG_REFLECT_CONSTRUCTOR[3]))
+					id = T_JavaLangReflectConstructor;
+				return;
+			} else if (CharOperation.equals(packageName, ANNOTATION)) {
+				switch (typeName[0]) {
+					case 'A' :			
+						if (CharOperation.equals(typeName, JAVA_LANG_ANNOTATION_ANNOTATION[3]))
+							id = T_JavaLangAnnotationAnnotation;
+						return;
+					case 'D' :
+						if (CharOperation.equals(typeName, JAVA_LANG_ANNOTATION_DOCUMENTED[3]))
+							id = T_JavaLangAnnotationDocumented;
+						return;
+					case 'E' :
+						if (CharOperation.equals(typeName, JAVA_LANG_ANNOTATION_ELEMENTTYPE[3]))
+							id = T_JavaLangAnnotationElementType;
+						return;
+					case 'I' :
+						if (CharOperation.equals(typeName, JAVA_LANG_ANNOTATION_INHERITED[3]))
+							id = T_JavaLangAnnotationInherited;
+						return;
+					case 'R' :
+						if (CharOperation.equals(typeName, JAVA_LANG_ANNOTATION_RETENTION[3]))
+							id = T_JavaLangAnnotationRetention;
+						else if (CharOperation.equals(typeName, JAVA_LANG_ANNOTATION_RETENTIONPOLICY[3]))
+							id = T_JavaLangAnnotationRetentionPolicy;
+						return;
+					case 'T' :
+						if (CharOperation.equals(typeName, JAVA_LANG_ANNOTATION_TARGET[3]))
+							id = T_JavaLangAnnotationTarget;
+						return;
+				}				
+			}
+			break;
 	}
 }
 /* Answer the receiver's constant pool name.
@@ -282,7 +355,7 @@
 	if (constantPoolName != null) 	return constantPoolName;
 	return constantPoolName = CharOperation.concatWith(compoundName, '/');
 }
-String debugName() {
+public String debugName() {
 	return (compoundName != null) ? new String(readableName()) : "UNNAMED TYPE"; //$NON-NLS-1$
 }
 public final int depth() {
@@ -292,12 +365,6 @@
 		depth++;
 	return depth;
 }
-/* Answer the receiver's enclosing type... null if the receiver is a top level type.
-*/
-
-public ReferenceBinding enclosingType() {
-	return null;
-}
 public final ReferenceBinding enclosingTypeAt(int relativeDepth) {
 	ReferenceBinding current = this;
 	while (relativeDepth-- > 0 && current != null)
@@ -310,29 +377,118 @@
 public FieldBinding[] fields() {
 	return NoFields;
 }
+/**
+ * Find supertype which erases to a given well-known type, or null if not found
+ * (using id avoids triggering the load of well-known type: 73740)
+ * NOTE: only works for erasures of well-known types, as random other types may share
+ * same id though being distincts.
+ *
+ */
+public ReferenceBinding findSuperTypeErasingTo(int erasureId, boolean erasureIsClass) {
+
+    if (this.id == erasureId || erasure().id == erasureId) return this;
+    ReferenceBinding currentType = this;
+    // iterate superclass to avoid recording interfaces if searched supertype is class
+    if (erasureIsClass) {
+		while ((currentType = currentType.superclass()) != null) { 
+			if (currentType.id == erasureId || currentType.erasure().id == erasureId) return currentType;
+		}    
+		return null;
+    }
+	ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
+	int lastPosition = -1;
+	do {
+		ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+		if (itsInterfaces != NoSuperInterfaces) {
+			if (++lastPosition == interfacesToVisit.length)
+				System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+			interfacesToVisit[lastPosition] = itsInterfaces;
+		}
+	} while ((currentType = currentType.superclass()) != null);
+			
+	for (int i = 0; i <= lastPosition; i++) {
+		ReferenceBinding[] interfaces = interfacesToVisit[i];
+		for (int j = 0, length = interfaces.length; j < length; j++) {
+			if ((currentType = interfaces[j]).id == erasureId || currentType.erasure().id == erasureId)
+				return currentType;
+
+			ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+			if (itsInterfaces != NoSuperInterfaces) {
+				if (++lastPosition == interfacesToVisit.length)
+					System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+				interfacesToVisit[lastPosition] = itsInterfaces;
+			}
+		}
+	}
+	return null;
+}
+/**
+ * Find supertype which erases to a given type, or null if not found
+ */
+public ReferenceBinding findSuperTypeErasingTo(ReferenceBinding erasure) {
+
+    if (this == erasure || erasure() == erasure) return this;
+    ReferenceBinding currentType = this;
+    if (erasure.isClass()) {
+		while ((currentType = currentType.superclass()) != null) {
+			if (currentType == erasure || currentType.erasure() == erasure) return currentType;
+		}
+		return null;
+    }
+	ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
+	int lastPosition = -1;
+	do {
+		ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+		if (itsInterfaces != NoSuperInterfaces) {
+			if (++lastPosition == interfacesToVisit.length)
+				System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+			interfacesToVisit[lastPosition] = itsInterfaces;
+		}
+	} while ((currentType = currentType.superclass()) != null);
+			
+	for (int i = 0; i <= lastPosition; i++) {
+		ReferenceBinding[] interfaces = interfacesToVisit[i];
+		for (int j = 0, length = interfaces.length; j < length; j++) {
+			if ((currentType = interfaces[j]) == erasure || currentType.erasure() == erasure)
+				return currentType;
+
+			ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+			if (itsInterfaces != NoSuperInterfaces) {
+				if (++lastPosition == interfacesToVisit.length)
+					System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+				interfacesToVisit[lastPosition] = itsInterfaces;
+			}
+		}
+	}
+	return null;
+}
+
 public final int getAccessFlags() {
 	return modifiers & AccJustFlag;
 }
+
+/**
+ * @see org.eclipse.jdt.internal.compiler.lookup.Binding#getAnnotationTagBits()
+ */
+public long getAnnotationTagBits() {
+	return this.tagBits;
+}
+
 public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
 	return null;
 }
 public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes) {
+	return getExactMethod(selector, argumentTypes, null);
+}
+public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
 	return null;
 }
 public FieldBinding getField(char[] fieldName, boolean needResolve) {
 	return null;
 }
 /**
- * Answer the file name which defines the type.
- *
- * The path part (optional) must be separated from the actual
- * file proper name by a java.io.File.separator.
- *
- * The proper file name includes the suffix extension (e.g. ".java")
- *
- * e.g. "c:/com/ibm/compiler/java/api/Compiler.java" 
+ * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
  */
-
 public char[] getFileName() {
 	return fileName;
 }
@@ -352,12 +508,30 @@
 public boolean hasMemberTypes() {
     return false;
 }
+public TypeVariableBinding getTypeVariable(char[] variableName) {
+	TypeVariableBinding[] typeVariables = typeVariables();
+	for (int i = typeVariables.length; --i >= 0;)
+		if (CharOperation.equals(typeVariables[i].sourceName, variableName))
+			return typeVariables[i];
+	return null;
+}
+public int hashCode() {
+	// ensure ReferenceBindings hash to the same posiiton as UnresolvedReferenceBindings so they can be replaced without rehashing
+	// ALL ReferenceBindings are unique when created so equals() is the same as ==
+	return (this.compoundName == null || this.compoundName.length == 0)
+		? super.hashCode()
+		: CharOperation.hashCode(this.compoundName[this.compoundName.length - 1]);
+}
+
+public final boolean hasRestrictedAccess() {
+	return (modifiers & AccRestrictedAccess) != 0;
+}
+
 /* Answer true if the receiver implements anInterface or is identical to anInterface.
 * If searchHierarchy is true, then also search the receiver's superclasses.
 *
 * NOTE: Assume that anInterface is an interface.
 */
-
 public boolean implementsInterface(ReferenceBinding anInterface, boolean searchHierarchy) {
 	if (this == anInterface)
 		return true;
@@ -377,7 +551,7 @@
 	for (int i = 0; i <= lastPosition; i++) {
 		ReferenceBinding[] interfaces = interfacesToVisit[i];
 		for (int j = 0, length = interfaces.length; j < length; j++) {
-			if ((currentType = interfaces[j]) == anInterface)
+			if ((currentType = interfaces[j]).isEquivalentTo(anInterface))
 				return true;
 
 			ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
@@ -409,66 +583,72 @@
 public final boolean isAbstract() {
 	return (modifiers & AccAbstract) != 0;
 }
+public boolean isAnnotationType() {
+	return (modifiers & AccAnnotation) != 0;
+}
 public final boolean isAnonymousType() {
 	return (tagBits & IsAnonymousType) != 0;
 }
 public final boolean isBinaryBinding() {
 	return (tagBits & IsBinaryBinding) != 0;
 }
-public final boolean isClass() {
-	return (modifiers & AccInterface) == 0;
+public boolean isClass() {
+	return (modifiers & (AccInterface | AccAnnotation | AccEnum)) == 0;
+}
+/*
+ * Returns true if the type hierarchy is being connected
+ */
+public boolean isHierarchyBeingConnected() {
+	return (this.tagBits & EndHierarchyCheck) == 0 && (this.tagBits & BeginHierarchyCheck) != 0;
 }
 /* Answer true if the receiver type can be assigned to the argument type (right)
 */
-	
-public boolean isCompatibleWith(TypeBinding right) {
-	if (right == this)
+public boolean isCompatibleWith(TypeBinding otherType) {
+    
+	if (otherType == this)
 		return true;
-	if (right.id == T_Object)
+	if (otherType.id == T_JavaLangObject)
 		return true;
-	if (!(right instanceof ReferenceBinding))
+	if (!(otherType instanceof ReferenceBinding))
 		return false;
-
-	ReferenceBinding referenceBinding = (ReferenceBinding) right;
-	if (referenceBinding.isInterface())
-		return implementsInterface(referenceBinding, true);
+	ReferenceBinding otherReferenceType = (ReferenceBinding) otherType;
+	if (this.isEquivalentTo(otherReferenceType)) return true;
+	if (otherReferenceType.isWildcard()) {
+		return false; // should have passed equivalence check above if wildcard
+	}
+	if (otherReferenceType.isInterface())
+		return implementsInterface(otherReferenceType, true);
 	if (isInterface())  // Explicit conversion from an interface to a class is not allowed
 		return false;
-	return referenceBinding.isSuperclassOf(this);
+	return otherReferenceType.isSuperclassOf(this);
 }
+
 /* Answer true if the receiver has default visibility
 */
-
 public final boolean isDefault() {
 	return (modifiers & (AccPublic | AccProtected | AccPrivate)) == 0;
 }
+
 /* Answer true if the receiver is a deprecated type
 */
-
 public final boolean isDeprecated() {
 	return (modifiers & AccDeprecated) != 0;
 }
+public boolean isEnum() {
+	return (modifiers & AccEnum) != 0;
+}
 /* Answer true if the receiver is final and cannot be subclassed
 */
-
 public final boolean isFinal() {
 	return (modifiers & AccFinal) != 0;
 }
-public final boolean isInterface() {
-	return (modifiers & AccInterface) != 0;
+public boolean isInterface() {
+	// only consider strict interfaces
+	return (modifiers & (AccInterface | AccAnnotation)) == AccInterface;
 }
-public final boolean isLocalType() {
-	return (tagBits & IsLocalType) != 0;
-}
-public final boolean isMemberType() {
-	return (tagBits & IsMemberType) != 0;
-}
-public final boolean isNestedType() {
-	return (tagBits & IsNestedType) != 0;
-}
+
 /* Answer true if the receiver has private visibility
 */
-
 public final boolean isPrivate() {
 	return (modifiers & AccPrivate) != 0;
 }
@@ -508,13 +688,13 @@
 * NOTE: Object.isSuperclassOf(Object) -> false
 */
 
-public boolean isSuperclassOf(ReferenceBinding type) {
-	do {
-		if (this == (type = type.superclass())) return true;
-	} while (type != null);
-
+public boolean isSuperclassOf(ReferenceBinding otherType) {
+	while ((otherType = otherType.superclass()) != null) {
+		if (otherType.isEquivalentTo(this)) return true;
+	}
 	return false;
 }
+
 /* Answer true if the receiver is deprecated (or any of its enclosing types)
 */
 
@@ -525,6 +705,26 @@
 public ReferenceBinding[] memberTypes() {
 	return NoMemberTypes;
 }
+
+/**
+ * Meant to be invoked on compatible types, to figure if unchecked conversion is necessary
+ */
+public boolean needsUncheckedConversion(TypeBinding targetType) {
+	if (this == targetType) return false;
+	if (!(targetType instanceof ReferenceBinding)) 
+		return false;
+	TypeBinding compatible = this.findSuperTypeErasingTo((ReferenceBinding)targetType.erasure());
+	if (compatible == null) 
+		return false;
+	if (!compatible.isPartOfRawType()) return false;
+	do {
+		if (compatible.isRawType() && (targetType.isBoundParameterizedType() || targetType.isGenericType())) {
+			return true;
+		}
+	} while ((compatible = compatible.enclosingType()) != null && (targetType = targetType.enclosingType()) != null);
+	return false;
+}
+
 public MethodBinding[] methods() {
 	return NoMethods;
 }
@@ -540,16 +740,50 @@
 	return sourceName();
 }
 
-public char[] readableName() /*java.lang.Object*/ {
-	if (isMemberType())
-		return CharOperation.concat(enclosingType().readableName(), sourceName, '.');
-	return CharOperation.concatWith(compoundName, '.');
+public char[] readableName() /*java.lang.Object,  p.X<T> */ {
+    char[] readableName;
+	if (isMemberType()) {
+		readableName = CharOperation.concat(enclosingType().readableName(), sourceName, '.');
+	} else {
+		readableName = CharOperation.concatWith(compoundName, '.');
+	}
+	TypeVariableBinding[] typeVars;
+	if ((typeVars = this.typeVariables()) != NoTypeVariables) {
+	    StringBuffer nameBuffer = new StringBuffer(10);
+	    nameBuffer.append(readableName).append('<');
+	    for (int i = 0, length = typeVars.length; i < length; i++) {
+	        if (i > 0) nameBuffer.append(',');
+	        nameBuffer.append(typeVars[i].readableName());
+	    }
+	    nameBuffer.append('>');
+		int nameLength = nameBuffer.length();
+		readableName = new char[nameLength];
+		nameBuffer.getChars(0, nameLength, readableName, 0);  
+	}
+	return readableName;
 }
 
 public char[] shortReadableName() /*Object*/ {
-	if (isMemberType())
-		return CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
-	return sourceName;
+    char[] shortReadableName;
+	if (isMemberType()) {
+		shortReadableName = CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
+	} else {
+		shortReadableName = this.sourceName;
+	}
+	TypeVariableBinding[] typeVars;
+	if ((typeVars = this.typeVariables()) != NoTypeVariables) {
+	    StringBuffer nameBuffer = new StringBuffer(10);
+	    nameBuffer.append(shortReadableName).append('<');
+	    for (int i = 0, length = typeVars.length; i < length; i++) {
+	        if (i > 0) nameBuffer.append(',');
+	        nameBuffer.append(typeVars[i].shortReadableName());
+	    }
+	    nameBuffer.append('>');
+		int nameLength = nameBuffer.length();
+		shortReadableName = new char[nameLength];
+		nameBuffer.getChars(0, nameLength, shortReadableName, 0);	    
+	}
+	return shortReadableName;
 }
 
 /* Answer the receiver's signature.
@@ -566,6 +800,7 @@
 public char[] sourceName() {
 	return sourceName;
 }
+
 public ReferenceBinding superclass() {
 	return null;
 }
@@ -583,6 +818,7 @@
 public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
 	return null;		// is null if no enclosing instances are required
 }
+
 MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types
 	return methods();
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index 335f9b1..9b0209f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -10,6 +10,11 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ast.*;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -20,22 +25,19 @@
 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
 
 public abstract class Scope
-	implements BaseTypes, BindingIds, CompilerModifiers, ProblemReasons, TagBits, TypeConstants, TypeIds {
+	implements BaseTypes, CompilerModifiers, ProblemReasons, TagBits, TypeConstants, TypeIds {
 
 	public final static int BLOCK_SCOPE = 1;
-	public final static int METHOD_SCOPE = 2;
 	public final static int CLASS_SCOPE = 3;
 	public final static int COMPILATION_UNIT_SCOPE = 4;
+	public final static int METHOD_SCOPE = 2;
 
-	public int kind;
-	public Scope parent;
+	public final static int NOT_COMPATIBLE = -1;
+	public final static int COMPATIBLE = 0;
+	public final static int AUTOBOX_COMPATIBLE = 1;
+	public final static int VARARGS_COMPATIBLE = 2;
 
-	protected Scope(int kind, Scope parent) {
-		this.kind = kind;
-		this.parent = 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
@@ -49,22 +51,128 @@
 		return NotRelated;
 	}
 
-	// Internal use only
-	protected final boolean areParametersAssignable(TypeBinding[] parameters, TypeBinding[] arguments) {
-		if (parameters == arguments)
-			return true;
-
-		int length = parameters.length;
-		if (length != arguments.length)
-			return false;
-
-		for (int i = 0; i < length; i++)
-			if (parameters[i] != arguments[i])
-				if (!arguments[i].isCompatibleWith(parameters[i]))
-					return false;
-		return true;
+	/**
+	 * Returns an array of types, where original types got substituted given a substitution.
+	 * Only allocate an array if anything is different.
+	 */
+	public static ReferenceBinding[] substitute(Substitution substitution, ReferenceBinding[] originalTypes) {
+	    ReferenceBinding[] substitutedTypes = originalTypes;
+	    for (int i = 0, length = originalTypes.length; i < length; i++) {
+	        ReferenceBinding originalType = originalTypes[i];
+	        ReferenceBinding substitutedParameter = (ReferenceBinding)substitution.substitute(originalType);
+	        if (substitutedParameter != originalType) {
+	            if (substitutedTypes == originalTypes) {
+	                System.arraycopy(originalTypes, 0, substitutedTypes = new ReferenceBinding[length], 0, i);
+	            }
+	            substitutedTypes[i] = substitutedParameter;
+	        } else if (substitutedTypes != originalTypes) {
+	            substitutedTypes[i] = originalType;
+	        }
+	    }
+	    return substitutedTypes;
 	}
-	
+
+	/**
+	 * Returns an array of types, where original types got substituted given a substitution.
+	 * Only allocate an array if anything is different.
+	 */
+	public static TypeBinding[] substitute(Substitution substitution, TypeBinding[] originalTypes) {
+	    TypeBinding[] substitutedTypes = originalTypes;
+	    for (int i = 0, length = originalTypes.length; i < length; i++) {
+	        TypeBinding originalType = originalTypes[i];
+	        TypeBinding substitutedParameter = substitution.substitute(originalType);
+	        if (substitutedParameter != originalType) {
+	            if (substitutedTypes == originalTypes) {
+	                System.arraycopy(originalTypes, 0, substitutedTypes = new TypeBinding[length], 0, i);
+	            }
+	            substitutedTypes[i] = substitutedParameter;
+	        } else if (substitutedTypes != originalTypes) {
+	            substitutedTypes[i] = originalType;
+	        }
+	    }
+	    return substitutedTypes;
+	}
+
+	public int kind;
+	public Scope parent;
+
+	protected Scope(int kind, Scope parent) {
+		this.kind = kind;
+		this.parent = parent;
+	}
+
+	/*
+	 * Boxing primitive
+	 */
+	public int boxing(int id) {
+		switch (id) {
+			case T_int :
+				return T_JavaLangInteger;
+			case T_byte :
+				return T_JavaLangByte;
+			case T_short :
+				return T_JavaLangShort;
+			case T_char :
+				return T_JavaLangCharacter;
+			case T_long :
+				return T_JavaLangLong;
+			case T_float :
+				return T_JavaLangFloat;
+			case T_double :
+				return T_JavaLangDouble;
+			case T_boolean :
+				return T_JavaLangBoolean;
+			case T_void :
+				return T_JavaLangVoid;
+		}
+		return id;
+	}
+	/*
+	 * Boxing primitive
+	 */
+	public TypeBinding boxing(TypeBinding type) {
+		TypeBinding boxedType;
+		switch (type.id) {
+			case T_int :
+				boxedType = environment().getType(JAVA_LANG_INTEGER);
+				if (boxedType != null) return boxedType;
+				return new ProblemReferenceBinding(	JAVA_LANG_INTEGER, NotFound);				
+			case T_byte :
+				boxedType = environment().getType(JAVA_LANG_BYTE);
+				if (boxedType != null) return boxedType;
+				return new ProblemReferenceBinding(	JAVA_LANG_BYTE, NotFound);				
+			case T_short :
+				boxedType = environment().getType(JAVA_LANG_SHORT);
+				if (boxedType != null) return boxedType;
+				return new ProblemReferenceBinding(	JAVA_LANG_SHORT, NotFound);				
+			case T_char :
+				boxedType = environment().getType(JAVA_LANG_CHARACTER);
+				if (boxedType != null) return boxedType;
+				return new ProblemReferenceBinding(	JAVA_LANG_CHARACTER, NotFound);				
+			case T_long :
+				boxedType = environment().getType(JAVA_LANG_LONG);
+				if (boxedType != null) return boxedType;
+				return new ProblemReferenceBinding(	JAVA_LANG_LONG, NotFound);				
+			case T_float :
+				boxedType = environment().getType(JAVA_LANG_FLOAT);
+				if (boxedType != null) return boxedType;
+				return new ProblemReferenceBinding(	JAVA_LANG_FLOAT, NotFound);				
+			case T_double :
+				boxedType = environment().getType(JAVA_LANG_DOUBLE);
+				if (boxedType != null) return boxedType;
+				return new ProblemReferenceBinding(	JAVA_LANG_DOUBLE, NotFound);				
+			case T_boolean :
+				boxedType = environment().getType(JAVA_LANG_BOOLEAN);
+				if (boxedType != null) return boxedType;
+				return new ProblemReferenceBinding(	JAVA_LANG_BOOLEAN, NotFound);				
+			case T_void :
+				boxedType = environment().getType(JAVA_LANG_VOID);
+				if (boxedType != null) return boxedType;
+				return new ProblemReferenceBinding(	JAVA_LANG_VOID, NotFound);				
+		}
+		return type;
+	}	
+
 	public final ClassScope classScope() {
 		Scope scope = this;
 		do {
@@ -97,16 +205,264 @@
 		return (CompilationUnitScope) lastScope;
 	}
 
-	public ArrayBinding createArray(TypeBinding type, int dimension) {
-		if (!type.isValidBinding())
-			return new ArrayBinding(type, dimension);
-		return environment().createArrayType(type, dimension);
+	/**
+	 * Internal use only
+	 * Given a method, returns null if arguments cannot be converted to parameters.
+	 * Will answer a subsituted method in case the method was generic and type inference got triggered;
+	 * in case the method was originally compatible, then simply answer it back.
+	 */
+	protected final MethodBinding computeCompatibleMethod(MethodBinding method, TypeBinding[] arguments, InvocationSite invocationSite) {
+
+		TypeBinding[] genericTypeArguments = invocationSite.genericTypeArguments();
+		TypeBinding[] parameters = method.parameters;
+		TypeVariableBinding[] typeVariables = method.typeVariables;
+		if (parameters == arguments
+			&& (method.returnType.tagBits & HasTypeVariable) == 0 
+			&& genericTypeArguments == null
+			&& typeVariables == NoTypeVariables)
+				return method;
+
+		int argLength = arguments.length;
+		int paramLength = parameters.length;
+		boolean isVarArgs = method.isVarargs();
+		if (argLength != paramLength)
+			if (!isVarArgs || argLength < paramLength - 1)
+				return null; // incompatible
+
+		if (typeVariables != NoTypeVariables) { // generic method
+			method = ParameterizedGenericMethodBinding.computeCompatibleMethod(method, arguments, this, invocationSite);
+			if (method == null) return null; // incompatible
+			if (!method.isValidBinding()) return method; // bound check issue is taking precedence
+			parameters = method.parameters; // reacquire them after type inference has performed
+		} else if (genericTypeArguments != null) {
+			if (method instanceof ParameterizedGenericMethodBinding) {
+				if (!((ParameterizedGenericMethodBinding) method).wasInferred) {
+					// attempt to invoke generic method of raw type with type hints <String>foo()
+					return new ProblemMethodBinding(method, method.selector, genericTypeArguments, TypeArgumentsForRawGenericMethod);
+				}
+			} else {
+				return new ProblemMethodBinding(method, method.selector, genericTypeArguments, TypeParameterArityMismatch);
+			}
+		}
+
+		if (parameterCompatibilityLevel(method, arguments) > NOT_COMPATIBLE)
+			return method;
+		if (genericTypeArguments != null)
+			return new ProblemMethodBinding(method, method.selector, arguments, ParameterizedMethodTypeMismatch);
+		return null; // incompatible
+	}
+	
+	protected boolean connectTypeVariables(TypeParameter[] typeParameters) {
+		boolean noProblems = true;
+		if (typeParameters == null || environment().options.sourceLevel < ClassFileConstants.JDK1_5) return true;
+
+		nextVariable : for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++) {
+			TypeParameter typeParameter = typeParameters[i];
+			TypeVariableBinding typeVariable = typeParameter.binding;
+			if (typeVariable == null) return false;
+
+			typeVariable.superclass = getJavaLangObject();
+			typeVariable.superInterfaces = NoSuperInterfaces;
+			// set firstBound to the binding of the first explicit bound in parameter declaration
+			typeVariable.firstBound = null; // first bound used to compute erasure
+
+			TypeReference typeRef = typeParameter.type;
+			if (typeRef == null)
+				continue nextVariable;
+			ReferenceBinding superType = this.kind == METHOD_SCOPE
+				? (ReferenceBinding) typeRef.resolveType((BlockScope)this, false/*no bound check*/)
+				: (ReferenceBinding) typeRef.resolveType((ClassScope)this);
+			if (superType == null) {
+				typeVariable.tagBits |= HierarchyHasProblems;
+				noProblems = false;
+				continue nextVariable;
+			}
+			if (superType.isTypeVariable()) {
+				TypeVariableBinding varSuperType = (TypeVariableBinding) superType;
+				if (varSuperType.rank >= typeVariable.rank && varSuperType.declaringElement == typeVariable.declaringElement) {
+					problemReporter().forwardTypeVariableReference(typeParameter, varSuperType);
+					typeVariable.tagBits |= HierarchyHasProblems;
+					noProblems = false;
+					continue nextVariable;
+				}
+			}
+			if (superType.isFinal())
+				problemReporter().finalVariableBound(typeVariable, typeRef);
+			typeRef.resolvedType = superType; // hold onto the problem type
+			if (superType.isClass()) {
+				typeVariable.superclass = superType;
+			} else {
+				typeVariable.superInterfaces = new ReferenceBinding[] {superType};
+				typeVariable.modifiers |= AccInterface;
+			}
+			typeVariable.firstBound = superType; // first bound used to compute erasure
+
+			TypeReference[] boundRefs = typeParameter.bounds;
+			if (boundRefs != null) {
+				for (int j = 0, k = boundRefs.length; j < k; j++) {
+					typeRef = boundRefs[j];
+					superType = this.kind == METHOD_SCOPE
+						? (ReferenceBinding) typeRef.resolveType((BlockScope)this, false)
+						: (ReferenceBinding) typeRef.resolveType((ClassScope)this);
+					if (superType == null) {
+						typeVariable.tagBits |= HierarchyHasProblems;
+						noProblems = false;
+						continue nextVariable;
+					}
+					typeRef.resolvedType = superType; // hold onto the problem type
+					if (superType.isClass()) {
+						problemReporter().boundsMustBeAnInterface(typeRef, superType);
+						typeVariable.tagBits |= HierarchyHasProblems;
+						noProblems = false;
+						continue nextVariable;
+					}
+					if (superType.isParameterizedType()) {
+						ReferenceBinding match = typeVariable.superclass.findSuperTypeErasingTo((ReferenceBinding) superType.erasure());
+						boolean isCollision = match != null && match != superType;
+						for (int index = typeVariable.superInterfaces.length; !isCollision && --index >= 0;) {
+							ReferenceBinding temp = typeVariable.superInterfaces[index];
+							isCollision = superType != temp && superType.erasure() == temp.erasure();
+						}
+						if (isCollision) {
+							problemReporter().boundHasConflictingArguments(typeRef, superType);
+							typeVariable.tagBits |= HierarchyHasProblems;
+							noProblems = false;
+							continue nextVariable;
+						}
+					}
+					int size = typeVariable.superInterfaces.length;
+					System.arraycopy(typeVariable.superInterfaces, 0, typeVariable.superInterfaces = new ReferenceBinding[size + 1], 0, size);
+					typeVariable.superInterfaces[size] = superType;
+				}
+			}
+		}
+		return noProblems;
+	}
+
+	public TypeBinding convertToRawType(TypeBinding type) {
+		int dimension = type.dimensions();
+		TypeBinding originalType = type.leafComponentType();
+		if (originalType instanceof ReferenceBinding) {
+			ReferenceBinding convertedType = (ReferenceBinding) originalType;
+			ReferenceBinding originalEnclosing = originalType.enclosingType();
+			ReferenceBinding convertedEnclosing = originalEnclosing;
+			if (originalEnclosing != null && convertedType.isStatic() && originalEnclosing.isGenericType()) {
+				convertedEnclosing = (ReferenceBinding) convertToRawType(originalEnclosing);
+			}
+			if (originalType.isGenericType()) {
+				convertedType = environment().createRawType(convertedType, convertedEnclosing);
+			} else if (originalEnclosing != convertedEnclosing) {
+				convertedType = createParameterizedType(convertedType, null, convertedEnclosing);
+			}
+			if (originalType != convertedType) {
+				return dimension > 0 ? (TypeBinding)createArrayType(convertedType, dimension) : convertedType;
+			}
+		}
+		return type;
+	}
+//		TypeBinding leafType = type.leafComponentType();
+//		int dimension = type.dimensions();
+//		ReferenceBinding originalEnclosing = leafType.enclosingType();
+//		ReferenceBinding convertedEnclosing = originalEnclosing;
+//		if (originalEnclosing != null && ((ReferenceBinding)leafType).isStatic()) {
+//			convertedEnclosing = (ReferenceBinding) convertToRawType(originalEnclosing);
+//		}
+//		if (leafType.isGenericType()) {
+//			type = environment().createRawType((ReferenceBinding) leafType, convertedEnclosing);
+//			if (dimension > 0) 
+//				type = createArrayType(type, dimension);
+//		} else if (originalEnclosing != convertedEnclosing) {
+//			type = createParameterizedType((ReferenceBinding)leafType, null, convertedEnclosing);
+//			if (dimension > 0) 
+//				type = createArrayType(type, dimension);
+//		}
+//	    return type;
+
+	public ArrayBinding createArrayType(TypeBinding type, int dimension) {
+		if (type.isValidBinding())
+			return environment().createArrayType(type, dimension);
+		// do not cache obvious invalid types
+		return new ArrayBinding(type, dimension, environment());
+	}
+	
+	public ParameterizedTypeBinding createParameterizedType(ReferenceBinding genericType, TypeBinding[] arguments, ReferenceBinding enclosingType) {
+		valid: {
+			if (!genericType.isValidBinding()) break valid;
+			for (int i = 0, max = arguments == null ? 0 : arguments.length; i < max; i++)
+				if (!arguments[i].isValidBinding()) break valid;
+			return environment().createParameterizedType(genericType, arguments, enclosingType);
+		}
+		return new ParameterizedTypeBinding(genericType, arguments, enclosingType, environment());
+	}
+	
+	public TypeVariableBinding[] createTypeVariables(TypeParameter[] typeParameters, Binding declaringElement) {
+
+		PackageBinding unitPackage = compilationUnitScope().fPackage;
+		
+		// do not construct type variables if source < 1.5
+		if (typeParameters == null || environment().options.sourceLevel < ClassFileConstants.JDK1_5)
+			return NoTypeVariables;
+		TypeVariableBinding[] typeVariableBindings = NoTypeVariables;
+		
+		int length = typeParameters.length;
+		typeVariableBindings = new TypeVariableBinding[length];
+		HashtableOfObject knownTypeParameterNames = new HashtableOfObject(length);
+		int count = 0;
+		nextParameter : for (int i = 0; i < length; i++) {
+			TypeParameter typeParameter = typeParameters[i];
+			TypeVariableBinding parameterBinding = new TypeVariableBinding(typeParameter.name, declaringElement, i);
+			parameterBinding.fPackage = unitPackage;
+			typeParameter.binding = parameterBinding;
+			
+			if (knownTypeParameterNames.containsKey(typeParameter.name)) {
+				TypeVariableBinding previousBinding = (TypeVariableBinding) knownTypeParameterNames.get(typeParameter.name);
+				if (previousBinding != null) {
+					for (int j = 0; j < i; j++) {
+						TypeParameter previousParameter = typeParameters[j];
+						if (previousParameter.binding == previousBinding) {
+							problemReporter().duplicateTypeParameterInType(previousParameter);
+							previousParameter.binding = null;
+							break;
+						}
+					}
+				}
+				knownTypeParameterNames.put(typeParameter.name, null); // ensure that the duplicate parameter is found & removed
+				problemReporter().duplicateTypeParameterInType(typeParameter);
+				typeParameter.binding = null;
+			} else {
+				knownTypeParameterNames.put(typeParameter.name, parameterBinding);
+				// remember that we have seen a field with this name
+				if (parameterBinding != null)
+					typeVariableBindings[count++] = parameterBinding;
+			}
+//				TODO should offer warnings to inform about hiding declaring, enclosing or member types				
+//				ReferenceBinding type = sourceType;
+//				// check that the member does not conflict with an enclosing type
+//				do {
+//					if (CharOperation.equals(type.sourceName, memberContext.name)) {
+//						problemReporter().hidingEnclosingType(memberContext);
+//						continue nextParameter;
+//					}
+//					type = type.enclosingType();
+//				} while (type != null);
+//				// check that the member type does not conflict with another sibling member type
+//				for (int j = 0; j < i; j++) {
+//					if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
+//						problemReporter().duplicateNestedType(memberContext);
+//						continue nextParameter;
+//					}
+//				}
+		}
+		if (count != length) {
+			System.arraycopy(typeVariableBindings, 0, typeVariableBindings = new TypeVariableBinding[count], 0, count);
+		}
+		return typeVariableBindings;
 	}
 
 	public final ClassScope enclosingClassScope() {
 		Scope scope = this;
 		while ((scope = scope.parent) != null) {
-			if (scope instanceof ClassScope) return (ClassScope)scope;
+			if (scope instanceof ClassScope) return (ClassScope) scope;
 		}
 		return null; // may answer null if no type around
 	}
@@ -114,7 +470,7 @@
 	public final MethodScope enclosingMethodScope() {
 		Scope scope = this;
 		while ((scope = scope.parent) != null) {
-			if (scope instanceof MethodScope) return (MethodScope)scope;
+			if (scope instanceof MethodScope) return (MethodScope) scope;
 		}
 		return null; // may answer null if no method around
 	}
@@ -137,28 +493,6 @@
 		return ((CompilationUnitScope) unitScope).environment;
 	}
 
-	protected void faultInReceiverType(TypeBinding type) {
-		if (type.isArrayType())
-			type = ((ArrayBinding) type).leafComponentType;
-
-        // check on Begin bit, so as to be resilient with potential illformed binaries containing cycles (67769)
-		if (type instanceof BinaryTypeBinding && (type.tagBits & BeginHierarchyCheck) == 0) {
-		    type.tagBits |= BeginHierarchyCheck;
-			// fault in the hierarchy of the type now so we can detect missing types instead of in storeDependencyInfo
-			BinaryTypeBinding binaryType = (BinaryTypeBinding) type;
-			ReferenceBinding enclosingType = binaryType.enclosingType();
-			if (enclosingType != null)
-				faultInReceiverType(enclosingType);
-			ReferenceBinding superclass = binaryType.superclass();
-			if (superclass != null)
-				faultInReceiverType(superclass);
-			ReferenceBinding[] interfaces = binaryType.superInterfaces();
-			for (int i = 0, l = interfaces.length; i < l; i++)
-				faultInReceiverType(interfaces[i]);
-			type.tagBits |= EndHierarchyCheck;
-		}
-	}
-
 	// abstract method lookup lookup (since maybe missing default abstract methods)
 	public MethodBinding findDefaultAbstractMethod(
 		ReferenceBinding receiverType, 
@@ -175,24 +509,34 @@
 			matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
 			currentType = currentType.superclass();
 		}
+		CompilationUnitScope unitScope = compilationUnitScope();
 		int foundSize = found.size;
 		if (foundSize == startFoundSize) {
-			if (matchingMethod != null) compilationUnitScope().recordTypeReferences(matchingMethod.thrownExceptions);
+			if (matchingMethod != null)
+				unitScope.recordTypeReferences(matchingMethod.thrownExceptions);
 			return matchingMethod; // maybe null
 		}
 		MethodBinding[] candidates = new MethodBinding[foundSize - startFoundSize];
 		int candidatesCount = 0;
+		MethodBinding problemMethod = null;
 		// argument type compatibility check
 		for (int i = startFoundSize; i < foundSize; i++) {
 			MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
-			if (areParametersAssignable(methodBinding.parameters, argumentTypes))
-				candidates[candidatesCount++] = methodBinding;
+			MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
+			if (compatibleMethod != null) {
+				if (compatibleMethod.isValidBinding())
+					candidates[candidatesCount++] = compatibleMethod;
+				else if (problemMethod == null)
+					problemMethod = compatibleMethod;
+			}
 		}
+
 		if (candidatesCount == 1) {
-			compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
+			unitScope.recordTypeReferences(candidates[0].thrownExceptions);
 			return candidates[0]; 
 		}
 		if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
+			if (problemMethod != null) return problemMethod;
 			int argLength = argumentTypes.length;
 			nextMethod : for (int i = 0; i < foundSize; i++) {
 				MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
@@ -210,7 +554,10 @@
 			return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
 		}
 		// no need to check for visibility - interface methods are public
-		return mostSpecificInterfaceMethodBinding(candidates, candidatesCount);
+		boolean isCompliant14 = unitScope.environment.options.complianceLevel >= ClassFileConstants.JDK1_4;
+		if (isCompliant14)
+			return mostSpecificMethodBinding(candidates, candidatesCount, argumentTypes, invocationSite);
+		return mostSpecificInterfaceMethodBinding(candidates, candidatesCount, invocationSite);
 	}
 
 	// Internal use only
@@ -219,14 +566,15 @@
 			return null; // know it has no member types (nor inherited member types)
 
 		SourceTypeBinding enclosingSourceType = enclosingSourceType();
-		compilationUnitScope().recordReference(enclosingType.compoundName, typeName);
+		CompilationUnitScope unitScope = compilationUnitScope();
+		unitScope.recordReference(enclosingType, typeName);
 		ReferenceBinding memberType = enclosingType.getMemberType(typeName);
 		if (memberType != null) {
-			compilationUnitScope().recordTypeReference(memberType); // to record supertypes
+			unitScope.recordTypeReference(memberType);
 			if (enclosingSourceType == null
-					? memberType.canBeSeenBy(getCurrentPackage())
-					: memberType.canBeSeenBy(enclosingType, enclosingSourceType))
-				return memberType;
+				? memberType.canBeSeenBy(getCurrentPackage())
+				: memberType.canBeSeenBy(enclosingType, enclosingSourceType))
+					return memberType;
 			return new ProblemReferenceBinding(typeName, memberType, NotVisible);
 		}
 		return null;
@@ -239,14 +587,24 @@
 		TypeBinding[] argumentTypes,
 		InvocationSite invocationSite) {
 
-		faultInReceiverType(receiverType);
-		compilationUnitScope().recordTypeReference(receiverType);
-		compilationUnitScope().recordTypeReferences(argumentTypes);
-		MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes);
+		CompilationUnitScope unitScope = compilationUnitScope();
+		unitScope.recordTypeReferences(argumentTypes);
+		MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes, unitScope);
 		if (exactMethod != null) {
-			compilationUnitScope().recordTypeReferences(exactMethod.thrownExceptions);
-			if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this))
+			unitScope.recordTypeReferences(exactMethod.thrownExceptions);
+			// special treatment for Object.getClass() in 1.5 mode (substitute parameterized return type)
+			if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this)) {
+				if (receiverType.id != T_JavaLangObject
+					&& argumentTypes == NoParameters
+				    && CharOperation.equals(selector, GETCLASS)
+				    && exactMethod.returnType.isParameterizedType()/*1.5*/) {
+						return ParameterizedMethodBinding.instantiateGetClass(receiverType, exactMethod, this);
+			    }
+				// targeting a generic method could find an exact match with variable return type
+				if (exactMethod.typeVariables != NoTypeVariables || invocationSite.genericTypeArguments() != null)
+					exactMethod = computeCompatibleMethod(exactMethod, argumentTypes, invocationSite);
 				return exactMethod;
+			}
 		}
 		return null;
 	}
@@ -263,28 +621,29 @@
 	*/
 	public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite, boolean needResolve) {
 		if (receiverType.isBaseType()) return null;
+
+		CompilationUnitScope unitScope = compilationUnitScope();
+		unitScope.recordTypeReference(receiverType);
 		if (receiverType.isArrayType()) {
 			TypeBinding leafType = receiverType.leafComponentType();
-			if (leafType instanceof ReferenceBinding) {
+			if (leafType instanceof ReferenceBinding)
 				if (!((ReferenceBinding) leafType).canBeSeenBy(this))
 					return new ProblemFieldBinding((ReferenceBinding)leafType, fieldName, ReceiverTypeNotVisible);
-			}
 			if (CharOperation.equals(fieldName, LENGTH))
 				return ArrayBinding.ArrayLength;
 			return null;
 		}
 
-		faultInReceiverType(receiverType);
-		compilationUnitScope().recordTypeReference(receiverType);
-
 		ReferenceBinding currentType = (ReferenceBinding) receiverType;
 		if (!currentType.canBeSeenBy(this))
 			return new ProblemFieldBinding(currentType, fieldName, ReceiverTypeNotVisible);
 
 		FieldBinding field = currentType.getField(fieldName, true /*resolve*/);
 		if (field != null) {
-			if (field.canBeSeenBy(currentType, invocationSite, this))
-				return field;
+			if (invocationSite == null
+				? field.canBeSeenBy(getCurrentPackage())
+				: field.canBeSeenBy(currentType, invocationSite, this))
+					return field;
 			return new ProblemFieldBinding(field /* closest match*/, field.declaringClass, fieldName, NotVisible);
 		}
 		// collect all superinterfaces of receiverType until the field is found in a supertype
@@ -296,21 +655,21 @@
 		// we could hold onto the not visible field for extra error reporting
 		while (keepLooking) {
 			ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+			if (itsInterfaces == null) { // needed for statically imported types which don't know their hierarchy yet
+				((SourceTypeBinding) currentType).scope.connectTypeHierarchy();
+				itsInterfaces = currentType.superInterfaces();
+			}
 			if (itsInterfaces != NoSuperInterfaces) {
 				if (interfacesToVisit == null)
 					interfacesToVisit = new ReferenceBinding[5][];
 				if (++lastPosition == interfacesToVisit.length)
-					System.arraycopy(
-						interfacesToVisit,
-						0,
-						interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
-						0,
-						lastPosition);
+					System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
 				interfacesToVisit[lastPosition] = itsInterfaces;
 			}
 			if ((currentType = currentType.superclass()) == null)
 				break;
 
+			unitScope.recordTypeReference(currentType);
 			if ((field = currentType.getField(fieldName, needResolve)) != null) {
 				keepLooking = false;
 				if (field.canBeSeenBy(receiverType, invocationSite, this)) {
@@ -334,6 +693,7 @@
 					if ((anInterface.tagBits & InterfaceVisited) == 0) {
 						// if interface as not already been visited
 						anInterface.tagBits |= InterfaceVisited;
+						unitScope.recordTypeReference(anInterface);
 						if ((field = anInterface.getField(fieldName, true /*resolve*/)) != null) {
 							if (visibleField == null) {
 								visibleField = field;
@@ -345,12 +705,7 @@
 							ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
 							if (itsInterfaces != NoSuperInterfaces) {
 								if (++lastPosition == interfacesToVisit.length)
-									System.arraycopy(
-										interfacesToVisit,
-										0,
-										interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
-										0,
-										lastPosition);
+									System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
 								interfacesToVisit[lastPosition] = itsInterfaces;
 							}
 						}
@@ -382,14 +737,15 @@
 
 		SourceTypeBinding enclosingSourceType = enclosingSourceType();
 		PackageBinding currentPackage = getCurrentPackage();
-		compilationUnitScope().recordReference(enclosingType.compoundName, typeName);
+		CompilationUnitScope unitScope = compilationUnitScope();
+		unitScope.recordReference(enclosingType, typeName);
 		ReferenceBinding memberType = enclosingType.getMemberType(typeName);
 		if (memberType != null) {
-			compilationUnitScope().recordTypeReference(memberType); // to record supertypes
+			unitScope.recordTypeReference(memberType);
 			if (enclosingSourceType == null
-					? memberType.canBeSeenBy(currentPackage)
-					: memberType.canBeSeenBy(enclosingType, enclosingSourceType))
-				return memberType;
+				? memberType.canBeSeenBy(currentPackage)
+				: memberType.canBeSeenBy(enclosingType, enclosingSourceType))
+					return memberType;
 			return new ProblemReferenceBinding(typeName, memberType, NotVisible);
 		}
 
@@ -403,24 +759,23 @@
 		// we could hold onto the not visible field for extra error reporting
 		while (keepLooking) {
 			ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+			if (itsInterfaces == null) { // needed for statically imported types which don't know their hierarchy yet
+				((SourceTypeBinding) currentType).scope.connectTypeHierarchy();
+				itsInterfaces = currentType.superInterfaces();
+			}
 			if (itsInterfaces != NoSuperInterfaces) {
 				if (interfacesToVisit == null)
 					interfacesToVisit = new ReferenceBinding[5][];
 				if (++lastPosition == interfacesToVisit.length)
-					System.arraycopy(
-						interfacesToVisit,
-						0,
-						interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
-						0,
-						lastPosition);
+					System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
 				interfacesToVisit[lastPosition] = itsInterfaces;
 			}
 			if ((currentType = currentType.superclass()) == null)
 				break;
 
-			compilationUnitScope().recordReference(currentType.compoundName, typeName);
+			unitScope.recordReference(currentType, typeName);
 			if ((memberType = currentType.getMemberType(typeName)) != null) {
-				compilationUnitScope().recordTypeReference(memberType); // to record supertypes
+				unitScope.recordTypeReference(memberType);
 				keepLooking = false;
 				if (enclosingSourceType == null
 					? memberType.canBeSeenBy(currentPackage)
@@ -444,9 +799,9 @@
 					if ((anInterface.tagBits & InterfaceVisited) == 0) {
 						// if interface as not already been visited
 						anInterface.tagBits |= InterfaceVisited;
-						compilationUnitScope().recordReference(anInterface.compoundName, typeName);
+						unitScope.recordReference(anInterface, typeName);
 						if ((memberType = anInterface.getMemberType(typeName)) != null) {
-							compilationUnitScope().recordTypeReference(memberType); // to record supertypes
+							unitScope.recordTypeReference(memberType);
 							if (visibleMemberType == null) {
 								visibleMemberType = memberType;
 							} else {
@@ -457,12 +812,7 @@
 							ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
 							if (itsInterfaces != NoSuperInterfaces) {
 								if (++lastPosition == interfacesToVisit.length)
-									System.arraycopy(
-										interfacesToVisit,
-										0,
-										interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
-										0,
-										lastPosition);
+									System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
 								interfacesToVisit[lastPosition] = itsInterfaces;
 							}
 						}
@@ -495,13 +845,13 @@
 
 		ReferenceBinding currentType = receiverType;
 		MethodBinding matchingMethod = null;
-		ObjectVector found = new ObjectVector(); //TODO should rewrite to remove #matchingMethod since found is allocated anyway
+		ObjectVector found = new ObjectVector(); //TODO (kent) should rewrite to remove #matchingMethod since found is allocated anyway
 
-		faultInReceiverType(receiverType);
-		compilationUnitScope().recordTypeReference(receiverType);
-		compilationUnitScope().recordTypeReferences(argumentTypes);
+		CompilationUnitScope unitScope = compilationUnitScope();
+		unitScope.recordTypeReferences(argumentTypes);
 
 		if (currentType.isInterface()) {
+			unitScope.recordTypeReference(currentType);
 			MethodBinding[] currentMethods = currentType.getMethods(selector);
 			int currentLength = currentMethods.length;
 			if (currentLength == 1) {
@@ -513,31 +863,31 @@
 			currentType = getJavaLangObject();
 		}
 
-		boolean isCompliant14 = compilationUnitScope().environment.options.complianceLevel >= ClassFileConstants.JDK1_4;
+		boolean isCompliant14 = unitScope.environment.options.complianceLevel >= ClassFileConstants.JDK1_4;
 		// superclass lookup
 		ReferenceBinding classHierarchyStart = currentType;
 		while (currentType != null) {
+			unitScope.recordTypeReference(currentType);
 			MethodBinding[] currentMethods = currentType.getMethods(selector);
 			int currentLength = currentMethods.length;
-			
-			/*
-			 * if 1.4 compliant, must filter out redundant protected methods from superclasses
-			 */
-			if (isCompliant14){			 
-				nextMethod: for (int i = 0; i < currentLength; i++){
+
+			if (isCompliant14 && matchingMethod != null || found.size > 0) {
+				nextMethod: for (int i = 0; i < currentLength; i++) {
 					MethodBinding currentMethod = currentMethods[i];
+					// if 1.4 compliant, must filter out redundant protected methods from superclasses
 					// protected method need to be checked only - default access is already dealt with in #canBeSeen implementation
 					// when checking that p.C -> q.B -> p.A cannot see default access members from A through B.
-					if ((currentMethod.modifiers & AccProtected) == 0) continue nextMethod;
-					if (matchingMethod != null){
-						if (currentMethod.areParametersEqual(matchingMethod)){
+					// if ((currentMethod.modifiers & AccProtected) == 0) continue nextMethod;
+					// BUT we can also ignore any overridden method since we already know the better match (fixes 80028)
+					if (matchingMethod != null) {
+						if (currentMethod.areParametersEqual(matchingMethod)) {
 							currentLength--;
 							currentMethods[i] = null; // discard this match
 							continue nextMethod;
 						}
 					} else {
 						for (int j = 0, max = found.size; j < max; j++) {
-							if (((MethodBinding)found.elementAt(j)).areParametersEqual(currentMethod)){
+							if (((MethodBinding) found.elementAt(j)).areParametersEqual(currentMethod)) {
 								currentLength--;
 								currentMethods[i] = null;
 								continue nextMethod;
@@ -546,7 +896,7 @@
 					}
 				}
 			}
-			
+
 			if (currentLength == 1 && matchingMethod == null && found.size == 0) {
 				matchingMethod = currentMethods[0];
 			} else if (currentLength > 0) {
@@ -573,41 +923,65 @@
 		MethodBinding[] candidates = null;
 		int candidatesCount = 0;
 		boolean checkedMatchingMethod = false; // is matchingMethod meeting argument expectation ?
+		MethodBinding problemMethod = null;
 		if (foundSize > 0) {
 			// argument type compatibility check
 			for (int i = 0; i < foundSize; i++) {
 				MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
-				if (areParametersAssignable(methodBinding.parameters, argumentTypes)) {
-					switch (candidatesCount) {
-						case 0: 
-							matchingMethod = methodBinding; // if only one match, reuse matchingMethod
-							checkedMatchingMethod = true; // matchingMethod is known to exist and match params here
-							break;
-						case 1:
-							candidates = new MethodBinding[foundSize]; // only lazily created if more than one match
-							candidates[0] = matchingMethod; // copy back
-							matchingMethod = null;
-							// fall through
-						default:
-							candidates[candidatesCount] = methodBinding;
+				MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
+				if (compatibleMethod != null) {
+					if (compatibleMethod.isValidBinding()) {
+						switch (candidatesCount) {
+							case 0: 
+								matchingMethod = compatibleMethod; // if only one match, reuse matchingMethod
+								checkedMatchingMethod = true; // matchingMethod is known to exist and match params here
+								break;
+							case 1:
+								candidates = new MethodBinding[foundSize]; // only lazily created if more than one match
+								candidates[0] = matchingMethod; // copy back
+								matchingMethod = null;
+								// fall through
+							default:
+								candidates[candidatesCount] = compatibleMethod;
+						}
+						candidatesCount++;
+					} else if (problemMethod == null) {
+						problemMethod = compatibleMethod;
 					}
-					candidatesCount++;
 				}
 			}
 		}
+		if (candidatesCount > 0)
+			problemMethod = null; // forget the problem method if candidates were found
+
 		// if only one matching method left (either from start or due to elimination of rivals), then match is in matchingMethod
 		if (matchingMethod != null) {
-			if (checkedMatchingMethod || areParametersAssignable(matchingMethod.parameters, argumentTypes)) {
+			if (!checkedMatchingMethod) {
+				MethodBinding compatibleMethod = computeCompatibleMethod(matchingMethod, argumentTypes, invocationSite);
+				if (compatibleMethod != null) {
+					if (compatibleMethod.isValidBinding()) {
+						matchingMethod = compatibleMethod;
+						checkedMatchingMethod = true;
+					} else {
+						problemMethod = compatibleMethod;
+					}
+				}
+			}
+			if (checkedMatchingMethod) {
 				// (if no default abstract) must explicitly look for one instead, which could be a better match
 				if (!matchingMethod.canBeSeenBy(receiverType, invocationSite, this)) {
 					// ignore matching method (to be consistent with multiple matches, none visible (matching method is then null)
-					MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, null, found);						
+					MethodBinding interfaceMethod =
+						findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, null, found);						
 					if (interfaceMethod != null) return interfaceMethod;
-					compilationUnitScope().recordTypeReferences(matchingMethod.thrownExceptions);
+					unitScope.recordTypeReferences(matchingMethod.thrownExceptions);
 					return matchingMethod;
 				}
 			} 
-			return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
+			matchingMethod =
+				findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
+			if (matchingMethod != null) return matchingMethod;
+			return problemMethod;
 		}
 
 		// no match was found, try to find a close match when the parameter order is wrong or missing some parameters
@@ -615,6 +989,7 @@
 			MethodBinding interfaceMethod =
 				findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
 			if (interfaceMethod != null) return interfaceMethod;
+			if (problemMethod != null) return problemMethod;
 
 			int argLength = argumentTypes.length;
 			foundSize = found.size;
@@ -631,9 +1006,23 @@
 				}
 				return methodBinding;
 			}
+			if (found.size == 0) return null;
 			return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
 		}
 
+		// check for duplicate parameterized methods
+		if (unitScope.environment.options.sourceLevel >= ClassFileConstants.JDK1_5) {
+			for (int i = 0; i < candidatesCount; i++) {
+				MethodBinding current = candidates[i];
+				if (current instanceof ParameterizedGenericMethodBinding)
+					current = ((ParameterizedGenericMethodBinding) current).originalMethod;
+				if (current instanceof ParameterizedMethodBinding)
+					for (int j = i + 1; j < candidatesCount; j++)
+						if (current.declaringClass == candidates[j].declaringClass && current.areParametersEqual(candidates[j]))
+							return new ProblemMethodBinding(candidates[i].selector, candidates[i].parameters, Ambiguous);
+			}
+		}
+
 		// tiebreak using visibility check
 		int visiblesCount = 0;
 		for (int i = 0; i < candidatesCount; i++) {
@@ -647,7 +1036,7 @@
 			}
 		}
 		if (visiblesCount == 1) {
-			compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
+			unitScope.recordTypeReferences(candidates[0].thrownExceptions);
 			return candidates[0];
 		}
 		if (visiblesCount == 0) {
@@ -657,10 +1046,10 @@
 			return new ProblemMethodBinding(candidates[0], candidates[0].selector, candidates[0].parameters, NotVisible);
 		}
 		if (isCompliant14)
-			return mostSpecificMethodBinding(candidates, visiblesCount);
+			return mostSpecificMethodBinding(candidates, visiblesCount, argumentTypes, invocationSite);
 		return candidates[0].declaringClass.isClass()
-			? mostSpecificClassMethodBinding(candidates, visiblesCount)
-			: mostSpecificInterfaceMethodBinding(candidates, visiblesCount);
+			? mostSpecificClassMethodBinding(candidates, visiblesCount, invocationSite)
+			: mostSpecificInterfaceMethodBinding(candidates, visiblesCount, invocationSite);
 	}
 	
 	// Internal use only
@@ -680,15 +1069,27 @@
 		MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes);
 		if (methodBinding != null) {
 			// handle the method clone() specially... cannot be protected or throw exceptions
-			if (argumentTypes == NoParameters && CharOperation.equals(selector, CLONE))
-				return new UpdatedMethodBinding(
-					environment().options.targetJDK >= ClassFileConstants.JDK1_4 ? (TypeBinding)receiverType : (TypeBinding)object, // remember its array type for codegen purpose on target>=1.4.0
-					(methodBinding.modifiers ^ AccProtected) | AccPublic,
-					CLONE,
-					methodBinding.returnType,
-					argumentTypes,
-					null,
-					object);
+			if (argumentTypes == NoParameters) {
+			    switch (selector[0]) {
+			        case 'c': 
+			            if (CharOperation.equals(selector, CLONE)) {
+							return new UpdatedMethodBinding(
+								environment().options.targetJDK >= ClassFileConstants.JDK1_4 ? (TypeBinding)receiverType : (TypeBinding)object, // remember its array type for codegen purpose on target>=1.4.0
+								(methodBinding.modifiers & ~AccProtected) | AccPublic,
+								CLONE,
+								methodBinding.returnType,
+								argumentTypes,
+								null,
+								object);
+			            }
+			            break;
+			        case 'g': 
+			            if (CharOperation.equals(selector, GETCLASS) && methodBinding.returnType.isParameterizedType()/*1.5*/) {
+							return ParameterizedMethodBinding.instantiateGetClass(receiverType, methodBinding, this);
+			            }
+			            break;
+			    }
+			}
 			if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
 				return methodBinding;
 		}
@@ -697,18 +1098,15 @@
 		if (methodBinding == null)
 			return new ProblemMethodBinding(selector, argumentTypes, NotFound);
 		if (methodBinding.isValidBinding()) {
-			if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
-				return new ProblemMethodBinding(
-					methodBinding,
-					selector,
-					argumentTypes,
-					NotFound);
+			MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
+			if (compatibleMethod == null)
+				return new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotFound);
+			if (!compatibleMethod.isValidBinding())
+				return compatibleMethod;
+
+			methodBinding = compatibleMethod;
 			if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this))
-				return new ProblemMethodBinding(
-					methodBinding,
-					selector,
-					methodBinding.parameters,
-					NotVisible);
+				return new ProblemMethodBinding(methodBinding, selector, methodBinding.parameters, NotVisible);
 		}
 		return methodBinding;
 	}
@@ -738,6 +1136,7 @@
 						// if interface as not already been visited
 						currentType.tagBits |= InterfaceVisited;
 
+						compilationUnitScope().recordTypeReference(currentType);
 						MethodBinding[] currentMethods = currentType.getMethods(selector);
 						int currentLength = currentMethods.length;
 						if (currentLength == 1 && matchingMethod == null && found.size == 0) {
@@ -795,7 +1194,7 @@
 		return null;
 	}
 	
-	public TypeBinding getBaseType(char[] name) {
+	public static TypeBinding getBaseType(char[] name) {
 		// list should be optimized (with most often used first)
 		int length = name.length;
 		if (length > 2 && length < 8) {
@@ -858,7 +1257,7 @@
 	}
 
 	/* API
-     *	
+	 *	
 	 *	Answer the binding that corresponds to the argument name.
 	 *	flag is a mask of the following values VARIABLE (= FIELD or LOCAL), TYPE, PACKAGE.
 	 *	Only bindings corresponding to the mask can be answered.
@@ -881,10 +1280,10 @@
 		try {
 			Binding binding = null;
 			FieldBinding problemField = null;
-			if ((mask & VARIABLE) != 0) {
+			if ((mask & Binding.VARIABLE) != 0) {
 				boolean insideStaticContext = false;
 				boolean insideConstructorCall = false;
-	
+
 				FieldBinding foundField = null;
 				// can be a problem field which is answered if a valid field is not found
 				ProblemFieldBinding foundInsideProblem = null;
@@ -918,10 +1317,25 @@
 						case CLASS_SCOPE :
 							ClassScope classScope = (ClassScope) scope;
 							SourceTypeBinding enclosingType = classScope.referenceContext.binding;
-							FieldBinding fieldBinding =
-								classScope.findField(enclosingType, name, invocationSite, needResolve);
+							FieldBinding fieldBinding = classScope.findField(enclosingType, name, invocationSite, needResolve);
 							// Use next line instead if willing to enable protected access accross inner types
 							// FieldBinding fieldBinding = findField(enclosingType, name, invocationSite);
+							
+//							SourceTypeBinding initialType = this.enclosingSourceType();
+//							if ((fieldBinding == null || !fieldBinding.isValidBinding()) && enclosingType.hasMemberTypes()) { // check member enums
+//								ReferenceBinding[] memberTypes = enclosingType.memberTypes();
+//								for (int i = 0, length = memberTypes.length; i < length; i++) {
+//									ReferenceBinding memberType = memberTypes[i];
+//									if (memberType != initialType && memberType.isEnum()) { // do not find one's field through its enclosing members
+//										FieldBinding enumField = ((SourceTypeBinding)memberType).scope.findField(memberType, name, invocationSite, needResolve);
+//										if (enumField != null && (enumField.modifiers & AccEnum) != 0) {
+//											// grant access to enum constants of enclosing members
+//											// TODO (kent) need to revisit to see whether should walk sibling enums and issue an ambiguous match
+//											return enumField;
+//										}
+//									}
+//								}
+//							}
 							if (fieldBinding != null) { // skip it if we did not find anything
 								if (fieldBinding.problemId() == Ambiguous) {
 									if (foundField == null || foundField.problemId() == NotVisible)
@@ -934,7 +1348,7 @@
 										name,
 										InheritedNameHidesEnclosingName);
 								}
-	
+
 								ProblemFieldBinding insideProblem = null;
 								if (fieldBinding.isValidBinding()) {
 									if (!fieldBinding.isStatic()) {
@@ -954,8 +1368,7 @@
 													NonStaticReferenceInStaticContext);
 										}
 									}
-									if (enclosingType == fieldBinding.declaringClass
-										|| environment().options.complianceLevel >= ClassFileConstants.JDK1_4){
+									if (enclosingType == fieldBinding.declaringClass || environment().options.complianceLevel >= ClassFileConstants.JDK1_4) {
 										// found a valid field in the 'immediate' scope (ie. not inherited)
 										// OR in 1.4 mode (inherited shadows enclosing)
 										if (foundField == null) {
@@ -977,10 +1390,8 @@
 													InheritedNameHidesEnclosingName);
 									}
 								}
-	
-								if (foundField == null
-									|| (foundField.problemId() == NotVisible
-										&& fieldBinding.problemId() != NotVisible)) {
+
+								if (foundField == null || (foundField.problemId() == NotVisible && fieldBinding.problemId() != NotVisible)) {
 									// only remember the fieldBinding if its the first one found or the previous one was not visible & fieldBinding is...
 									foundDepth = depth;
 									foundActualReceiverType = enclosingType;
@@ -1002,12 +1413,12 @@
 					}
 					scope = scope.parent;
 				}
-	
+
 				if (foundInsideProblem != null)
 					return foundInsideProblem;
 				if (foundField != null) {
-					if (foundField.isValidBinding()){
-						if (foundDepth > 0){
+					if (foundField.isValidBinding()) {
+						if (foundDepth > 0) {
 							invocationSite.setDepth(foundDepth);
 							invocationSite.setActualReceiverType(foundActualReceiverType);
 						}
@@ -1015,24 +1426,69 @@
 					}
 					problemField = foundField;
 				}
+
+				if (environment().options.complianceLevel >= ClassFileConstants.JDK1_5) {
+					// at this point the scope is a compilation unit scope & need to check for imported static fields
+					CompilationUnitScope unitScope = (CompilationUnitScope) scope;
+					ImportBinding[] imports = unitScope.imports;
+					if (imports != null) {
+						// check single static imports
+						for (int i = 0, length = imports.length; i < length; i++) {
+							ImportBinding importBinding = imports[i];
+							if (importBinding.isStatic() && !importBinding.onDemand) {
+								if (CharOperation.equals(importBinding.compoundName[importBinding.compoundName.length - 1], name)) {
+									if (unitScope.resolveSingleImport(importBinding) != null && importBinding.resolvedImport instanceof FieldBinding) {
+										ImportReference importReference = importBinding.reference;
+										if (importReference != null) importReference.used = true;
+										return importBinding.resolvedImport; // already know its visible
+									}
+								}
+							}
+						}
+						// check on demand imports
+						boolean foundInImport = false;
+						for (int i = 0, length = imports.length; i < length; i++) {
+							ImportBinding importBinding = imports[i];
+							if (importBinding.isStatic() && importBinding.onDemand) {
+								Binding resolvedImport = importBinding.resolvedImport;
+								if (resolvedImport instanceof ReferenceBinding) {
+									FieldBinding temp = findField((ReferenceBinding) resolvedImport, name, invocationSite, needResolve);
+									if (temp != null) {
+										if (!temp.isValidBinding()) {
+											problemField = temp;
+										} else if (temp.isStatic()) {
+											ImportReference importReference = importBinding.reference;
+											if (importReference != null) importReference.used = true;
+											if (foundInImport)
+												// Answer error binding -- import on demand conflict; name found in two import on demand packages.
+												return new ProblemReferenceBinding(name, Ambiguous);
+											foundField = temp;
+											foundInImport = true;
+										}
+									}
+								}
+							}
+						}
+						if (foundField != null) return foundField;
+					}
+				}
 			}
-	
+
 			// We did not find a local or instance variable.
-			if ((mask & TYPE) != 0) {
+			if ((mask & Binding.TYPE) != 0) {
 				if ((binding = getBaseType(name)) != null)
 					return binding;
-				binding = getTypeOrPackage(name, (mask & PACKAGE) == 0 ? TYPE : TYPE | PACKAGE);
-				if (binding.isValidBinding() || mask == TYPE)
+				binding = getTypeOrPackage(name, (mask & Binding.PACKAGE) == 0 ? Binding.TYPE : Binding.TYPE | Binding.PACKAGE);
+				if (binding.isValidBinding() || mask == Binding.TYPE)
 					return binding;
 				// answer the problem type binding if we are only looking for a type
-			} else if ((mask & PACKAGE) != 0) {
+			} else if ((mask & Binding.PACKAGE) != 0) {
 				compilationUnitScope().recordSimpleReference(name);
 				if ((binding = environment().getTopLevelPackage(name)) != null)
 					return binding;
 			}
 			if (problemField != null) return problemField;
 			return new ProblemBinding(name, enclosingSourceType(), NotFound);
-
 		} catch (AbortCompilation e) {
 			e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
 			throw e;
@@ -1041,29 +1497,40 @@
 
 	public MethodBinding getConstructor(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
 		try {
-			faultInReceiverType(receiverType);
-			compilationUnitScope().recordTypeReference(receiverType);
-			compilationUnitScope().recordTypeReferences(argumentTypes);
+			CompilationUnitScope unitScope = compilationUnitScope();
+			unitScope.recordTypeReference(receiverType);
+			unitScope.recordTypeReferences(argumentTypes);
 			MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes);
-			if (methodBinding != null && methodBinding.canBeSeenBy(invocationSite, this))
+			if (methodBinding != null && methodBinding.canBeSeenBy(invocationSite, this)) {
+			    // targeting a non generic constructor with type arguments ?
+			    if (invocationSite.genericTypeArguments() != null)
+			    	methodBinding = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);				
 				return methodBinding;
-			MethodBinding[] methods = receiverType.getMethods(ConstructorDeclaration.ConstantPoolName);
+			}
+			MethodBinding[] methods = receiverType.getMethods(TypeConstants.INIT);
 			if (methods == NoMethods)
 				return new ProblemMethodBinding(
-					ConstructorDeclaration.ConstantPoolName,
+					TypeConstants.INIT,
 					argumentTypes,
 					NotFound);
-	
+
 			MethodBinding[] compatible = new MethodBinding[methods.length];
 			int compatibleIndex = 0;
-			for (int i = 0, length = methods.length; i < length; i++)
-				if (areParametersAssignable(methods[i].parameters, argumentTypes))
-					compatible[compatibleIndex++] = methods[i];
-			if (compatibleIndex == 0)
-				return new ProblemMethodBinding(
-					ConstructorDeclaration.ConstantPoolName,
-					argumentTypes,
-					NotFound);
+			MethodBinding problemMethod = null;
+			for (int i = 0, length = methods.length; i < length; i++) {
+				MethodBinding compatibleMethod = computeCompatibleMethod(methods[i], argumentTypes, invocationSite);
+				if (compatibleMethod != null) {
+					if (compatibleMethod.isValidBinding())
+						compatible[compatibleIndex++] = compatibleMethod;
+					else if (problemMethod == null)
+						problemMethod = compatibleMethod;
+				}
+			}
+			if (compatibleIndex == 0) {
+				if (problemMethod == null)
+					return new ProblemMethodBinding(TypeConstants.INIT, argumentTypes, NotFound);
+				return problemMethod;
+			}
 			// need a more descriptive error... cannot convert from X to Y
 	
 			MethodBinding[] visible = new MethodBinding[compatibleIndex];
@@ -1077,10 +1544,11 @@
 			if (visibleIndex == 0)
 				return new ProblemMethodBinding(
 					compatible[0],
-					ConstructorDeclaration.ConstantPoolName,
+					TypeConstants.INIT,
 					compatible[0].parameters,
 					NotVisible);
-			return mostSpecificClassMethodBinding(visible, visibleIndex);
+			// all of visible are from the same declaringClass, even before 1.4 we can call this method instead of mostSpecificClassMethodBinding
+			return mostSpecificMethodBinding(visible, visibleIndex, argumentTypes, invocationSite);
 		} catch (AbortCompilation e) {
 			e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
 			throw e;
@@ -1106,26 +1574,22 @@
 				if (!methodScope.isInsideInitializer()){
 					// check method modifiers to see if deprecated
 					MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
-					if (context != null) {
+					if (context != null)
 						return context.modifiers;
-					}
 				} else {
-					SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
+					SourceTypeBinding type = ((BlockScope) this).referenceType().binding;
 
 					// inside field declaration ? check field modifier to see if deprecated
-					if (methodScope.initializedField != null) {
+					if (methodScope.initializedField != null)
 						return methodScope.initializedField.modifiers;
-					}
-					if (type != null) {
+					if (type != null)
 						return type.modifiers;
-					}
 				}
 				break;
 			case Scope.CLASS_SCOPE :
 				ReferenceBinding context = ((ClassScope)this).referenceType().binding;
-				if (context != null) {
+				if (context != null)
 					return context.modifiers;
-				}
 				break;
 		}
 		return -1;
@@ -1143,7 +1607,7 @@
 		} catch (AbortCompilation e) {
 			e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
 			throw e;
-		}
+		}			
 	}
 
 	/* API
@@ -1159,17 +1623,14 @@
 	 * 
 	 *	If no visible method is discovered, an error binding is answered.
 	 */
-	public MethodBinding getImplicitMethod(
-		char[] selector,
-		TypeBinding[] argumentTypes,
-		InvocationSite invocationSite) {
+	public MethodBinding getImplicitMethod(char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
 
 		boolean insideStaticContext = false;
 		boolean insideConstructorCall = false;
 		MethodBinding foundMethod = null;
-		ProblemMethodBinding foundFuzzyProblem = null;
+		MethodBinding foundFuzzyProblem = null;
 		// the weird method lookup case (matches method name in scope, then arg types, then visibility)
-		ProblemMethodBinding foundInsideProblem = null;
+		MethodBinding foundInsideProblem = null;
 		// inside Constructor call or inside static context
 		Scope scope = this;
 		int depth = 0;
@@ -1185,26 +1646,16 @@
 					SourceTypeBinding receiverType = classScope.referenceContext.binding;
 					boolean isExactMatch = true;
 					// retrieve an exact visible match (if possible)
+					// compilationUnitScope().recordTypeReference(receiverType);   not needed since receiver is the source type
 					MethodBinding methodBinding =
 						(foundMethod == null)
-							? classScope.findExactMethod(
-								receiverType,
-								selector,
-								argumentTypes,
-								invocationSite)
-							: classScope.findExactMethod(
-								receiverType,
-								foundMethod.selector,
-								foundMethod.parameters,
-								invocationSite);
-					//						? findExactMethod(receiverType, selector, argumentTypes, invocationSite)
-					//						: findExactMethod(receiverType, foundMethod.selector, foundMethod.parameters, invocationSite);
+							? classScope.findExactMethod(receiverType, selector, argumentTypes, invocationSite)
+							: classScope.findExactMethod(receiverType, foundMethod.selector, foundMethod.parameters, invocationSite);
 					if (methodBinding == null) {
 						// answers closest approximation, may not check argumentTypes or visibility
 						isExactMatch = false;
-						methodBinding =
-							classScope.findMethod(receiverType, selector, argumentTypes, invocationSite);
-						//					methodBinding = findMethod(receiverType, selector, argumentTypes, invocationSite);
+						methodBinding = classScope.findMethod(receiverType, selector, argumentTypes, invocationSite);
+						// methodBinding = findMethod(receiverType, selector, argumentTypes, invocationSite);
 					}
 					if (methodBinding != null) { // skip it if we did not find anything
 						if (methodBinding.problemId() == Ambiguous) {
@@ -1219,26 +1670,25 @@
 								argumentTypes,
 								InheritedNameHidesEnclosingName);
 						}
-						ProblemMethodBinding fuzzyProblem = null;
-						ProblemMethodBinding insideProblem = null;
+						MethodBinding fuzzyProblem = null;
+						MethodBinding insideProblem = null;
 						if (methodBinding.isValidBinding()) {
 							if (!isExactMatch) {
-								if (!areParametersAssignable(methodBinding.parameters, argumentTypes)) {
-									if (foundMethod == null || foundMethod.problemId() == NotVisible){
+								MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
+								if (compatibleMethod == null) {
+									if (foundMethod == null || foundMethod.problemId() == NotVisible)
 										// inherited mismatch is reported directly, not looking at enclosing matches
 										return new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotFound);
-									}
 									// make the user qualify the method, likely wants the first inherited method (javac generates an ambiguous error instead)
-									fuzzyProblem = new ProblemMethodBinding(selector, methodBinding.parameters, InheritedNameHidesEnclosingName);
-
-								} else if (!methodBinding.canBeSeenBy(receiverType, invocationSite, classScope)) {
-									// using <classScope> instead of <this> for visibility check does grant all access to innerclass
-									fuzzyProblem =
-										new ProblemMethodBinding(
-											methodBinding,
-											selector,
-											methodBinding.parameters,
-											NotVisible);
+									fuzzyProblem = new ProblemMethodBinding(methodBinding, selector, methodBinding.parameters, InheritedNameHidesEnclosingName);
+								} else if (!compatibleMethod.isValidBinding()) {
+									fuzzyProblem = compatibleMethod;
+								} else {
+									methodBinding = compatibleMethod;
+									if (!methodBinding.canBeSeenBy(receiverType, invocationSite, classScope)) {
+										// using <classScope> instead of <this> for visibility check does grant all access to innerclass
+										fuzzyProblem = new ProblemMethodBinding(methodBinding, selector, methodBinding.parameters, NotVisible);
+									}
 								}
 							}
 							if (fuzzyProblem == null && !methodBinding.isStatic()) {
@@ -1258,10 +1708,10 @@
 											NonStaticReferenceInStaticContext);
 								}
 							}
-							
+
 							if (receiverType == methodBinding.declaringClass
 								|| (receiverType.getMethods(selector)) != NoMethods
-								|| ((fuzzyProblem == null || fuzzyProblem.problemId() != NotVisible) && environment().options.complianceLevel >= ClassFileConstants.JDK1_4)){
+								|| ((fuzzyProblem == null || fuzzyProblem.problemId() != NotVisible) && environment().options.complianceLevel >= ClassFileConstants.JDK1_4)) {
 								// found a valid method in the 'immediate' scope (ie. not inherited)
 								// OR the receiverType implemented a method with the correct name
 								// OR in 1.4 mode (inherited visible shadows enclosing)
@@ -1289,12 +1739,10 @@
 							}
 						}
 
-						if (foundMethod == null
-							|| (foundMethod.problemId() == NotVisible
-								&& methodBinding.problemId() != NotVisible)) {
+						if (foundMethod == null || (foundMethod.problemId() == NotVisible && methodBinding.problemId() != NotVisible)) {
 							// only remember the methodBinding if its the first one found or the previous one was not visible & methodBinding is...
 							// remember that private methods are visible if defined directly by an enclosing class
-							if (depth > 0){
+							if (depth > 0) {
 								invocationSite.setDepth(depth);
 								invocationSite.setActualReceiverType(receiverType);
 							}
@@ -1325,6 +1773,53 @@
 			return foundInsideProblem;
 		if (foundMethod != null)
 			return foundMethod;
+
+		if (insideStaticContext && environment().options.complianceLevel >= ClassFileConstants.JDK1_5) {
+			// at this point the scope is a compilation unit scope & need to check for imported static methods
+			CompilationUnitScope unitScope = (CompilationUnitScope) scope;
+			ImportBinding[] imports = unitScope.imports;
+			if (imports != null) {
+				// check on demand imports
+				boolean foundInImport = false;
+				for (int i = 0, length = imports.length; i < length; i++) {
+					ImportBinding importBinding = imports[i];
+					if (importBinding.isStatic() && importBinding.onDemand) {
+						Binding resolvedImport = importBinding.resolvedImport;
+						if (resolvedImport instanceof ReferenceBinding) {
+							// answers closest approximation, may not check argumentTypes or visibility
+							MethodBinding temp = findMethod((ReferenceBinding) resolvedImport, selector, argumentTypes, invocationSite);
+							if (temp != null) {
+								if (!temp.isValidBinding()) {
+									if (foundMethod == null)
+										foundMethod = temp;
+								} else if (temp.isStatic()) {
+									MethodBinding compatibleMethod = computeCompatibleMethod(temp, argumentTypes, invocationSite);
+									if (compatibleMethod != null) {
+										if (compatibleMethod.isValidBinding()) {
+											if (compatibleMethod.canBeSeenBy(unitScope.fPackage)) {
+												ImportReference importReference = importBinding.reference;
+												if (importReference != null) importReference.used = true;
+												if (foundInImport)
+													// Answer error binding -- import on demand conflict; name found in two import on demand types.
+													return new ProblemMethodBinding(compatibleMethod, selector, compatibleMethod.parameters, Ambiguous);
+												foundMethod = compatibleMethod;
+												foundInImport = true;
+											} else if (foundMethod == null) {
+												foundMethod = new ProblemMethodBinding(compatibleMethod, selector, compatibleMethod.parameters, NotVisible);
+											}
+										}
+									} else if (foundMethod == null) {
+										foundMethod = new ProblemMethodBinding(temp, selector, argumentTypes, NotFound);
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+			if (foundMethod != null)
+				return foundMethod;
+		}
 		return new ProblemMethodBinding(selector, argumentTypes, NotFound);
 	}
 
@@ -1336,7 +1831,16 @@
 		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);
+		if (type != null) return type;
+	
+		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);
@@ -1362,7 +1866,14 @@
 		problemReporter().isClassPathCorrect(JAVA_LANG_CLONEABLE, referenceCompilationUnit());
 		return null; // will not get here since the above error aborts the compilation
 	}
-
+	public final ReferenceBinding getJavaLangEnum() {
+		compilationUnitScope().recordQualifiedReference(JAVA_LANG_ENUM);
+		ReferenceBinding type = environment().getType(JAVA_LANG_ENUM);
+		if (type != null) return type;
+	
+		problemReporter().isClassPathCorrect(JAVA_LANG_ENUM, referenceCompilationUnit());
+		return null; // will not get here since the above error aborts the compilation
+	}
 	public final ReferenceBinding getJavaLangError() {
 		compilationUnitScope().recordQualifiedReference(JAVA_LANG_ERROR);
 		ReferenceBinding type = environment().getType(JAVA_LANG_ERROR);
@@ -1371,7 +1882,14 @@
 		problemReporter().isClassPathCorrect(JAVA_LANG_ERROR, referenceCompilationUnit());
 		return null; // will not get here since the above error aborts the compilation
 	}
-
+	public final ReferenceBinding getJavaLangIterable() {
+		compilationUnitScope().recordQualifiedReference(JAVA_LANG_ITERABLE);
+		ReferenceBinding type = environment().getType(JAVA_LANG_ITERABLE);
+		if (type != null) return type;
+	
+		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);
@@ -1407,6 +1925,14 @@
 		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);
+		if (type != null) return type;
+	
+		problemReporter().isClassPathCorrect(JAVA_UTIL_ITERATOR, referenceCompilationUnit());
+		return null; // will not get here since the above error aborts the compilation
+	}
 
 	/* Answer the type binding corresponding to the typeName argument, relative to the enclosingType.
 	*/
@@ -1418,11 +1944,13 @@
 
 	public MethodBinding getMethod(TypeBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
 		try {
-			if (receiverType.isArrayType())
-				return findMethodForArray((ArrayBinding) receiverType, selector, argumentTypes, invocationSite);
 			if (receiverType.isBaseType())
 				return new ProblemMethodBinding(selector, argumentTypes, NotFound);
-	
+
+			compilationUnitScope().recordTypeReference(receiverType);
+			if (receiverType.isArrayType())
+				return findMethodForArray((ArrayBinding) receiverType, selector, argumentTypes, invocationSite);
+
 			ReferenceBinding currentType = (ReferenceBinding) receiverType;
 			if (!currentType.canBeSeenBy(this))
 				return new ProblemMethodBinding(selector, argumentTypes, ReceiverTypeNotVisible);
@@ -1431,32 +1959,64 @@
 			MethodBinding methodBinding = findExactMethod(currentType, selector, argumentTypes, invocationSite);
 			if (methodBinding != null) return methodBinding;
 	
+			// TODO (kent) performance - we are accumulating super methods which are *hidden* during the walk (see testcase from bug 69141)
 			// answers closest approximation, may not check argumentTypes or visibility
 			methodBinding = findMethod(currentType, selector, argumentTypes, invocationSite);
 			if (methodBinding == null)
 				return new ProblemMethodBinding(selector, argumentTypes, NotFound);
 			if (methodBinding.isValidBinding()) {
-				if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
-					return new ProblemMethodBinding(
-						methodBinding,
-						selector,
-						argumentTypes,
-						NotFound);
+				MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
+				if (compatibleMethod == null)
+					return new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotFound);
+				if (!compatibleMethod.isValidBinding())
+					return compatibleMethod;
+	
+				methodBinding = compatibleMethod;
 				if (!methodBinding.canBeSeenBy(currentType, invocationSite, this))
-					return new ProblemMethodBinding(
-						methodBinding,
-						selector,
-						methodBinding.parameters,
-						NotVisible);
+					return new ProblemMethodBinding( methodBinding, selector, methodBinding.parameters, NotVisible);
 			}
 			return methodBinding;
-			
 		} catch (AbortCompilation e) {
 			e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
 			throw e;
 		}
 	}
 
+	/* Answer the package from the compoundName or null if it begins with a type.
+	* Intended to be used while resolving a qualified type name.
+	*
+	* NOTE: If a problem binding is returned, senders should extract the compound name
+	* from the binding & not assume the problem applies to the entire compoundName.
+	*/
+	public final Binding getPackage(char[][] compoundName) {
+		compilationUnitScope().recordQualifiedReference(compoundName);
+		Binding binding = getTypeOrPackage(compoundName[0], Binding.TYPE | Binding.PACKAGE);
+		if (binding == null)
+			return new ProblemReferenceBinding(compoundName[0], NotFound);
+		if (!binding.isValidBinding())
+			return (ReferenceBinding) binding;
+
+		if (!(binding instanceof PackageBinding)) return null; // compoundName does not start with a package
+
+		int currentIndex = 1;
+		PackageBinding packageBinding = (PackageBinding) binding;
+		while (currentIndex < compoundName.length) {
+			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
+			if (binding == null)
+				return new ProblemReferenceBinding(
+					CharOperation.subarray(compoundName, 0, currentIndex),
+					NotFound);
+			if (!binding.isValidBinding())
+				return new ProblemReferenceBinding(
+					CharOperation.subarray(compoundName, 0, currentIndex),
+					binding.problemId());
+			if (!(binding instanceof PackageBinding))
+				return packageBinding;
+			packageBinding = (PackageBinding) binding;
+		}
+		return new ProblemReferenceBinding(compoundName, NotFound);
+	}
+
 	/* Answer the type binding that corresponds the given name, starting the lookup in the receiver.
 	* The name provided is a simple source name (e.g., "Object" , "Point", ...)
 	*/
@@ -1467,7 +2027,34 @@
 		// Would like to remove this test and require senders to specially handle base types
 		TypeBinding binding = getBaseType(name);
 		if (binding != null) return binding;
-		return (ReferenceBinding) getTypeOrPackage(name, TYPE);
+		return (ReferenceBinding) getTypeOrPackage(name, Binding.TYPE);
+	}
+
+	/* Answer the type binding that corresponds to the given name, starting the lookup in the receiver
+	* or the packageBinding if provided.
+	* The name provided is a simple source name (e.g., "Object" , "Point", ...)
+	*/
+	public final TypeBinding getType(char[] name, PackageBinding packageBinding) {
+		if (packageBinding == null)
+			return getType(name);
+
+		Binding binding = packageBinding.getTypeOrPackage(name);
+		if (binding == null)
+			return new ProblemReferenceBinding(
+				CharOperation.arrayConcat(packageBinding.compoundName, name),
+				NotFound);
+		if (!binding.isValidBinding())
+			return new ProblemReferenceBinding(
+				CharOperation.arrayConcat(packageBinding.compoundName, name),
+				binding.problemId());
+
+		ReferenceBinding typeBinding = (ReferenceBinding) binding;
+		if (!typeBinding.canBeSeenBy(this))
+			return new ProblemReferenceBinding(
+				CharOperation.arrayConcat(packageBinding.compoundName, name),
+				typeBinding,
+				NotVisible);
+		return typeBinding;
 	}
 
 	/* Answer the type binding corresponding to the compoundName.
@@ -1475,17 +2062,17 @@
 	* NOTE: If a problem binding is returned, senders should extract the compound name
 	* from the binding & not assume the problem applies to the entire compoundName.
 	*/
-	public final TypeBinding getType(char[][] compoundName) {
-		int typeNameLength = compoundName.length;
+	public final TypeBinding getType(char[][] compoundName, int typeNameLength) {
 		if (typeNameLength == 1) {
 			// Would like to remove this test and require senders to specially handle base types
 			TypeBinding binding = getBaseType(compoundName[0]);
 			if (binding != null) return binding;
 		}
 
-		compilationUnitScope().recordQualifiedReference(compoundName);
+		CompilationUnitScope unitScope = compilationUnitScope();
+		unitScope.recordQualifiedReference(compoundName);
 		Binding binding =
-			getTypeOrPackage(compoundName[0], typeNameLength == 1 ? TYPE : TYPE | PACKAGE);
+			getTypeOrPackage(compoundName[0], typeNameLength == 1 ? Binding.TYPE : Binding.TYPE | Binding.PACKAGE);
 		if (binding == null)
 			return new ProblemReferenceBinding(compoundName[0], NotFound);
 		if (!binding.isValidBinding())
@@ -1518,7 +2105,7 @@
 
 		// binding is now a ReferenceBinding
 		ReferenceBinding typeBinding = (ReferenceBinding) binding;
-		compilationUnitScope().recordTypeReference(typeBinding); // to record supertypes
+		unitScope.recordTypeReference(typeBinding);
 		if (checkVisibility) // handles the fall through case
 			if (!typeBinding.canBeSeenBy(this))
 				return new ProblemReferenceBinding(
@@ -1549,7 +2136,8 @@
 	final Binding getTypeOrPackage(char[] name, int mask) {
 		Scope scope = this;
 		ReferenceBinding foundType = null;
-		if ((mask & TYPE) == 0) {
+		boolean insideStaticContext = false;
+		if ((mask & Binding.TYPE) == 0) {
 			Scope next = scope;
 			while ((next = scope.parent) != null)
 				scope = next;
@@ -1557,6 +2145,13 @@
 			done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
 				switch (scope.kind) {
 					case METHOD_SCOPE :
+						MethodScope methodScope = (MethodScope) scope;
+						AbstractMethodDeclaration methodDecl = methodScope.referenceMethod();
+						if (methodDecl != null && methodDecl.binding != null) {
+							TypeVariableBinding typeVariable = methodDecl.binding.getTypeVariable(name);
+							if (typeVariable != null)	return typeVariable;
+						}
+						insideStaticContext |= methodScope.isStatic;
 					case BLOCK_SCOPE :
 						ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only
 						if (localType != null) {
@@ -1567,7 +2162,24 @@
 						break;
 					case CLASS_SCOPE :
 						SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
-						// 6.5.5.1 - simple name favors member type over top-level type in same unit
+						if (sourceType.isHierarchyBeingConnected()) {
+							// type variables take precedence over the source type, ex. class X <X> extends X == class X <Y> extends Y 
+							TypeVariableBinding typeVariable = sourceType.getTypeVariable(name);
+							if (typeVariable != null)
+								return typeVariable;
+							if (CharOperation.equals(name, sourceType.sourceName))
+								return sourceType;
+							break;
+						}
+						// type variables take precedence over member types
+						TypeVariableBinding typeVariable = sourceType.getTypeVariable(name);
+						if (typeVariable != null) {
+							if (insideStaticContext) // do not consider this type modifiers: access is legite within same type
+								return new ProblemReferenceBinding(name, NonStaticReferenceInStaticContext);
+							return typeVariable;
+						}
+						insideStaticContext |= (sourceType.modifiers & AccStatic) != 0; // not isStatic()
+						// 6.5.5.1 - member types have precedence over top-level type in same unit
 						ReferenceBinding memberType = findMemberType(name, sourceType);
 						if (memberType != null) { // skip it if we did not find anything
 							if (memberType.problemId() == Ambiguous) {
@@ -1584,10 +2196,9 @@
 									// OR in 1.4 mode (inherited shadows enclosing)
 									if (foundType == null)
 										return memberType; 
-									if (foundType.isValidBinding())
-										// if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
-										if (foundType != memberType)
-											return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
+									// if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
+									if (foundType.isValidBinding() && foundType != memberType)
+										return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
 								}
 							}
 							if (foundType == null || (foundType.problemId() == NotVisible && memberType.problemId() != NotVisible))
@@ -1613,7 +2224,7 @@
 		CompilationUnitScope unitScope = (CompilationUnitScope) scope;
 		PackageBinding currentPackage = unitScope.fPackage; 
 		// ask for the imports + name
-		if ((mask & TYPE) != 0) {
+		if ((mask & Binding.TYPE) != 0) {
 			// check single type imports.
 
 			ImportBinding[] imports = unitScope.imports;
@@ -1632,9 +2243,10 @@
 						ImportBinding typeImport = imports[i];
 						if (!typeImport.onDemand) {
 							if (CharOperation.equals(typeImport.compoundName[typeImport.compoundName.length - 1], name)) {
-								if (unitScope.resolveSingleTypeImport(typeImport) != null) {
+								if (unitScope.resolveSingleImport(typeImport) != null) {
 									ImportReference importReference = typeImport.reference;
-									if (importReference != null) importReference.used = true;
+									if (importReference != null)
+										importReference.used = true;
 									return typeImport.resolvedImport; // already know its visible
 								}
 							}
@@ -1657,7 +2269,9 @@
 						Binding resolvedImport = someImport.resolvedImport;
 						ReferenceBinding temp = resolvedImport instanceof PackageBinding
 							? findType(name, (PackageBinding) resolvedImport, currentPackage)
-							: findDirectMemberType(name, (ReferenceBinding) resolvedImport);
+							: (someImport.isStatic()
+								? findMemberType(name, (ReferenceBinding) resolvedImport) // static imports are allowed to see inherited member types
+								: findDirectMemberType(name, (ReferenceBinding) resolvedImport));
 						if (temp != null) {
 							if (temp.isValidBinding()) {
 								ImportReference importReference = someImport.reference;
@@ -1678,7 +2292,7 @@
 		}
 
 		unitScope.recordSimpleReference(name);
-		if ((mask & PACKAGE) != 0) {
+		if ((mask & Binding.PACKAGE) != 0) {
 			PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
 			if (packageBinding != null) return packageBinding;
 		}
@@ -1689,13 +2303,16 @@
 	}
 
 	// 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
+	// use CompilationUnitScope.getImport(char[][]) instead
 	public final Binding getTypeOrPackage(char[][] compoundName) {
 		int nameLength = compoundName.length;
 		if (nameLength == 1) {
 			TypeBinding binding = getBaseType(compoundName[0]);
 			if (binding != null) return binding;
 		}
-		Binding binding = getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
+		Binding binding = getTypeOrPackage(compoundName[0], Binding.TYPE | Binding.PACKAGE);
 		if (!binding.isValidBinding()) return binding;
 
 		int currentIndex = 1;
@@ -1721,7 +2338,17 @@
 			checkVisibility = true;
 		}
 		// binding is now a ReferenceBinding
+		ReferenceBinding qualifiedType = null;
+
 		ReferenceBinding typeBinding = (ReferenceBinding) binding;
+		if (typeBinding.isGenericType()) {
+			qualifiedType = this.environment().createRawType(typeBinding, qualifiedType);
+		} else {
+			qualifiedType = (qualifiedType != null && (qualifiedType.isRawType() || qualifiedType.isParameterizedType()))
+				? this.createParameterizedType(typeBinding, null, qualifiedType)
+				: typeBinding;
+		}
+
 		if (checkVisibility) // handles the fall through case
 			if (!typeBinding.canBeSeenBy(this))
 				return new ProblemReferenceBinding(
@@ -1731,18 +2358,63 @@
 
 		while (currentIndex < nameLength) {
 			typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
+
+			if (typeBinding.isGenericType()) {
+				qualifiedType = this.environment().createRawType(typeBinding, qualifiedType);
+			} else {
+				qualifiedType = (qualifiedType != null && (qualifiedType.isRawType() || qualifiedType.isParameterizedType()))
+					? this.createParameterizedType(typeBinding, null, qualifiedType)
+					: typeBinding;
+			}
+
 			// checks visibility
-			if (!typeBinding.isValidBinding())
+			if (!qualifiedType.isValidBinding())
 				return new ProblemReferenceBinding(
 					CharOperation.subarray(compoundName, 0, currentIndex),
-					typeBinding.problemId());
+					qualifiedType.problemId());
 		}
-		return typeBinding;
+		return qualifiedType;
+	}
+	
+	// 5.1.10
+	public TypeBinding[] greaterLowerBound(TypeBinding[] types) {
+		if (types == null) return null;
+		int length = types.length;
+		TypeBinding[] result = types;
+		int removed = 0;
+		for (int i = 0; i < length; i++) {
+			TypeBinding iType = result[i];
+			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;
+		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;
+	}
+
+	public boolean isBoxingCompatibleWith(TypeBinding left, TypeBinding right) {
+		return left.isBaseType() != right.isBaseType() && environment().isBoxingCompatibleWith(left, right);
 	}
 
 	/* Answer true if the scope is nested inside a given field declaration.
-     * Note: it works as long as the scope.fieldDeclarationIndex is reflecting the field being traversed 
-     * e.g. during name resolution.
+	 * Note: it works as long as the scope.fieldDeclarationIndex is reflecting the field being traversed 
+	 * e.g. during name resolution.
 	*/
 	public final boolean isDefinedInField(FieldBinding field) {
 		Scope scope = this;
@@ -1763,10 +2435,9 @@
 		do {
 			if (scope instanceof MethodScope) {
 				ReferenceContext refContext = ((MethodScope) scope).referenceContext;
-				if (refContext instanceof AbstractMethodDeclaration
-						&& ((AbstractMethodDeclaration)refContext).binding == method) {
-					return true;
-				}
+				if (refContext instanceof AbstractMethodDeclaration)
+					if (((AbstractMethodDeclaration) refContext).binding == method)
+						return true;
 			}
 			scope = scope.parent;
 		} while (scope != null);
@@ -1787,8 +2458,7 @@
 			unitScope = scope;
 
 		// test that the enclosingType is not part of the compilation unit
-		SourceTypeBinding[] topLevelTypes =
-			((CompilationUnitScope) unitScope).topLevelTypes;
+		SourceTypeBinding[] topLevelTypes = ((CompilationUnitScope) unitScope).topLevelTypes;
 		for (int i = topLevelTypes.length; --i >= 0;)
 			if (topLevelTypes[i] == enclosingType)
 				return true;
@@ -1801,9 +2471,8 @@
 		Scope scope = this;
 		do {
 			if (scope instanceof ClassScope)
-				if (((ClassScope) scope).referenceContext.binding == type){
+				if (((ClassScope) scope).referenceContext.binding == type)
 					return true;
-				}
 			scope = scope.parent;
 		} while (scope != null);
 		return false;
@@ -1817,29 +2486,136 @@
 				if (!methodScope.isInsideInitializer()){
 					// check method modifiers to see if deprecated
 					MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
-					if (context != null && context.isViewedAsDeprecated()) {
+					if (context != null && context.isViewedAsDeprecated())
 						return true;
-					}
 				} else {
 					SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
 					// inside field declaration ? check field modifier to see if deprecated
-					if (methodScope.initializedField != null && methodScope.initializedField.isViewedAsDeprecated()) {
+					if (methodScope.initializedField != null && methodScope.initializedField.isViewedAsDeprecated())
 						return true;
-					}
-					if (type != null && type.isViewedAsDeprecated()) {
+					if (type != null && type.isViewedAsDeprecated())
 						return true;
-					}
 				}
 				break;
 			case Scope.CLASS_SCOPE :
 				ReferenceBinding context = ((ClassScope)this).referenceType().binding;
-				if (context != null && context.isViewedAsDeprecated()) {
+				if (context != null && context.isViewedAsDeprecated())
 					return true;
-				}
 				break;
 		}
 		return false;
 	}
+	private TypeBinding leastContainingInvocation(TypeBinding mec, List invocations) {
+		int length = invocations.size();
+		if (length == 0) return mec;
+		if (length == 1) return (TypeBinding) invocations.get(0);
+		int argLength = mec.typeVariables().length;
+		if (argLength == 0) return mec; // should be caught by no invocation check
+
+		// infer proper parameterized type from invocations
+		TypeBinding[] bestArguments = new TypeBinding[argLength];
+		for (int i = 0; i < length; i++) {
+			TypeBinding invocation = (TypeBinding)invocations.get(i);
+			TypeVariableBinding[] invocationVariables = invocation.typeVariables();
+			if (invocation.isGenericType()) {
+				for (int j = 0; j < argLength; j++) {
+					TypeBinding bestArgument = leastContainingTypeArgument(bestArguments[j], invocationVariables[j], (ReferenceBinding) mec, j);
+					if (bestArgument == null) return null;
+					bestArguments[j] = bestArgument;
+				}
+			} else if (invocation.isParameterizedType()) {
+				ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding)invocation;
+				for (int j = 0; j < argLength; j++) {
+					TypeBinding bestArgument = leastContainingTypeArgument(bestArguments[j], parameterizedType.arguments[j], (ReferenceBinding) mec, j);
+					if (bestArgument == null) return null;
+					bestArguments[j] = bestArgument;
+				}
+			} else if (invocation.isRawType()) {
+				return invocation; // raw type is taking precedence
+			}
+		}
+		return createParameterizedType((ReferenceBinding) mec.erasure(), bestArguments, null);
+	}
+	
+	// JLS 15.12.2
+	private TypeBinding leastContainingTypeArgument(TypeBinding u, TypeBinding v, ReferenceBinding genericType, int rank) {
+		if (u == null) return v;
+		if (u == v) return u;
+		if (v.isWildcard()) {
+			WildcardBinding wildV = (WildcardBinding) v;
+			if (u.isWildcard()) {
+				WildcardBinding wildU = (WildcardBinding) u;
+				switch (wildU.kind) {
+					// ? extends U
+					case Wildcard.EXTENDS :
+						switch(wildV.kind) {
+							// ? extends U, ? extends V
+							case Wildcard.EXTENDS :  
+								TypeBinding lub = lowerUpperBound(new TypeBinding[]{wildU.bound,wildV.bound});
+								if (lub == null) return null;
+								return environment().createWildcard(genericType, rank, lub, Wildcard.EXTENDS);	
+							// ? extends U, ? SUPER V
+							case Wildcard.SUPER : 
+								if (wildU.bound == wildV.bound) return wildU.bound;
+								return environment().createWildcard(genericType, rank, null, Wildcard.UNBOUND);
+						}
+						break;
+						// ? super U
+					case Wildcard.SUPER : 
+						// ? super U, ? super V
+						if (wildU.kind == Wildcard.SUPER) {
+							TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound,wildV.bound});
+							if (glb == null) return null;
+							return environment().createWildcard(genericType, rank, glb[0], Wildcard.SUPER);	// TODO (philippe) need to capture entire bounds
+						}
+				}				
+			} else {
+				switch (wildV.kind) {
+					// U, ? extends V
+					case Wildcard.EXTENDS :
+						TypeBinding lub = lowerUpperBound(new TypeBinding[]{u,wildV.bound});
+						if (lub == null) return null;
+						return environment().createWildcard(genericType, rank, lub, Wildcard.EXTENDS);	
+					// U, ? super V
+					case Wildcard.SUPER :
+						TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{u,wildV.bound});
+						if (glb == null) return null;
+						return environment().createWildcard(genericType, rank, glb[0], Wildcard.SUPER);	// TODO (philippe) need to capture entire bounds
+					case Wildcard.UNBOUND :
+				}
+			}
+		} else if (u.isWildcard()) {
+			WildcardBinding wildU = (WildcardBinding) u;
+			switch (wildU.kind) {
+				// U, ? extends V
+				case Wildcard.EXTENDS :
+					TypeBinding lub = lowerUpperBound(new TypeBinding[]{wildU.bound, v});
+					if (lub == null) return null;
+					return environment().createWildcard(genericType, rank, lub, Wildcard.EXTENDS);	
+				// U, ? super V
+				case Wildcard.SUPER :
+					TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound, v});
+					if (glb == null) return null;
+					return environment().createWildcard(genericType, rank, glb[0], Wildcard.SUPER); // TODO (philippe) need to capture entire bounds		
+				case Wildcard.UNBOUND :
+			}
+		}
+		TypeBinding lub = lowerUpperBound(new TypeBinding[]{u,v});
+		if (lub == null) return null;
+		return environment().createWildcard(genericType, rank, lub, Wildcard.EXTENDS);
+	}
+
+	// 15.12.2
+	public TypeBinding lowerUpperBound(TypeBinding[] types) {
+		
+		if (types.length == 1) {
+			TypeBinding type = types[0];
+			return type == null ? VoidBinding : type;
+		}
+		ArrayList invocations = new ArrayList(1);
+		TypeBinding mec = minimalErasedCandidate(types, invocations);
+		return leastContainingInvocation(mec, invocations);
+	}
 	
 	public final MethodScope methodScope() {
 		Scope scope = this;
@@ -1851,6 +2627,143 @@
 		return null;
 	}
 
+	/**
+	 * Returns the most specific type compatible with all given types.
+	 * (i.e. most specific common super type)
+	 * If no types is given, will return VoidBinding. If not compatible 
+	 * reference type is found, returns null.
+	 */
+	private TypeBinding minimalErasedCandidate(TypeBinding[] types, List invocations) {
+		Map allInvocations = new HashMap(2);
+		int length = types.length;
+		int indexOfFirst = -1, actualLength = 0;
+		for (int i = 0; i < length; i++) {
+			TypeBinding type = types[i];
+			if (type == null) continue;
+			if (type.isBaseType()) return null;
+			if (indexOfFirst < 0) indexOfFirst = i;
+			actualLength ++;
+		}
+		switch (actualLength) {
+			case 0: return VoidBinding;
+			case 1: return types[indexOfFirst];
+		}
+
+		// record all supertypes of type
+		// intersect with all supertypes of otherType
+		TypeBinding firstType = types[indexOfFirst];
+		TypeBinding[] superTypes;
+		int superLength;
+		if (firstType.isBaseType()) {
+			return null; 
+		} else if (firstType.isArrayType()) {
+			superLength = 4;
+			if (firstType.erasure() != firstType) {
+				ArrayList someInvocations = new ArrayList(1);
+				someInvocations.add(firstType);
+				allInvocations.put(firstType.erasure(), someInvocations);
+			}
+			superTypes = new TypeBinding[] {
+					firstType.erasure(), 
+					getJavaIoSerializable(),
+					getJavaLangCloneable(),
+					getJavaLangObject(),
+			};
+		} else {
+			ArrayList typesToVisit = new ArrayList(5);
+			if (firstType.erasure() != firstType) {
+				ArrayList someInvocations = new ArrayList(1);
+				someInvocations.add(firstType);
+				allInvocations.put(firstType.erasure(), someInvocations);
+			}			
+			typesToVisit.add(firstType.erasure());
+			ReferenceBinding currentType = (ReferenceBinding)firstType;
+			for (int i = 0, max = 1; i < max; i++) {
+				currentType = (ReferenceBinding) typesToVisit.get(i);
+				TypeBinding itsSuperclass = currentType.superclass();
+				if (itsSuperclass != null) {
+					TypeBinding itsSuperclassErasure = itsSuperclass.erasure();
+					if (!typesToVisit.contains(itsSuperclassErasure)) {
+						if (itsSuperclassErasure != itsSuperclass) {
+							ArrayList someInvocations = new ArrayList(1);
+							someInvocations.add(itsSuperclass);
+							allInvocations.put(itsSuperclassErasure, someInvocations);
+						}
+						typesToVisit.add(itsSuperclassErasure);
+						max++;
+					}
+				}
+				ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+				for (int j = 0, count = itsInterfaces.length; j < count; j++) {
+					TypeBinding itsInterface = itsInterfaces[j];
+					TypeBinding itsInterfaceErasure = itsInterface.erasure();
+					if (!typesToVisit.contains(itsInterfaceErasure)) {
+						if (itsInterfaceErasure != itsInterface) {
+							ArrayList someInvocations = new ArrayList(1);
+							someInvocations.add(itsInterface);
+							allInvocations.put(itsInterfaceErasure, someInvocations);
+						}						
+						typesToVisit.add(itsInterfaceErasure);
+						max++;
+					}
+				}
+			}
+			superLength = typesToVisit.size();
+			superTypes = new TypeBinding[superLength];
+			typesToVisit.toArray(superTypes);
+		}
+		int remaining = superLength;
+		nextOtherType: for (int i = indexOfFirst+1; i < length; i++) {
+			TypeBinding otherType = types[i];
+			if (otherType == null)
+				continue nextOtherType;
+			else if (otherType.isArrayType()) {
+				nextSuperType: for (int j = 0; j < superLength; j++) {
+					TypeBinding superType = superTypes[j];
+					if (superType == null || superType == otherType) continue nextSuperType;
+					switch (superType.id) {
+						case T_JavaIoSerializable :
+						case T_JavaLangCloneable :
+						case T_JavaLangObject :
+							continue nextSuperType;
+					}
+					superTypes[j] = null;
+					if (--remaining == 0) return null;
+					
+				}
+				continue nextOtherType;
+			}
+			ReferenceBinding otherRefType = (ReferenceBinding) otherType;
+			nextSuperType: for (int j = 0; j < superLength; j++) {
+				TypeBinding superType = superTypes[j];
+				if (superType == null) continue nextSuperType;
+				if (otherRefType.erasure().isCompatibleWith(superType)) {
+					TypeBinding match = otherRefType.findSuperTypeErasingTo((ReferenceBinding)superType);
+						if (match != null && match.erasure() != match) { // match can be null: interface.findSuperTypeErasingTo(Object)
+							ArrayList someInvocations = (ArrayList) allInvocations.get(superType);
+							if (someInvocations == null) someInvocations = new ArrayList(1);
+							someInvocations.add(match);
+							allInvocations.put(superType, someInvocations);
+						}						
+					break nextSuperType;
+				} else {
+					superTypes[j] = null;
+					if (--remaining == 0) return null;
+				}
+			}				
+		}
+		// per construction, first non-null supertype is most specific common supertype
+		for (int i = 0; i < superLength; i++) {
+			TypeBinding superType = superTypes[i];
+			if (superType != null) {
+				List matchingInvocations = (List)allInvocations.get(superType);
+				if (matchingInvocations != null) invocations.addAll(matchingInvocations);
+				return superType;
+			}
+		}
+		return null;
+	}
+	
 	// Internal use only
 	/* All methods in visible are acceptable matches for the method in question...
 	* The methods defined by the receiver type appear before those defined by its
@@ -1861,29 +2774,28 @@
 	* is defined by a superclass, when a lesser match is defined by the receiver type
 	* or a closer superclass.
 	*/
-	protected final MethodBinding mostSpecificClassMethodBinding(MethodBinding[] visible, int visibleSize) {
-
-		MethodBinding method = null;
+	protected final MethodBinding mostSpecificClassMethodBinding(MethodBinding[] visible, int visibleSize, InvocationSite invocationSite) {
+		MethodBinding problemMethod = null;
 		MethodBinding previous = null;
-
 		nextVisible : for (int i = 0; i < visibleSize; i++) {
-			method = visible[i];
-						
+			MethodBinding method = visible[i];
 			if (previous != null && method.declaringClass != previous.declaringClass)
 				break; // cannot answer a method farther up the hierarchy than the first method found
-			previous = method;
+
+			if (!method.isStatic()) previous = method; // no ambiguity for static methods
 			for (int j = 0; j < visibleSize; j++) {
 				if (i == j) continue;
-				MethodBinding next = visible[j];
-				if (!areParametersAssignable(next.parameters, method.parameters))
+				if (!visible[j].areParametersCompatibleWith(method.parameters))
 					continue nextVisible;
 			}
 			compilationUnitScope().recordTypeReferences(method.thrownExceptions);
 			return method;
 		}
-		return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
+		if (problemMethod == null)
+			return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
+		return problemMethod;
 	}
-
+	
 	// Internal use only
 	/* All methods in visible are acceptable matches for the method in question...
 	* Since the receiver type is an interface, we ignore the possibility that 2 inherited
@@ -1913,42 +2825,53 @@
 		public void foo(I i, X x) { i.bar(x); }
 	}
 	*/
-	protected final MethodBinding mostSpecificInterfaceMethodBinding(MethodBinding[] visible, int visibleSize) {
-		MethodBinding method = null;
+	protected final MethodBinding mostSpecificInterfaceMethodBinding(MethodBinding[] visible, int visibleSize, InvocationSite invocationSite) {
+		MethodBinding problemMethod = null;
 		nextVisible : for (int i = 0; i < visibleSize; i++) {
-			method = visible[i];
+			MethodBinding method = visible[i];
 			for (int j = 0; j < visibleSize; j++) {
 				if (i == j) continue;
-				MethodBinding next = visible[j];
-				if (!areParametersAssignable(next.parameters, method.parameters))
+				if (!visible[j].areParametersCompatibleWith(method.parameters))
 					continue nextVisible;
 			}
 			compilationUnitScope().recordTypeReferences(method.thrownExceptions);
 			return method;
 		}
-		return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
+		if (problemMethod == null)
+			return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
+		return problemMethod;
 	}
 
-	
-	// Internal use only
-	/* All methods in visible are acceptable matches for the method in question...
-	* Since 1.4, the inherited ambiguous case has been removed from mostSpecificClassMethodBinding
-	*/
-	protected final MethodBinding mostSpecificMethodBinding(MethodBinding[] visible, int visibleSize) {
-		MethodBinding method = null;
-		nextVisible : for (int i = 0; i < visibleSize; i++) {
-			method = visible[i];
-			for (int j = 0; j < visibleSize; j++) {
-				if (i == j) continue;
-				MethodBinding next = visible[j];
-				if (!areParametersAssignable(next.parameters, method.parameters))
-					continue nextVisible;
+	protected final MethodBinding mostSpecificMethodBinding(MethodBinding[] visible, int visibleSize, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
+		int[] compatibilityLevels = new int[visibleSize];
+		for (int i = 0; i < visibleSize; i++)
+			compatibilityLevels[i] = parameterCompatibilityLevel(visible[i], argumentTypes);
+
+		for (int level = 0; level <= 2; level++) {
+			nextVisible : for (int i = 0; i < visibleSize; i++) {
+				if (compatibilityLevels[i] != level) continue nextVisible; // skip this method for now
+				MethodBinding method = visible[i];
+				for (int j = 0; j < visibleSize; j++) {
+					if (i == j || compatibilityLevels[j] != level) continue;
+					// tiebreak generic methods using variant where type params are substituted by their erasures
+					if (!visible[j].tiebreakMethod().areParametersCompatibleWith(method.tiebreakMethod().parameters)) {
+						if (method.isVarargs() && visible[j].isVarargs()) {
+							int paramLength = method.parameters.length;
+							if (paramLength == visible[j].parameters.length && paramLength == argumentTypes.length + 1) {
+								TypeBinding elementsType = ((ArrayBinding) visible[j].parameters[paramLength - 1]).elementsType();
+								if (method.parameters[paramLength - 1].isCompatibleWith(elementsType))
+									continue; // special case to choose between 2 varargs methods when the last arg is missing
+							}
+						}
+						continue nextVisible;
+					}
+				}
+				compilationUnitScope().recordTypeReferences(method.thrownExceptions);
+				return method;
 			}
-			compilationUnitScope().recordTypeReferences(method.thrownExceptions);
-			return method;
 		}
 		return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
-	}
+	}	
 
 	public final ClassScope outerMostClassScope() {
 		ClassScope lastClassScope = null;
@@ -1972,6 +2895,55 @@
 		return lastMethodScope; // may answer null if no method around
 	}
 
+	protected int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] arguments) {
+		TypeBinding[] parameters = method.parameters;
+		int paramLength = parameters.length;
+		int argLength = arguments.length;
+		int lastIndex = argLength;
+		int level = COMPATIBLE; // no autoboxing or varargs support needed
+		if (method.isVarargs()) {
+			lastIndex = paramLength - 1;
+			if (paramLength == argLength) { // accept X or X[] but not X[][]
+				TypeBinding param = parameters[lastIndex]; // is an ArrayBinding by definition
+				TypeBinding arg = arguments[lastIndex];
+				if (param != arg && !arg.isCompatibleWith(param)) {
+					if (isBoxingCompatibleWith(arg, param)) {
+						level = AUTOBOX_COMPATIBLE; // autoboxing support needed
+					} else {
+						// expect X[], called with X
+						param = ((ArrayBinding) param).elementsType();
+						if (!arg.isCompatibleWith(param) && !isBoxingCompatibleWith(arg, param))
+							return NOT_COMPATIBLE;
+						level = VARARGS_COMPATIBLE; // varargs support needed
+					}
+				}
+			} else {
+				if (paramLength < argLength) { // all remainig argument types must be compatible with the elementsType of varArgType
+					TypeBinding param = ((ArrayBinding) parameters[lastIndex]).elementsType();
+					for (int i = lastIndex; i < argLength; i++) {
+						TypeBinding arg = arguments[i];
+						if (param != arg && !arg.isCompatibleWith(param) && !isBoxingCompatibleWith(arg, param))
+							return NOT_COMPATIBLE;
+					}
+				}  else if (lastIndex != argLength) { // can call foo(int i, X ... x) with foo(1) but NOT foo();
+					return NOT_COMPATIBLE;
+				}
+				level = VARARGS_COMPATIBLE; // varargs support needed
+			}
+			// now compare standard arguments from 0 to lastIndex
+		}
+		for (int i = 0; i < lastIndex; i++) {
+			TypeBinding param = parameters[i];
+			TypeBinding arg = arguments[i];
+			if (arg != param && !arg.isCompatibleWith(param)) {
+				if (!isBoxingCompatibleWith(arg, param))
+					return NOT_COMPATIBLE;
+				level = AUTOBOX_COMPATIBLE; // autoboxing support needed
+			}
+		}
+		return level;
+	}
+
 	public abstract ProblemReporter problemReporter();
 
 	public final CompilationUnitDeclaration referenceCompilationUnit() {
@@ -1997,4 +2969,56 @@
 		} while (scope != null);
 		return null;
 	}
+	/*
+	 * Unboxing primitive
+	 */
+	public int unboxing(int id) {
+		switch (id) {
+			case T_JavaLangInteger :
+				return T_int;
+			case T_JavaLangByte :
+				return T_byte;
+			case T_JavaLangShort :
+				return T_short;
+			case T_JavaLangCharacter :
+				return T_char;
+			case T_JavaLangLong :
+				return T_long;
+			case T_JavaLangFloat :
+				return T_float;
+			case T_JavaLangDouble :
+				return T_double;
+			case T_JavaLangBoolean :
+				return T_boolean;
+			case T_JavaLangVoid :
+				return T_void;
+		}
+		return id;
+	}
+	/*
+	 * Unboxing primitive
+	 */
+	public TypeBinding unboxing(TypeBinding type) {
+		switch (type.id) {
+			case T_JavaLangInteger :
+				return IntBinding;
+			case T_JavaLangByte :
+				return ByteBinding;
+			case T_JavaLangShort :
+				return ShortBinding;		
+			case T_JavaLangCharacter :
+				return CharBinding;				
+			case T_JavaLangLong :
+				return LongBinding;
+			case T_JavaLangFloat :
+				return FloatBinding;
+			case T_JavaLangDouble :
+				return DoubleBinding;
+			case T_JavaLangBoolean :
+				return BooleanBinding;
+			case T_JavaLangVoid :
+				return VoidBinding;
+		}
+		return type;
+	}		
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SignatureWrapper.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SignatureWrapper.java
new file mode 100644
index 0000000..b4293a0
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SignatureWrapper.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+
+public class SignatureWrapper {
+	public char[] signature;
+	public int start;
+	public int end;
+	public int bracket;
+
+	public SignatureWrapper(char[] signature) {
+		this.signature = signature;
+		this.start = 0;
+		this.end = this.bracket = -1;
+	}
+	public boolean atEnd() {
+		return this.start < 0 || this.start >= this.signature.length;
+	}
+	public int computeEnd() {
+		int index = this.start;
+		while (this.signature[index] == '[')
+			index++;
+		switch (this.signature[index]) {
+			case 'L' :
+			case 'T' :
+				this.end = CharOperation.indexOf(';', this.signature, this.start);
+				if (this.bracket <= this.start) // already know it if its > start
+					this.bracket = CharOperation.indexOf('<', this.signature, this.start);
+		
+				if (this.bracket > this.start && this.bracket < this.end)
+					this.end = this.bracket;
+				else if (this.end == -1)
+					this.end = this.signature.length + 1;
+				break;
+			default :
+				this.end = this.start;
+		}
+
+		this.start = this.end + 1; // skip ';'
+		return this.end;
+	}
+	public char[] nextWord() {
+		this.end = CharOperation.indexOf(';', this.signature, this.start);
+		if (this.bracket <= this.start) // already know it if its > start
+			this.bracket = CharOperation.indexOf('<', this.signature, this.start);
+		int dot = CharOperation.indexOf('.', this.signature, this.start);
+
+		if (this.bracket > this.start && this.bracket < this.end)
+			this.end = this.bracket;
+		if (dot > this.start && dot < this.end)
+			this.end = dot;
+
+		return CharOperation.subarray(this.signature, this.start, this.start = this.end); // skip word
+	}
+	public String toString() {
+		return new String(this.signature) + " @ " + this.start; //$NON-NLS-1$
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index e791f1e..6c1b032 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -10,21 +10,24 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
-import java.util.Enumeration;
+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;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Argument;
-import org.eclipse.jdt.internal.compiler.ast.AssertStatement;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
-import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 
 public class SourceTypeBinding extends ReferenceBinding {
 	public ReferenceBinding superclass;
@@ -32,16 +35,17 @@
 	public FieldBinding[] fields;
 	public MethodBinding[] methods;
 	public ReferenceBinding[] memberTypes;
+    public TypeVariableBinding[] typeVariables;
 
 	public ClassScope scope;
 
-	// Synthetics are separated into 4 categories: methods, super methods, fields, class literals and changed declaring type bindings
+	// Synthetics are separated into 5 categories: methods, super methods, fields, class literals, changed declaring type bindings and bridge methods
 	public final static int METHOD_EMUL = 0;
 	public final static int FIELD_EMUL = 1;
 	public final static int CLASS_LITERAL_EMUL = 2;
 	public final static int RECEIVER_TYPE_EMUL = 3;
-	
-	Hashtable[] synthetics;
+	HashMap[] synthetics;
+	char[] genericReferenceTypeSignature;
 	
 public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
 	this.compoundName = compoundName;
@@ -110,18 +114,18 @@
 *	Answer the new field or the existing field if one already existed.
 */
 
-public FieldBinding addSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
+public FieldBinding addSyntheticFieldForInnerclass(LocalVariableBinding actualOuterLocalVariable) {
 	if (synthetics == null) {
-		synthetics = new Hashtable[4];
+		synthetics = new HashMap[4];
 	}
 	if (synthetics[FIELD_EMUL] == null) {
-		synthetics[FIELD_EMUL] = new Hashtable(5);
+		synthetics[FIELD_EMUL] = new HashMap(5);
 	}
 	
 	FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get(actualOuterLocalVariable);
 	if (synthField == null) {
 		synthField = new SyntheticFieldBinding(
-			CharOperation.concat(SyntheticArgumentBinding.OuterLocalPrefix, actualOuterLocalVariable.name), 
+			CharOperation.concat(TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX, actualOuterLocalVariable.name), 
 			actualOuterLocalVariable.type, 
 			AccPrivate | AccFinal | AccSynthetic, 
 			this, 
@@ -142,7 +146,7 @@
 				FieldDeclaration fieldDecl = typeDecl.fields[i];
 				if (fieldDecl.binding == existingField) {
 					synthField.name = CharOperation.concat(
-						SyntheticArgumentBinding.OuterLocalPrefix,
+						TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX,
 						actualOuterLocalVariable.name,
 						("$" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
 					needRecheck = true;
@@ -157,20 +161,20 @@
 *	Answer the new field or the existing field if one already existed.
 */
 
-public FieldBinding addSyntheticField(ReferenceBinding enclosingType) {
+public FieldBinding addSyntheticFieldForInnerclass(ReferenceBinding enclosingType) {
 
 	if (synthetics == null) {
-		synthetics = new Hashtable[4];
+		synthetics = new HashMap[4];
 	}
 	if (synthetics[FIELD_EMUL] == null) {
-		synthetics[FIELD_EMUL] = new Hashtable(5);
+		synthetics[FIELD_EMUL] = new HashMap(5);
 	}
 
 	FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get(enclosingType);
 	if (synthField == null) {
 		synthField = new SyntheticFieldBinding(
 			CharOperation.concat(
-				SyntheticArgumentBinding.EnclosingInstancePrefix,
+				TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX,
 				String.valueOf(enclosingType.depth()).toCharArray()),
 			enclosingType,
 			AccDefault | AccFinal | AccSynthetic,
@@ -197,20 +201,22 @@
 *	Answer the new field or the existing field if one already existed.
 */
 
-public FieldBinding addSyntheticField(TypeBinding targetType, BlockScope blockScope) {
+public FieldBinding addSyntheticFieldForClassLiteral(TypeBinding targetType, BlockScope blockScope) {
 
 	if (synthetics == null) {
-		synthetics = new Hashtable[4];
+		synthetics = new HashMap[4];
 	}
 	if (synthetics[CLASS_LITERAL_EMUL] == null) {
-		synthetics[CLASS_LITERAL_EMUL] = new Hashtable(5);
+		synthetics[CLASS_LITERAL_EMUL] = new HashMap(5);
 	}
 
 	// use a different table than FIELDS, given there might be a collision between emulation of X.this$0 and X.class.
 	FieldBinding synthField = (FieldBinding) synthetics[CLASS_LITERAL_EMUL].get(targetType);
 	if (synthField == null) {
 		synthField = new SyntheticFieldBinding(
-			("class$" + synthetics[CLASS_LITERAL_EMUL].size()).toCharArray(), //$NON-NLS-1$
+			CharOperation.concat(
+				TypeConstants.SYNTHETIC_CLASS,
+				String.valueOf(synthetics[CLASS_LITERAL_EMUL].size()).toCharArray()),
 			blockScope.getJavaLangClass(),
 			AccDefault | AccStatic | AccSynthetic,
 			this,
@@ -236,19 +242,19 @@
 /* Add a new synthetic field for the emulation of the assert statement.
 *	Answer the new field or the existing field if one already existed.
 */
-public FieldBinding addSyntheticField(AssertStatement assertStatement, BlockScope blockScope) {
+public FieldBinding addSyntheticFieldForAssert(BlockScope blockScope) {
 
 	if (synthetics == null) {
-		synthetics = new Hashtable[4];
+		synthetics = new HashMap[4];
 	}
 	if (synthetics[FIELD_EMUL] == null) {
-		synthetics[FIELD_EMUL] = new Hashtable(5);
+		synthetics[FIELD_EMUL] = new HashMap(5);
 	}
 
 	FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get("assertionEmulation"); //$NON-NLS-1$
 	if (synthField == null) {
 		synthField = new SyntheticFieldBinding(
-			"$assertionsDisabled".toCharArray(), //$NON-NLS-1$
+			TypeConstants.SYNTHETIC_ASSERT_DISABLED,
 			BooleanBinding,
 			AccDefault | AccStatic | AccSynthetic | AccFinal,
 			this,
@@ -269,7 +275,54 @@
 				FieldDeclaration fieldDecl = typeDecl.fields[i];
 				if (fieldDecl.binding == existingField) {
 					synthField.name = CharOperation.concat(
-						"$assertionsDisabled".toCharArray(), //$NON-NLS-1$
+						TypeConstants.SYNTHETIC_ASSERT_DISABLED,
+						("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
+					needRecheck = true;
+					break;
+				}
+			}
+		}
+	} while (needRecheck);
+	return synthField;
+}
+
+/* Add a new synthetic field for recording all enum constant values
+*	Answer the new field or the existing field if one already existed.
+*/
+public FieldBinding addSyntheticFieldForEnumValues() {
+
+	if (synthetics == null) {
+		synthetics = new HashMap[4];
+	}
+	if (synthetics[FIELD_EMUL] == null) {
+		synthetics[FIELD_EMUL] = new HashMap(5);
+	}
+
+	FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get("enumConstantValues"); //$NON-NLS-1$
+	if (synthField == null) {
+		synthField = new SyntheticFieldBinding(
+			TypeConstants.SYNTHETIC_ENUM_VALUES,
+			scope.createArrayType(this,1),
+			AccPrivate | AccStatic | AccSynthetic | AccFinal,
+			this,
+			Constant.NotAConstant,
+			synthetics[FIELD_EMUL].size());
+		synthetics[FIELD_EMUL].put("enumConstantValues", synthField); //$NON-NLS-1$
+	}
+	// ensure there is not already such a field defined by the user
+	// ensure there is not already such a field defined by the user
+	boolean needRecheck;
+	int index = 0;
+	do {
+		needRecheck = false;
+		FieldBinding existingField;
+		if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
+			TypeDeclaration typeDecl = scope.referenceContext;
+			for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
+				FieldDeclaration fieldDecl = typeDecl.fields[i];
+				if (fieldDecl.binding == existingField) {
+					synthField.name = CharOperation.concat(
+						TypeConstants.SYNTHETIC_ENUM_VALUES,
 						("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
 					needRecheck = true;
 					break;
@@ -284,64 +337,184 @@
 	Answer the new method or the existing method if one already existed.
 */
 
-public SyntheticAccessMethodBinding addSyntheticMethod(FieldBinding targetField, boolean isReadAccess) {
+public SyntheticMethodBinding addSyntheticMethod(FieldBinding targetField, boolean isReadAccess) {
 
 	if (synthetics == null) {
-		synthetics = new Hashtable[4];
+		synthetics = new HashMap[4];
 	}
 	if (synthetics[METHOD_EMUL] == null) {
-		synthetics[METHOD_EMUL] = new Hashtable(5);
+		synthetics[METHOD_EMUL] = new HashMap(5);
 	}
 
-	SyntheticAccessMethodBinding accessMethod = null;
-	SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(targetField);
+	SyntheticMethodBinding accessMethod = null;
+	SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(targetField);
 	if (accessors == null) {
-		accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
-		synthetics[METHOD_EMUL].put(targetField, accessors = new SyntheticAccessMethodBinding[2]);
+		accessMethod = new SyntheticMethodBinding(targetField, isReadAccess, this);
+		synthetics[METHOD_EMUL].put(targetField, accessors = new SyntheticMethodBinding[2]);
 		accessors[isReadAccess ? 0 : 1] = accessMethod;		
 	} else {
 		if ((accessMethod = accessors[isReadAccess ? 0 : 1]) == null) {
-			accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
+			accessMethod = new SyntheticMethodBinding(targetField, isReadAccess, this);
 			accessors[isReadAccess ? 0 : 1] = accessMethod;
 		}
 	}
 	return accessMethod;
 }
+/* Add a new synthetic method the enum type. Selector can either be 'values' or 'valueOf'.
+ * char[] constants from TypeConstants must be used: TypeConstants.VALUES/VALUEOF
+*/
+
+public SyntheticMethodBinding addSyntheticEnumMethod(char[] selector) {
+
+	if (synthetics == null) {
+		synthetics = new HashMap[4];
+	}
+	if (synthetics[METHOD_EMUL] == null) {
+		synthetics[METHOD_EMUL] = new HashMap(5);
+	}
+
+	SyntheticMethodBinding accessMethod = null;
+	SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(selector);
+	if (accessors == null) {
+		accessMethod = new SyntheticMethodBinding(this, selector);
+		synthetics[METHOD_EMUL].put(selector, accessors = new SyntheticMethodBinding[2]);
+		accessors[0] = accessMethod;		
+	} else {
+		if ((accessMethod = accessors[0]) == null) {
+			accessMethod = new SyntheticMethodBinding(this, selector);
+			accessors[0] = accessMethod;
+		}
+	}
+	return accessMethod;
+}
 /* Add a new synthetic access method for access to <targetMethod>.
  * Must distinguish access method used for super access from others (need to use invokespecial bytecode)
 	Answer the new method or the existing method if one already existed.
 */
 
-public SyntheticAccessMethodBinding addSyntheticMethod(MethodBinding targetMethod, boolean isSuperAccess) {
+public SyntheticMethodBinding addSyntheticMethod(MethodBinding targetMethod, boolean isSuperAccess) {
 
 	if (synthetics == null) {
-		synthetics = new Hashtable[4];
+		synthetics = new HashMap[4];
 	}
 	if (synthetics[METHOD_EMUL] == null) {
-		synthetics[METHOD_EMUL] = new Hashtable(5);
+		synthetics[METHOD_EMUL] = new HashMap(5);
 	}
 
-	SyntheticAccessMethodBinding accessMethod = null;
-	SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(targetMethod);
+	SyntheticMethodBinding accessMethod = null;
+	SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(targetMethod);
 	if (accessors == null) {
-		accessMethod = new SyntheticAccessMethodBinding(targetMethod, isSuperAccess, this);
-		synthetics[METHOD_EMUL].put(targetMethod, accessors = new SyntheticAccessMethodBinding[2]);
+		accessMethod = new SyntheticMethodBinding(targetMethod, isSuperAccess, this);
+		synthetics[METHOD_EMUL].put(targetMethod, accessors = new SyntheticMethodBinding[2]);
 		accessors[isSuperAccess ? 0 : 1] = accessMethod;		
 	} else {
 		if ((accessMethod = accessors[isSuperAccess ? 0 : 1]) == null) {
-			accessMethod = new SyntheticAccessMethodBinding(targetMethod, isSuperAccess, this);
+			accessMethod = new SyntheticMethodBinding(targetMethod, isSuperAccess, this);
 			accessors[isSuperAccess ? 0 : 1] = accessMethod;
 		}
 	}
 	return accessMethod;
 }
+/* 
+ * Record the fact that bridge methods need to be generated to override certain inherited methods
+ */
+public SyntheticMethodBinding addSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge, MethodBinding localTargetMethod) {
+	if (!isClass()) return null; // only classes get bridge methods
+	if (inheritedMethodToBridge.returnType.erasure() == localTargetMethod.returnType.erasure()
+		&& inheritedMethodToBridge.areParameterErasuresEqual(localTargetMethod)) {
+			return null; // do not need bridge method
+	}
+	if (synthetics == null) {
+		synthetics = new HashMap[4];
+	}
+	if (synthetics[METHOD_EMUL] == null) {
+		synthetics[METHOD_EMUL] = new HashMap(5);
+	} else {
+		// check to see if there is another equivalent inheritedMethod already added
+		Iterator synthMethods = synthetics[METHOD_EMUL].keySet().iterator();
+		while (synthMethods.hasNext()) {
+			Object synthetic = synthMethods.next();
+			if (synthetic instanceof MethodBinding) {
+				MethodBinding method = (MethodBinding) synthetic;
+				if (CharOperation.equals(inheritedMethodToBridge.selector, method.selector)
+					&& inheritedMethodToBridge.returnType.erasure() == method.returnType.erasure()
+					&& inheritedMethodToBridge.areParameterErasuresEqual(method)) {
+						return null;
+				}
+			}
+		}
+	}
 
-public FieldBinding[] availableFields() {
-	return fields();
+	SyntheticMethodBinding accessMethod = null;
+	SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(inheritedMethodToBridge);
+	if (accessors == null) {
+		accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, localTargetMethod);
+		synthetics[METHOD_EMUL].put(inheritedMethodToBridge, accessors = new SyntheticMethodBinding[2]);
+		accessors[1] = accessMethod;		
+	} else {
+		if ((accessMethod = accessors[1]) == null) {
+			accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, localTargetMethod);
+			accessors[1] = accessMethod;
+		}
+	}
+	return accessMethod;
 }
-public MethodBinding[] availableMethods() {
-	return methods();
+
+/**
+ * Collect the substitutes into a map for certain type variables inside the receiver type
+ * e.g.   Collection<T>.findSubstitute(T, Collection<List<X>>):   T --> List<X>
+ */
+public void collectSubstitutes(TypeBinding otherType, Map substitutes) {
+	if (otherType instanceof ReferenceBinding) {
+		TypeVariableBinding[] variables = this.typeVariables;
+		if (variables == NoTypeVariables) return;
+		// generic type is acting as parameterized type with its own parameters as arguments
+		
+		// allow List<T> to match with LinkedList<String>
+		ReferenceBinding equivalent = this;
+        ReferenceBinding otherEquivalent = ((ReferenceBinding)otherType).findSuperTypeErasingTo(this);
+        if (otherEquivalent == null) {
+        	// allow LinkedList<String> to match List<T> (downcast scenario)
+	    	equivalent = this.findSuperTypeErasingTo((ReferenceBinding)otherType.erasure());
+        	if (equivalent == null) return;
+        	otherEquivalent = (ReferenceBinding)otherType;
+        }
+        TypeBinding[] elements;
+        switch (equivalent.kind()) {
+        	case Binding.GENERIC_TYPE :
+        		elements = equivalent.typeVariables();
+        		break;
+        	case Binding.PARAMETERIZED_TYPE :
+        		elements = ((ParameterizedTypeBinding)equivalent).arguments;
+        		break;
+        	default :
+        		return;
+        }
+        TypeBinding[] otherElements;
+        switch (otherEquivalent.kind()) {
+        	case Binding.GENERIC_TYPE :
+        		otherElements = otherEquivalent.typeVariables();
+        		break;
+        	case Binding.PARAMETERIZED_TYPE :
+        		otherElements = ((ParameterizedTypeBinding)otherEquivalent).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 = elements.length; i < length; i++) {
+            elements[i].collectSubstitutes(otherElements[i], substitutes);
+        }
+    }
 }
+	
+public int kind() {
+	if (this.typeVariables != NoTypeVariables) return Binding.GENERIC_TYPE;
+	return Binding.TYPE;
+}	
+
 void faultInTypesForFieldsAndMethods() {
 	fields();
 	methods();
@@ -349,48 +522,104 @@
 	for (int i = 0, length = memberTypes.length; i < length; i++)
 		((SourceTypeBinding) memberTypes[i]).faultInTypesForFieldsAndMethods();
 }
-// NOTE: the type of each field of a source type is resolved when needed
 
+// NOTE: the type of each field of a source type is resolved when needed
 public FieldBinding[] fields() {
-	
+	int failed = 0;
 	try {
-		int failed = 0;
-		for (int f = 0, max = fields.length; f < max; f++) {
-			if (resolveTypeFor(fields[f]) == null) {
-				fields[f] = null;
+		for (int i = 0, length = fields.length; i < length; i++) {
+			if (resolveTypeFor(fields[i]) == null) {
+				fields[i] = null;
 				failed++;
 			}
 		}
+	} finally {
 		if (failed > 0) {
+			// ensure fields are consistent reqardless of the error
 			int newSize = fields.length - failed;
 			if (newSize == 0)
 				return fields = NoFields;
 	
 			FieldBinding[] newFields = new FieldBinding[newSize];
-			for (int i = 0, n = 0, max = fields.length; i < max; i++)
+			for (int i = 0, j = 0, length = fields.length; i < length; i++)
 				if (fields[i] != null)
-					newFields[n++] = fields[i];
+					newFields[j++] = fields[i];
 			fields = newFields;
 		}
-	} catch(AbortCompilation e){
-		// ensure null fields are removed
-		FieldBinding[] newFields = null;
-		int count = 0;
-		for (int i = 0, max = fields.length; i < max; i++){
-			FieldBinding field = fields[i];
-			if (field == null && newFields == null){
-				System.arraycopy(fields, 0, newFields = new FieldBinding[max], 0, i);
-			} else if (newFields != null && field != null) {
-				newFields[count++] = field;
-			}
-		}
-		if (newFields != null){
-			System.arraycopy(newFields, 0, fields = new FieldBinding[count], 0, count);
-		}			
-		throw e;
 	}
 	return fields;
 }
+/**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#genericTypeSignature()
+ */
+public char[] genericTypeSignature() {
+    if (this.genericReferenceTypeSignature == null) {
+        if (this.typeVariables == NoTypeVariables) {
+	        this.genericReferenceTypeSignature = this.signature();
+        } else {
+		    char[] typeSig = this.signature();
+		    StringBuffer sig = new StringBuffer(10);
+		    for (int i = 0; i < typeSig.length-1; i++) { // copy all but trailing semicolon
+		    	sig.append(typeSig[i]);
+		    }
+		    sig.append('<');
+		    for (int i = 0, length = this.typeVariables.length; i < length; i++) {
+		        sig.append(this.typeVariables[i].genericTypeSignature());
+		    }
+		    sig.append(">;"); //$NON-NLS-1$
+			int sigLength = sig.length();
+			this.genericReferenceTypeSignature = new char[sigLength];
+			sig.getChars(0, sigLength, this.genericReferenceTypeSignature, 0);		    
+	    }
+    }
+    return this.genericReferenceTypeSignature;
+}
+/**
+ * <param1 ... paramN>superclass superinterface1 ... superinterfaceN
+ * <T:LY<TT;>;U:Ljava/lang/Object;V::Ljava/lang/Runnable;:Ljava/lang/Cloneable;:Ljava/util/Map;>Ljava/lang/Exception;Ljava/lang/Runnable;
+ */
+public char[] genericSignature() {
+    StringBuffer sig = null;
+	if (this.typeVariables != NoTypeVariables) {
+	    sig = new StringBuffer(10);
+	    sig.append('<');
+	    for (int i = 0, length = this.typeVariables.length; i < length; i++) {
+	        sig.append(this.typeVariables[i].genericSignature());
+	    }
+	    sig.append('>');
+	} else {
+	    // could still need a signature if any of supertypes is parameterized
+	    noSignature: if (this.superclass == null || !this.superclass.isParameterizedType()) {
+		    for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
+		        if (this.superInterfaces[i].isParameterizedType()) break noSignature;
+		    }        
+	        return null;
+	    }
+	    sig = new StringBuffer(10);
+	}
+	if (this.superclass != null) {
+		sig.append(this.superclass.genericTypeSignature());
+	} else {
+		// interface scenario only (as Object cannot be generic) - 65953
+		sig.append(scope.getJavaLangObject().genericTypeSignature());
+	}
+    for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
+        sig.append(this.superInterfaces[i].genericTypeSignature());
+    }
+	return sig.toString().toCharArray();
+}
+/**
+ * Compute the tagbits for standard annotations. For source types, these could require
+ * lazily resolving corresponding annotation nodes, in case of forward references.
+ * @see org.eclipse.jdt.internal.compiler.lookup.Binding#getAnnotationTagBits()
+ */
+public long getAnnotationTagBits() {
+	if ((this.tagBits & AnnotationResolved) == 0) {
+		TypeDeclaration typeDecl = this.scope.referenceContext;
+		ASTNode.resolveAnnotations(typeDecl.staticInitializerScope, typeDecl.annotations, this);
+	}
+	return this.tagBits;
+}
 public MethodBinding[] getDefaultAbstractMethods() {
 	int count = 0;
 	for (int i = methods.length; --i >= 0;)
@@ -413,7 +642,7 @@
 	if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
 		nextMethod : for (int m = methods.length; --m >= 0;) {
 			MethodBinding method = methods[m];
-			if (method.selector == ConstructorDeclaration.ConstantPoolName && method.parameters.length == argCount) {
+			if (method.selector == TypeConstants.INIT && method.parameters.length == argCount) {
 				TypeBinding[] toMatch = method.parameters;
 				for (int p = 0; p < argCount; p++)
 					if (toMatch[p] != argumentTypes[p])
@@ -422,7 +651,7 @@
 			}
 		}
 	} else {
-		MethodBinding[] constructors = getMethods(ConstructorDeclaration.ConstantPoolName); // takes care of duplicates & default abstract methods
+		MethodBinding[] constructors = getMethods(TypeConstants.INIT); // takes care of duplicates & default abstract methods
 		nextConstructor : for (int c = constructors.length; --c >= 0;) {
 			MethodBinding constructor = constructors[c];
 			TypeBinding[] toMatch = constructor.parameters;
@@ -439,7 +668,8 @@
 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
 // searches up the hierarchy as long as no potential (but not exact) match was found.
 
-public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes) {
+public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
+	// sender from refScope calls recordTypeReference(this)
 	int argCount = argumentTypes.length;
 	int selectorLength = selector.length;
 	boolean foundNothing = true;
@@ -475,152 +705,86 @@
 
 	if (foundNothing) {
 		if (isInterface()) {
-			 if (superInterfaces.length == 1)
-				return superInterfaces[0].getExactMethod(selector, argumentTypes);
+			 if (superInterfaces.length == 1) {
+				if (refScope != null)
+					refScope.recordTypeReference(superInterfaces[0]);
+				return superInterfaces[0].getExactMethod(selector, argumentTypes, refScope);
+			 }
 		} else if (superclass != null) {
-			return superclass.getExactMethod(selector, argumentTypes);
+			if (refScope != null)
+				refScope.recordTypeReference(superclass);
+			return superclass.getExactMethod(selector, argumentTypes, refScope);
 		}
 	}
 	return null;
 }
-// NOTE: the type of a field of a source type is resolved when needed
 
+// NOTE: the type of a field of a source type is resolved when needed
 public FieldBinding getField(char[] fieldName, boolean needResolve) {
 	// always resolve anyway on source types
 	int fieldLength = fieldName.length;
-	for (int f = fields.length; --f >= 0;) {
-		FieldBinding field = fields[f];
+	for (int i = 0, length = fields.length; i < length; i++) {
+		FieldBinding field = fields[i];
 		if (field.name.length == fieldLength && CharOperation.equals(field.name, fieldName)) {
-			if (resolveTypeFor(field) != null)
-				return field;
-
-			int newSize = fields.length - 1;
-			if (newSize == 0) {
-				fields = NoFields;
-			} else {
-				FieldBinding[] newFields = new FieldBinding[newSize];
-				System.arraycopy(fields, 0, newFields, 0, f);
-				System.arraycopy(fields, f + 1, newFields, f, newSize - f);
-				fields = newFields;
+			FieldBinding result = null;
+			try {
+				result = resolveTypeFor(field);
+				return result;
+			} finally {
+				if (result == null) {
+					// ensure fields are consistent reqardless of the error
+					int newSize = fields.length - 1;
+					if (newSize == 0) {
+						fields = NoFields;
+					} else {
+						FieldBinding[] newFields = new FieldBinding[newSize];
+						System.arraycopy(fields, 0, newFields, 0, i);
+						System.arraycopy(fields, i + 1, newFields, i, newSize - i);
+						fields = newFields;
+					}
+				}
 			}
-			return null;
 		}
 	}
 	return null;
 }
+
 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
-
 public MethodBinding[] getMethods(char[] selector) {
-	// handle forward references to potential default abstract methods
-	addDefaultAbstractMethods();
+	int selectorLength = selector.length;
+	boolean methodsAreResolved = (modifiers & AccUnresolved) == 0; // have resolved all arg types & return type of the methods
+	java.util.ArrayList matchingMethods = null;
+	for (int i = 0, length = methods.length; i < length; i++) {
+		MethodBinding method = methods[i];
+		if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
+			if (!methodsAreResolved && resolveTypesFor(method) == null || method.returnType == null) {
+				methods();
+				return getMethods(selector); // try again since the problem methods have been removed
+			}
+			if (matchingMethods == null)
+				matchingMethods = new java.util.ArrayList(2);
+			matchingMethods.add(method);
+		}
+	}
+	if (matchingMethods == null) return NoMethods;
 
-	try{
-		int count = 0;
-		int lastIndex = -1;
-		int selectorLength = selector.length;
-		if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
-			for (int m = 0, length = methods.length; m < length; m++) {
-				MethodBinding method = methods[m];
-				if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
-					count++;
-					lastIndex = m;
-				}
-			}
-		} else {
-			boolean foundProblem = false;
-			int failed = 0;
-			for (int m = 0, length = methods.length; m < length; m++) {
-				MethodBinding method = methods[m];
-				if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
-					if (resolveTypesFor(method) == null) {
-						foundProblem = true;
-						methods[m] = null; // unable to resolve parameters
-						failed++;
-					} else if (method.returnType == null) {
-						foundProblem = true;
-					} else {
-						count++;
-						lastIndex = m;
-					}
-				}
-			}
-	
-			if (foundProblem || count > 1) {
-				for (int m = methods.length; --m >= 0;) {
-					MethodBinding method = methods[m];
-					if (method != null && method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
-						AbstractMethodDeclaration methodDecl = null;
-						for (int i = 0; i < m; i++) {
-							MethodBinding method2 = methods[i];
-							if (method2 != null && CharOperation.equals(method.selector, method2.selector)) {
-								if (method.areParametersEqual(method2)) {
-									if (methodDecl == null) {
-										methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost
-										scope.problemReporter().duplicateMethodInType(this, methodDecl);
-										methodDecl.binding = null;
-										methods[m] = null;
-										failed++;
-									}
-									scope.problemReporter().duplicateMethodInType(this, method2.sourceMethod());
-									method2.sourceMethod().binding = null;
-									methods[i] = null;
-									failed++;
-								}
-							}
-						}
-						if (method.returnType == null && methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions
-							method.sourceMethod().binding = null;
-							methods[m] = null;
-							failed++;
-						}
-					}
-				}
-	
-				if (failed > 0) {
-					int newSize = methods.length - failed;
-					if (newSize == 0)
-						return methods = NoMethods;
-	
-					MethodBinding[] newMethods = new MethodBinding[newSize];
-					for (int i = 0, n = 0, max = methods.length; i < max; i++)
-						if (methods[i] != null)
-							newMethods[n++] = methods[i];
-					methods = newMethods;
-					return getMethods(selector); // try again now that the problem methods have been removed
+	MethodBinding[] result = new MethodBinding[matchingMethods.size()];
+	matchingMethods.toArray(result);
+	if (!methodsAreResolved) {
+		for (int i = 0, length = result.length - 1; i < length; i++) {
+			MethodBinding method = result[i];
+			for (int j = length; j > i; j--) {
+				boolean paramsMatch = fPackage.environment.options.sourceLevel >= ClassFileConstants.JDK1_5
+					? method.areParameterErasuresEqual(result[j])
+					: method.areParametersEqual(result[j]);
+				if (paramsMatch) {
+					methods();
+					return getMethods(selector); // try again since the duplicate methods have been removed
 				}
 			}
 		}
-		if (count == 1)
-			return new MethodBinding[] {methods[lastIndex]};
-		if (count > 1) {
-			MethodBinding[] result = new MethodBinding[count];
-			count = 0;
-			for (int m = 0; m <= lastIndex; m++) {
-				MethodBinding method = methods[m];
-				if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector))
-					result[count++] = method;
-			}
-			return result;
-		}
-	} catch(AbortCompilation e){
-		// ensure null methods are removed
-		MethodBinding[] newMethods = null;
-		int count = 0;
-		for (int i = 0, max = methods.length; i < max; i++){
-			MethodBinding method = methods[i];
-			if (method == null && newMethods == null){
-				System.arraycopy(methods, 0, newMethods = new MethodBinding[max], 0, i);
-			} else if (newMethods != null && method != null) {
-				newMethods[count++] = method;
-			}
-		}
-		if (newMethods != null){
-			System.arraycopy(newMethods, 0, methods = new MethodBinding[count], 0, count);
-		}			
-		modifiers ^= AccUnresolved;
-		throw e;
-	}		
-	return NoMethods;
+	}
+	return result;
 }
 /* Answer the synthetic field for <actualOuterLocalVariable>
 *	or null if one does not exist.
@@ -631,16 +795,72 @@
 	if (synthetics == null || synthetics[FIELD_EMUL] == null) return null;
 	return (FieldBinding) synthetics[FIELD_EMUL].get(actualOuterLocalVariable);
 }
+/* 
+ * Answer the bridge method associated for an  inherited methods or null if one does not exist
+ */
+public SyntheticMethodBinding getSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge) {
+    
+	if (synthetics == null) return null;
+	if (synthetics[METHOD_EMUL] == null) return null;
+	SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(inheritedMethodToBridge);
+	if (accessors == null) return null;
+	return accessors[1];
+}
+/**
+ * Returns true if a type is identical to another one,
+ * or for generic types, true if compared to its raw type.
+ */
+public boolean isEquivalentTo(TypeBinding otherType) {
+
+	if (this == otherType) return true;
+    if (otherType == null) return false;
+    switch(otherType.kind()) {
+
+    	case Binding.WILDCARD_TYPE :
+			return ((WildcardBinding) otherType).boundCheck(this);
+    	
+    	case Binding.PARAMETERIZED_TYPE :
+	        if ((otherType.tagBits & HasDirectWildcard) == 0 && (!this.isMemberType() || !otherType.isMemberType())) 
+	        	return false; // should have been identical
+	        ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType;
+	        if (this != otherParamType.type) 
+	            return false;
+            if (!isStatic()) { // static member types do not compare their enclosing
+		        ReferenceBinding enclosing = enclosingType();
+		        if (enclosing != null && !enclosing.isEquivalentTo(otherParamType.enclosingType()))
+		            return false;
+            }
+	        int length = this.typeVariables == null ? 0 : this.typeVariables.length;
+	        TypeBinding[] otherArguments = otherParamType.arguments;
+	        int otherLength = otherArguments == null ? 0 : otherArguments.length;
+	        if (otherLength != length) 
+	            return false;
+	        for (int i = 0; i < length; i++) {
+	        	if (!this.typeVariables[i].isTypeArgumentContainedBy(otherArguments[i]))
+					return false;
+	        }
+	        return true;
+    	
+    	case Binding.RAW_TYPE :
+	        return otherType.erasure() == this;
+    }
+	return false;
+}
+	
+public boolean isGenericType() {
+    return this.typeVariables != NoTypeVariables;
+}
+
 public ReferenceBinding[] memberTypes() {
 	return this.memberTypes;
 }
 public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) {
 
 	if (this.synthetics == null) {
-		this.synthetics = new Hashtable[4];
+		this.synthetics = new HashMap[4];
 	}
 	if (this.synthetics[RECEIVER_TYPE_EMUL] == null) {
-		this.synthetics[RECEIVER_TYPE_EMUL] = new Hashtable(5);
+		this.synthetics[RECEIVER_TYPE_EMUL] = new HashMap(5);
 	}
 
 	Hashtable fieldMap = (Hashtable) this.synthetics[RECEIVER_TYPE_EMUL].get(targetField);
@@ -659,10 +879,10 @@
 public MethodBinding getUpdatedMethodBinding(MethodBinding targetMethod, ReferenceBinding newDeclaringClass) {
 
 	if (this.synthetics == null) {
-		this.synthetics = new Hashtable[4];
+		this.synthetics = new HashMap[4];
 	}
 	if (this.synthetics[RECEIVER_TYPE_EMUL] == null) {
-		this.synthetics[RECEIVER_TYPE_EMUL] = new Hashtable(5);
+		this.synthetics[RECEIVER_TYPE_EMUL] = new HashMap(5);
 	}
 
 
@@ -683,82 +903,83 @@
 }
 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
 public MethodBinding[] methods() {
+	if ((modifiers & AccUnresolved) == 0)
+		return methods;
+
+	int failed = 0;
 	try {
-		if ((modifiers & AccUnresolved) == 0)
-			return methods;
-	
-		int failed = 0;
-		for (int m = 0, max = methods.length; m < max; m++) {
-			if (resolveTypesFor(methods[m]) == null) {
-				methods[m] = null; // unable to resolve parameters
+		for (int i = 0, length = methods.length; i < length; i++) {
+			if (resolveTypesFor(methods[i]) == null) {
+				methods[i] = null; // unable to resolve parameters
 				failed++;
 			}
 		}
-	
-		for (int m = methods.length; --m >= 0;) {
-			MethodBinding method = methods[m];
+
+		// find & report collision cases
+		for (int i = 0, length = methods.length; i < length; i++) {
+			MethodBinding method = methods[i];
 			if (method != null) {
 				AbstractMethodDeclaration methodDecl = null;
-				for (int i = 0; i < m; i++) {
-					MethodBinding method2 = methods[i];
+				for (int j = length - 1; j > i; j--) {
+					MethodBinding method2 = methods[j];
 					if (method2 != null && CharOperation.equals(method.selector, method2.selector)) {
-						if (method.areParametersEqual(method2)) {
+						boolean paramsMatch = fPackage.environment.options.sourceLevel >= ClassFileConstants.JDK1_5
+							? method.areParameterErasuresEqual(method2)
+							: method.areParametersEqual(method2);
+						if (paramsMatch) {
+							boolean isEnumSpecialMethod = isEnum()
+								&& (method.selector == TypeConstants.VALUEOF || method.selector == TypeConstants.VALUES);
 							if (methodDecl == null) {
-								methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost
-								scope.problemReporter().duplicateMethodInType(this, methodDecl);
-								methodDecl.binding = null;
-								methods[m] = null;
+								methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost & may still be null if method is special
+								if (methodDecl != null && methodDecl.binding != null) { // ensure its a valid user defined method
+									if (isEnumSpecialMethod)
+										scope.problemReporter().duplicateEnumSpecialMethod(this, methodDecl);
+									else
+										scope.problemReporter().duplicateMethodInType(this, methodDecl);
+									methodDecl.binding = null;
+									methods[i] = null;
+									failed++;
+								}
+							}
+							AbstractMethodDeclaration method2Decl = method2.sourceMethod();
+							if (method2Decl != null && method2Decl.binding != null) { // ensure its a valid user defined method
+								if (isEnumSpecialMethod)
+									scope.problemReporter().duplicateEnumSpecialMethod(this, method2Decl);
+								else
+									scope.problemReporter().duplicateMethodInType(this, method2Decl);
+								method2Decl.binding = null;
+								methods[j] = null;
 								failed++;
 							}
-							scope.problemReporter().duplicateMethodInType(this, method2.sourceMethod());
-							method2.sourceMethod().binding = null;
-							methods[i] = null;
-							failed++;
 						}
 					}
 				}
 				if (method.returnType == null && methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions
 					method.sourceMethod().binding = null;
-					methods[m] = null;
+					methods[i] = null;
 					failed++;
 				}
 			}
 		}
-	
+	} finally {
 		if (failed > 0) {
 			int newSize = methods.length - failed;
 			if (newSize == 0) {
 				methods = NoMethods;
 			} else {
 				MethodBinding[] newMethods = new MethodBinding[newSize];
-				for (int m = 0, n = 0, max = methods.length; m < max; m++)
-					if (methods[m] != null)
-						newMethods[n++] = methods[m];
+				for (int i = 0, j = 0, length = methods.length; i < length; i++)
+					if (methods[i] != null)
+						newMethods[j++] = methods[i];
 				methods = newMethods;
 			}
 		}
-	
+
 		// handle forward references to potential default abstract methods
 		addDefaultAbstractMethods();
-	} catch(AbortCompilation e){
-		// ensure null methods are removed
-		MethodBinding[] newMethods = null;
-		int count = 0;
-		for (int i = 0, max = methods.length; i < max; i++){
-			MethodBinding method = methods[i];
-			if (method == null && newMethods == null){
-				System.arraycopy(methods, 0, newMethods = new MethodBinding[max], 0, i);
-			} else if (newMethods != null && method != null) {
-				newMethods[count++] = method;
-			}
-		}
-		if (newMethods != null){
-			System.arraycopy(newMethods, 0, methods = new MethodBinding[count], 0, count);
-		}			
-		modifiers ^= AccUnresolved;
-		throw e;
+
+		modifiers &= ~AccUnresolved;
 	}		
-	modifiers ^= AccUnresolved;
 	return methods;
 }
 private FieldBinding resolveTypeFor(FieldBinding field) {
@@ -770,33 +991,59 @@
 		if (fieldDecls[f].binding != field)
 			continue;
 
-		field.type = fieldDecls[f].getTypeBinding(scope);
-		field.modifiers ^= AccUnresolved;
-		if (!field.type.isValidBinding()) {
-			scope.problemReporter().fieldTypeProblem(this, fieldDecls[f], field.type);
-			//scope.problemReporter().invalidType(fieldDecls[f].type, field.type);
-			fieldDecls[f].binding = null;
-			return null;
-		}
-		if (field.type == VoidBinding) {
-			scope.problemReporter().variableTypeCannotBeVoid(fieldDecls[f]);
-			fieldDecls[f].binding = null;
-			return null;
-		}
-		if (field.type.isArrayType() && ((ArrayBinding) field.type).leafComponentType == VoidBinding) {
-			scope.problemReporter().variableTypeCannotBeVoidArray(fieldDecls[f]);
-			fieldDecls[f].binding = null;
-			return null;
-		}
+			MethodScope initializationScope = field.isStatic() 
+				? scope.referenceContext.staticInitializerScope 
+				: scope.referenceContext.initializerScope;
+			FieldBinding previousField = initializationScope.initializedField;
+			try {
+				initializationScope.initializedField = field;
+				FieldDeclaration fieldDecl = fieldDecls[f];
+				TypeBinding fieldType = 
+					fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT
+						? this // enum constant is implicitly of declaring enum type
+						: fieldDecl.type.resolveType(initializationScope, true /* check bounds*/);
+				field.type = fieldType;
+				field.modifiers &= ~AccUnresolved;
+				if (fieldType == null) {
+					fieldDecls[f].binding = null;
+					return null;
+				}
+				if (fieldType == VoidBinding) {
+					scope.problemReporter().variableTypeCannotBeVoid(fieldDecls[f]);
+					fieldDecls[f].binding = null;
+					return null;
+				}
+				if (fieldType.isArrayType() && ((ArrayBinding) fieldType).leafComponentType == VoidBinding) {
+					scope.problemReporter().variableTypeCannotBeVoidArray(fieldDecls[f]);
+					fieldDecls[f].binding = null;
+					return null;
+				}
+				if (fieldType instanceof ReferenceBinding && (((ReferenceBinding)fieldType).modifiers & AccGenericSignature) != 0) {
+					field.modifiers |= AccGenericSignature;
+				}				
+			} finally {
+			    initializationScope.initializedField = previousField;
+			}
 		return field;
 	}
 	return null; // should never reach this point
 }
 private MethodBinding resolveTypesFor(MethodBinding method) {
+    
 	if ((method.modifiers & AccUnresolved) == 0)
 		return method;
 
 	AbstractMethodDeclaration methodDecl = method.sourceMethod();
+	if (methodDecl == null) return null; // method could not be resolved in previous iteration
+	
+	TypeParameter[] typeParameters = methodDecl.typeParameters();
+	if (typeParameters != null) {
+		methodDecl.scope.connectTypeVariables(typeParameters);
+		// Perform deferred bound checks for type variables (only done after type variable hierarchy is connected)
+		for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++) {
+			typeParameters[i].checkBounds(methodDecl.scope);
+		}
+	}
 	TypeReference[] exceptionTypes = methodDecl.thrownExceptions;
 	if (exceptionTypes != null) {
 		int size = exceptionTypes.length;
@@ -805,16 +1052,21 @@
 		int count = 0;
 		ReferenceBinding resolvedExceptionType;
 		for (int i = 0; i < size; i++) {
-			resolvedExceptionType = (ReferenceBinding) exceptionTypes[i].getTypeBinding(scope);
-			if (!resolvedExceptionType.isValidBinding()) {
-				methodDecl.scope.problemReporter().exceptionTypeProblem(this, methodDecl, exceptionTypes[i], resolvedExceptionType);
-				//methodDecl.scope.problemReporter().invalidType(exceptionTypes[i], resolvedExceptionType);
+			resolvedExceptionType = (ReferenceBinding) exceptionTypes[i].resolveType(methodDecl.scope, true /* check bounds*/);
+			if (resolvedExceptionType == null) {
+				continue;
+			}
+			if (resolvedExceptionType.isGenericType() || resolvedExceptionType.isParameterizedType()) {
+				methodDecl.scope.problemReporter().invalidParameterizedExceptionType(resolvedExceptionType, exceptionTypes[i]);
 				continue;
 			}
 			if (throwable != resolvedExceptionType && !throwable.isSuperclassOf(resolvedExceptionType)) {
 				methodDecl.scope.problemReporter().cannotThrowType(this, methodDecl, exceptionTypes[i], resolvedExceptionType);
 				continue;
 			}
+		    if ((resolvedExceptionType.modifiers & AccGenericSignature) != 0) {
+				method.modifiers |= AccGenericSignature;
+			}
 			method.thrownExceptions[count++] = resolvedExceptionType;
 		}
 		if (count < size)
@@ -828,50 +1080,63 @@
 		method.parameters = new TypeBinding[size];
 		for (int i = 0; i < size; i++) {
 			Argument arg = arguments[i];
-			method.parameters[i] = arg.type.getTypeBinding(scope);
-			if (!method.parameters[i].isValidBinding()) {
-				methodDecl.scope.problemReporter().argumentTypeProblem(this, methodDecl, arg, method.parameters[i]);
-				//methodDecl.scope.problemReporter().invalidType(arg, method.parameters[i]);
+			TypeBinding parameterType = arg.type.resolveType(methodDecl.scope, true /* check bounds*/);
+			if (parameterType == null) {
 				foundArgProblem = true;
-			} else if (method.parameters[i] == VoidBinding) {
+			} else if (parameterType == VoidBinding) {
 				methodDecl.scope.problemReporter().argumentTypeCannotBeVoid(this, methodDecl, arg);
 				foundArgProblem = true;
-			} else if (method.parameters[i].isArrayType() && ((ArrayBinding) method.parameters[i]).leafComponentType == VoidBinding) {
+			} else if (parameterType.isArrayType() && ((ArrayBinding) parameterType).leafComponentType == VoidBinding) {
 				methodDecl.scope.problemReporter().argumentTypeCannotBeVoidArray(this, methodDecl, arg);
 				foundArgProblem = true;
+			} else {
+			    if (parameterType instanceof ReferenceBinding && (((ReferenceBinding)parameterType).modifiers & AccGenericSignature) != 0) {
+					method.modifiers |= AccGenericSignature;
+				}
+				method.parameters[i] = parameterType;
 			}
 		}
 	}
 
 	boolean foundReturnTypeProblem = false;
 	if (!method.isConstructor()) {
-		TypeReference returnType = ((MethodDeclaration) methodDecl).returnType;
+		TypeReference returnType = methodDecl instanceof MethodDeclaration
+			? ((MethodDeclaration) methodDecl).returnType
+			: ((AnnotationMethodDeclaration) methodDecl).returnType;
 		if (returnType == null) {
 			methodDecl.scope.problemReporter().missingReturnType(methodDecl);
 			method.returnType = null;
 			foundReturnTypeProblem = true;
 		} else {
-			method.returnType = returnType.getTypeBinding(scope);
-			if (!method.returnType.isValidBinding()) {
-				methodDecl.scope.problemReporter().returnTypeProblem(this, (MethodDeclaration) methodDecl, method.returnType);
-				//methodDecl.scope.problemReporter().invalidType(returnType, method.returnType);
-				method.returnType = null;
+		    TypeBinding methodType = returnType.resolveType(methodDecl.scope, true /* check bounds*/);
+			if (methodType == null) {
 				foundReturnTypeProblem = true;
-			} else if (method.returnType.isArrayType() && ((ArrayBinding) method.returnType).leafComponentType == VoidBinding) {
+			} else if (methodType.isArrayType() && ((ArrayBinding) methodType).leafComponentType == VoidBinding) {
 				methodDecl.scope.problemReporter().returnTypeCannotBeVoidArray(this, (MethodDeclaration) methodDecl);
-				method.returnType = null;
 				foundReturnTypeProblem = true;
+			} else {
+				method.returnType = methodType;
+				if (methodType instanceof ReferenceBinding && (((ReferenceBinding)methodType).modifiers & AccGenericSignature) != 0) {
+					method.modifiers |= AccGenericSignature;
+				}
 			}
 		}
 	}
 	if (foundArgProblem) {
 		methodDecl.binding = null;
+		// nullify type parameter bindings as well as they have a backpointer to the method binding
+		// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=81134)
+		if (typeParameters != null)
+			for (int i = 0, length = typeParameters.length; i < length; i++) {
+				TypeParameter parameter = typeParameters[i];
+				parameter.binding = null;
+			}
 		return null;
 	}
 	if (foundReturnTypeProblem)
 		return method; // but its still unresolved with a null return type & is still connected to its method declaration
 
-	method.modifiers ^= AccUnresolved;
+	method.modifiers &= ~AccUnresolved;
 	return method;
 }
 public final int sourceEnd() {
@@ -886,39 +1151,40 @@
 public ReferenceBinding[] superInterfaces() {
 	return superInterfaces;
 }
-public SyntheticAccessMethodBinding[] syntheticAccessMethods() {
+// TODO (philippe) could be a performance issue since some senders are building the list just to count them
+public SyntheticMethodBinding[] syntheticMethods() {
 	
 	if (synthetics == null || synthetics[METHOD_EMUL] == null || synthetics[METHOD_EMUL].size() == 0) return null;
 
 	// difficult to compute size up front because of the embedded arrays so assume there is only 1
 	int index = 0;
-	SyntheticAccessMethodBinding[] bindings = new SyntheticAccessMethodBinding[1];
-	Enumeration fieldsOrMethods = synthetics[METHOD_EMUL].keys();
-	while (fieldsOrMethods.hasMoreElements()) {
+	SyntheticMethodBinding[] bindings = new SyntheticMethodBinding[1];
+	Iterator fieldsOrMethods = synthetics[METHOD_EMUL].keySet().iterator();
+	while (fieldsOrMethods.hasNext()) {
 
-		Object fieldOrMethod = fieldsOrMethods.nextElement();
+		Object fieldOrMethod = fieldsOrMethods.next();
 
 		if (fieldOrMethod instanceof MethodBinding) {
 
-			SyntheticAccessMethodBinding[] methodAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(fieldOrMethod);
+			SyntheticMethodBinding[] methodAccessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(fieldOrMethod);
 			int numberOfAccessors = 0;
 			if (methodAccessors[0] != null) numberOfAccessors++;
 			if (methodAccessors[1] != null) numberOfAccessors++;
 			if (index + numberOfAccessors > bindings.length)
-				System.arraycopy(bindings, 0, (bindings = new SyntheticAccessMethodBinding[index + numberOfAccessors]), 0, index);
+				System.arraycopy(bindings, 0, (bindings = new SyntheticMethodBinding[index + numberOfAccessors]), 0, index);
 			if (methodAccessors[0] != null) 
 				bindings[index++] = methodAccessors[0]; // super access 
 			if (methodAccessors[1] != null) 
-				bindings[index++] = methodAccessors[1]; // normal access
+				bindings[index++] = methodAccessors[1]; // normal access or bridge
 
 		} else {
 
-			SyntheticAccessMethodBinding[] fieldAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(fieldOrMethod);
+			SyntheticMethodBinding[] fieldAccessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(fieldOrMethod);
 			int numberOfAccessors = 0;
 			if (fieldAccessors[0] != null) numberOfAccessors++;
 			if (fieldAccessors[1] != null) numberOfAccessors++;
 			if (index + numberOfAccessors > bindings.length)
-				System.arraycopy(bindings, 0, (bindings = new SyntheticAccessMethodBinding[index + numberOfAccessors]), 0, index);
+				System.arraycopy(bindings, 0, (bindings = new SyntheticMethodBinding[index + numberOfAccessors]), 0, index);
 			if (fieldAccessors[0] != null) 
 				bindings[index++] = fieldAccessors[0]; // read access
 			if (fieldAccessors[1] != null) 
@@ -928,9 +1194,9 @@
 
 	// sort them in according to their own indexes
 	int length;
-	SyntheticAccessMethodBinding[] sortedBindings = new SyntheticAccessMethodBinding[length = bindings.length];
+	SyntheticMethodBinding[] sortedBindings = new SyntheticMethodBinding[length = bindings.length];
 	for (int i = 0; i < length; i++){
-		SyntheticAccessMethodBinding binding = bindings[i];
+		SyntheticMethodBinding binding = bindings[i];
 		sortedBindings[binding.index] = binding;
 	}
 	return sortedBindings;
@@ -950,89 +1216,108 @@
 
 	// add innerclass synthetics
 	if (synthetics[FIELD_EMUL] != null){
-		Enumeration elements = synthetics[FIELD_EMUL].elements();
+		Iterator elements = synthetics[FIELD_EMUL].values().iterator();
 		for (int i = 0; i < fieldSize; i++) {
-			SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
+			SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.next();
 			bindings[synthBinding.index] = synthBinding;
 		}
 	}
 	// add class literal synthetics
 	if (synthetics[CLASS_LITERAL_EMUL] != null){
-		Enumeration elements = synthetics[CLASS_LITERAL_EMUL].elements();
+		Iterator elements = synthetics[CLASS_LITERAL_EMUL].values().iterator();
 		for (int i = 0; i < literalSize; i++) {
-			SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
+			SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.next();
 			bindings[fieldSize+synthBinding.index] = synthBinding;
 		}
 	}
 	return bindings;
 }
 public String toString() {
-	String s = "(id="+(id == NoId ? "NoId" : (""+id) ) +")\n"; //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-4$ //$NON-NLS-1$
+    StringBuffer buffer = new StringBuffer(30);
+    buffer.append("(id="); //$NON-NLS-1$
+    if (id == NoId) 
+        buffer.append("NoId"); //$NON-NLS-1$
+    else 
+        buffer.append(id);
+    buffer.append(")\n"); //$NON-NLS-1$
+	if (isDeprecated()) buffer.append("deprecated "); //$NON-NLS-1$
+	if (isPublic()) buffer.append("public "); //$NON-NLS-1$
+	if (isProtected()) buffer.append("protected "); //$NON-NLS-1$
+	if (isPrivate()) buffer.append("private "); //$NON-NLS-1$
+	if (isAbstract() && isClass()) buffer.append("abstract "); //$NON-NLS-1$
+	if (isStatic() && isNestedType()) buffer.append("static "); //$NON-NLS-1$
+	if (isFinal()) buffer.append("final "); //$NON-NLS-1$
 
-	if (isDeprecated()) s += "deprecated "; //$NON-NLS-1$
-	if (isPublic()) s += "public "; //$NON-NLS-1$
-	if (isProtected()) s += "protected "; //$NON-NLS-1$
-	if (isPrivate()) s += "private "; //$NON-NLS-1$
-	if (isAbstract() && isClass()) s += "abstract "; //$NON-NLS-1$
-	if (isStatic() && isNestedType()) s += "static "; //$NON-NLS-1$
-	if (isFinal()) s += "final "; //$NON-NLS-1$
+	buffer.append(isInterface() ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
+	buffer.append((compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED TYPE"); //$NON-NLS-1$
 
-	s += isInterface() ? "interface " : "class "; //$NON-NLS-1$ //$NON-NLS-2$
-	s += (compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED TYPE"; //$NON-NLS-1$
-
-	s += "\n\textends "; //$NON-NLS-1$
-	s += (superclass != null) ? superclass.debugName() : "NULL TYPE"; //$NON-NLS-1$
+	if (this.typeVariables != null && this.typeVariables != NoTypeVariables) {
+		buffer.append("\n\t<"); //$NON-NLS-1$
+		for (int i = 0, length = this.typeVariables.length; i < length; i++) {
+			if (i  > 0)
+				buffer.append(", "); //$NON-NLS-1$
+			buffer.append((this.typeVariables[i] != null) ? this.typeVariables[i].toString() : "NULL TYPE VARIABLE"); //$NON-NLS-1$
+		}
+		buffer.append(">"); //$NON-NLS-1$
+	} else {
+		buffer.append("<NULL TYPE VARIABLES>"); //$NON-NLS-1$
+	}
+	buffer.append("\n\textends "); //$NON-NLS-1$
+	buffer.append((superclass != null) ? superclass.debugName() : "NULL TYPE"); //$NON-NLS-1$
 
 	if (superInterfaces != null) {
 		if (superInterfaces != NoSuperInterfaces) {
-			s += "\n\timplements : "; //$NON-NLS-1$
+			buffer.append("\n\timplements : "); //$NON-NLS-1$
 			for (int i = 0, length = superInterfaces.length; i < length; i++) {
 				if (i  > 0)
-					s += ", "; //$NON-NLS-1$
-				s += (superInterfaces[i] != null) ? superInterfaces[i].debugName() : "NULL TYPE"; //$NON-NLS-1$
+					buffer.append(", "); //$NON-NLS-1$
+				buffer.append((superInterfaces[i] != null) ? superInterfaces[i].debugName() : "NULL TYPE"); //$NON-NLS-1$
 			}
 		}
 	} else {
-		s += "NULL SUPERINTERFACES"; //$NON-NLS-1$
+		buffer.append("NULL SUPERINTERFACES"); //$NON-NLS-1$
 	}
 
 	if (enclosingType() != null) {
-		s += "\n\tenclosing type : "; //$NON-NLS-1$
-		s += enclosingType().debugName();
+		buffer.append("\n\tenclosing type : "); //$NON-NLS-1$
+		buffer.append(enclosingType().debugName());
 	}
 
 	if (fields != null) {
 		if (fields != NoFields) {
-			s += "\n/*   fields   */"; //$NON-NLS-1$
+			buffer.append("\n/*   fields   */"); //$NON-NLS-1$
 			for (int i = 0, length = fields.length; i < length; i++)
-				s += (fields[i] != null) ? "\n" + fields[i].toString() : "\nNULL FIELD"; //$NON-NLS-1$ //$NON-NLS-2$
+			    buffer.append('\n').append((fields[i] != null) ? fields[i].toString() : "NULL FIELD"); //$NON-NLS-1$ 
 		}
 	} else {
-		s += "NULL FIELDS"; //$NON-NLS-1$
+		buffer.append("NULL FIELDS"); //$NON-NLS-1$
 	}
 
 	if (methods != null) {
 		if (methods != NoMethods) {
-			s += "\n/*   methods   */"; //$NON-NLS-1$
+			buffer.append("\n/*   methods   */"); //$NON-NLS-1$
 			for (int i = 0, length = methods.length; i < length; i++)
-				s += (methods[i] != null) ? "\n" + methods[i].toString() : "\nNULL METHOD"; //$NON-NLS-1$ //$NON-NLS-2$
+				buffer.append('\n').append((methods[i] != null) ? methods[i].toString() : "NULL METHOD"); //$NON-NLS-1$ //$NON-NLS-2$
 		}
 	} else {
-		s += "NULL METHODS"; //$NON-NLS-1$
+		buffer.append("NULL METHODS"); //$NON-NLS-1$
 	}
 
 	if (memberTypes != null) {
 		if (memberTypes != NoMemberTypes) {
-			s += "\n/*   members   */"; //$NON-NLS-1$
+			buffer.append("\n/*   members   */"); //$NON-NLS-1$
 			for (int i = 0, length = memberTypes.length; i < length; i++)
-				s += (memberTypes[i] != null) ? "\n" + memberTypes[i].toString() : "\nNULL TYPE"; //$NON-NLS-1$ //$NON-NLS-2$
+				buffer.append('\n').append((memberTypes[i] != null) ? memberTypes[i].toString() : "NULL TYPE"); //$NON-NLS-1$ //$NON-NLS-2$
 		}
 	} else {
-		s += "NULL MEMBER TYPES"; //$NON-NLS-1$
+		buffer.append("NULL MEMBER TYPES"); //$NON-NLS-1$
 	}
 
-	s += "\n\n\n"; //$NON-NLS-1$
-	return s;
+	buffer.append("\n\n"); //$NON-NLS-1$
+	return buffer.toString();
+}
+public TypeVariableBinding[] typeVariables() {
+	return this.typeVariables;
 }
 void verifyMethods(MethodVerifier verifier) {
 	verifier.verify(this);
@@ -1055,11 +1340,11 @@
 	// class T { class M{}}
 	// class S extends T { class N extends M {}} --> need to use S as a default enclosing instance for the super constructor call in N().
 	if (!onlyExactMatch){
-		Enumeration accessFields = synthetics[FIELD_EMUL].elements();
-		while (accessFields.hasMoreElements()) {
-			field = (FieldBinding) accessFields.nextElement();
-			if (CharOperation.prefixEquals(SyntheticArgumentBinding.EnclosingInstancePrefix, field.name)
-				&& targetEnclosingType.isSuperclassOf((ReferenceBinding) field.type))
+		Iterator accessFields = synthetics[FIELD_EMUL].values().iterator();
+		while (accessFields.hasNext()) {
+			field = (FieldBinding) accessFields.next();
+			if (CharOperation.prefixEquals(TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX, field.name)
+				&& ((ReferenceBinding) field.type).findSuperTypeErasingTo(targetEnclosingType) != null)
 					return field;
 		}
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BindingIds.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Substitution.java
similarity index 69%
rename from org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BindingIds.java
rename to org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Substitution.java
index 9f2e688..8d40cd0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BindingIds.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Substitution.java
@@ -10,12 +10,14 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
-public interface BindingIds {
-	final int FIELD = 1;
-	final int LOCAL = 2;
-	final int VARIABLE = FIELD | LOCAL;
-	final int TYPE = 4;
-	final int METHOD = 8;
-	final int PACKAGE = 16;
-	final int IMPORT = 32;
+/*
+ * Encapsulates aspects related to type variable substitution
+ */
+public interface Substitution {
+    
+	/**
+	 * Returns the type substitute for a given type, or itself
+	 * if no substitution got performed.
+	 */
+	TypeBinding substitute(TypeBinding originalType);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticArgumentBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticArgumentBinding.java
index 521c6ea..7c08f8e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticArgumentBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticArgumentBinding.java
@@ -34,14 +34,11 @@
 	public LocalVariableBinding actualOuterLocalVariable;
 	// if the argument has a matching synthetic field
 	public FieldBinding matchingField;
-
-	final static char[] OuterLocalPrefix = { 'v', 'a', 'l', '$' };
-	final static char[] EnclosingInstancePrefix = { 't', 'h', 'i', 's', '$' };
 	
 	public SyntheticArgumentBinding(LocalVariableBinding actualOuterLocalVariable) {
 
 		super(
-			CharOperation.concat(OuterLocalPrefix, actualOuterLocalVariable.name), 
+			CharOperation.concat(TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX, actualOuterLocalVariable.name), 
 			actualOuterLocalVariable.type, 
 			AccFinal,
 			true);
@@ -52,7 +49,7 @@
 
 		super(
 			CharOperation.concat(
-				SyntheticArgumentBinding.EnclosingInstancePrefix,
+				TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX,
 				String.valueOf(enclosingType.depth()).toCharArray()),
 			enclosingType, 
 			AccFinal,
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticAccessMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
similarity index 69%
rename from org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticAccessMethodBinding.java
rename to org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
index 0803da4..f256cdd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticAccessMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
@@ -14,33 +14,34 @@
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 
-public class SyntheticAccessMethodBinding extends MethodBinding {
+public class SyntheticMethodBinding extends MethodBinding {
 
 	public FieldBinding targetReadField;		// read access to a field
 	public FieldBinding targetWriteField;		// write access to a field
 	public MethodBinding targetMethod;	// method or constructor
 	
-	public int accessType;
+	public int kind;
 
 	public final static int FieldReadAccess = 1; 		// field read
 	public final static int FieldWriteAccess = 2; 		// field write
 	public final static int MethodAccess = 3; 		// normal method 
 	public final static int ConstructorAccess = 4; 	// constructor
 	public final static int SuperMethodAccess = 5; // super method
-
-	final static char[] AccessMethodPrefix = { 'a', 'c', 'c', 'e', 's', 's', '$' };
+	public final static int BridgeMethod = 6; // bridge method
+	public final static int EnumValues = 7; // enum #values()
+	public final static int EnumValueOf = 8; // enum #valueOf(String)
 
 	public int sourceStart = 0; // start position of the matching declaration
 	public int index; // used for sorting access methods in the class file
 	
-	public SyntheticAccessMethodBinding(FieldBinding targetField, boolean isReadAccess, ReferenceBinding declaringClass) {
+	public SyntheticMethodBinding(FieldBinding targetField, boolean isReadAccess, ReferenceBinding declaringClass) {
 
 		this.modifiers = AccDefault | AccStatic | AccSynthetic;
 		SourceTypeBinding declaringSourceType = (SourceTypeBinding) declaringClass;
-		SyntheticAccessMethodBinding[] knownAccessMethods = declaringSourceType.syntheticAccessMethods();
+		SyntheticMethodBinding[] knownAccessMethods = declaringSourceType.syntheticMethods();
 		int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
 		this.index = methodId;
-		this.selector = CharOperation.concat(AccessMethodPrefix, String.valueOf(methodId).toCharArray());
+		this.selector = CharOperation.concat(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX, String.valueOf(methodId).toCharArray());
 		if (isReadAccess) {
 			this.returnType = targetField.type;
 			if (targetField.isStatic()) {
@@ -50,7 +51,7 @@
 				this.parameters[0] = declaringSourceType;
 			}
 			this.targetReadField = targetField;
-			this.accessType = FieldReadAccess;
+			this.kind = FieldReadAccess;
 		} else {
 			this.returnType = VoidBinding;
 			if (targetField.isStatic()) {
@@ -62,7 +63,7 @@
 				this.parameters[1] = targetField.type;
 			}
 			this.targetWriteField = targetField;
-			this.accessType = FieldWriteAccess;
+			this.kind = FieldWriteAccess;
 		}
 		this.thrownExceptions = NoExceptions;
 		this.declaringClass = declaringSourceType;
@@ -92,7 +93,7 @@
 				}
 			}
 			if (needRename) { // retry with a selector postfixed by a growing methodId
-				this.setSelector(CharOperation.concat(AccessMethodPrefix, String.valueOf(++methodId).toCharArray()));
+				this.setSelector(CharOperation.concat(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX, String.valueOf(++methodId).toCharArray()));
 			}
 		} while (needRename);
 	
@@ -126,7 +127,7 @@
 		this.sourceStart = declaringSourceType.scope.referenceContext.sourceStart; // use the target declaring class name position instead
 	}
 
-	public SyntheticAccessMethodBinding(MethodBinding targetMethod, boolean isSuperAccess, ReferenceBinding receiverType) {
+	public SyntheticMethodBinding(MethodBinding targetMethod, boolean isSuperAccess, ReferenceBinding receiverType) {
 	
 		if (targetMethod.isConstructor()) {
 			this.initializeConstructorAccessor(targetMethod);
@@ -136,6 +137,54 @@
 	}
 
 	/**
+	 * Construct a bridge method
+	 */
+	public SyntheticMethodBinding(MethodBinding overridenMethodToBridge, MethodBinding localTargetMethod) {
+		
+	    this.declaringClass = localTargetMethod.declaringClass;
+	    this.selector = overridenMethodToBridge.selector;
+	    this.modifiers = overridenMethodToBridge.modifiers | AccBridge | AccSynthetic;
+	    this.modifiers &= ~(AccAbstract | AccNative);
+	    this.returnType = overridenMethodToBridge.returnType;
+	    this.parameters = overridenMethodToBridge.parameters;
+	    this.thrownExceptions = overridenMethodToBridge.thrownExceptions;
+	    this.targetMethod = localTargetMethod;
+	    this.kind = BridgeMethod;
+		SyntheticMethodBinding[] knownAccessMethods = ((SourceTypeBinding)this.declaringClass).syntheticMethods();
+		int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
+		this.index = methodId;	    
+	}
+	
+	/**
+	 * Construct enum special methods: values or valueOf methods
+	 */
+	public SyntheticMethodBinding(SourceTypeBinding declaringEnum, char[] selector) {
+		if (selector == TypeConstants.VALUES) {
+		    this.declaringClass = declaringEnum;
+		    this.selector = selector;
+		    this.modifiers = AccFinal | AccPublic | AccStatic;
+		    this.returnType = declaringEnum.scope.createArrayType(declaringEnum, 1);
+		    this.parameters = NoParameters;
+		    this.thrownExceptions = NoExceptions;
+		    this.kind = EnumValues;
+			SyntheticMethodBinding[] knownAccessMethods = ((SourceTypeBinding)this.declaringClass).syntheticMethods();
+			int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
+			this.index = methodId;	    
+		} else if (selector == TypeConstants.VALUEOF) {
+		    this.declaringClass = declaringEnum;
+		    this.selector = selector;
+		    this.modifiers = AccFinal | AccPublic | AccStatic;
+		    this.returnType = declaringEnum;
+		    this.parameters = new TypeBinding[]{ declaringEnum.scope.getJavaLangString() };
+		    this.thrownExceptions = NoExceptions;
+		    this.kind = EnumValueOf;
+			SyntheticMethodBinding[] knownAccessMethods = ((SourceTypeBinding)this.declaringClass).syntheticMethods();
+			int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
+			this.index = methodId;	    
+		}
+	}
+
+	/**
 	 * An constructor accessor is a constructor with an extra argument (declaringClass), in case of
 	 * collision with an existing constructor, then add again an extra argument (declaringClass again).
 	 */
@@ -144,13 +193,13 @@
 		this.targetMethod = accessedConstructor;
 		this.modifiers = AccDefault | AccSynthetic;
 		SourceTypeBinding sourceType = (SourceTypeBinding) accessedConstructor.declaringClass; 
-		SyntheticAccessMethodBinding[] knownAccessMethods = 
-			sourceType.syntheticAccessMethods(); 
-		this.index = knownAccessMethods == null ? 0 : knownAccessMethods.length;
+		SyntheticMethodBinding[] knownSyntheticMethods = 
+			sourceType.syntheticMethods(); 
+		this.index = knownSyntheticMethods == null ? 0 : knownSyntheticMethods.length;
 	
 		this.selector = accessedConstructor.selector;
 		this.returnType = accessedConstructor.returnType;
-		this.accessType = ConstructorAccess;
+		this.kind = ConstructorAccess;
 		this.parameters = new TypeBinding[accessedConstructor.parameters.length + 1];
 		System.arraycopy(
 			accessedConstructor.parameters, 
@@ -178,12 +227,12 @@
 					}
 				}
 				// check for collision with synthetic accessors
-				if (knownAccessMethods != null) {
-					for (int i = 0, length = knownAccessMethods.length; i < length; i++) {
-						if (knownAccessMethods[i] == null)
+				if (knownSyntheticMethods != null) {
+					for (int i = 0, length = knownSyntheticMethods.length; i < length; i++) {
+						if (knownSyntheticMethods[i] == null)
 							continue;
-						if (CharOperation.equals(this.selector, knownAccessMethods[i].selector)
-							&& this.areParametersEqual(knownAccessMethods[i])) {
+						if (CharOperation.equals(this.selector, knownSyntheticMethods[i].selector)
+							&& this.areParametersEqual(knownSyntheticMethods[i])) {
 							needRename = true;
 							break check;
 						}
@@ -223,13 +272,13 @@
 		this.targetMethod = accessedMethod;
 		this.modifiers = AccDefault | AccStatic | AccSynthetic;
 		SourceTypeBinding declaringSourceType = (SourceTypeBinding) receiverType;
-		SyntheticAccessMethodBinding[] knownAccessMethods = declaringSourceType.syntheticAccessMethods();
+		SyntheticMethodBinding[] knownAccessMethods = declaringSourceType.syntheticMethods();
 		int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
 		this.index = methodId;
 	
-		this.selector = CharOperation.concat(AccessMethodPrefix, String.valueOf(methodId).toCharArray());
+		this.selector = CharOperation.concat(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX, String.valueOf(methodId).toCharArray());
 		this.returnType = accessedMethod.returnType;
-		this.accessType = isSuperAccess ? SuperMethodAccess : MethodAccess;
+		this.kind = isSuperAccess ? SuperMethodAccess : MethodAccess;
 		
 		if (accessedMethod.isStatic()) {
 			this.parameters = accessedMethod.parameters;
@@ -266,7 +315,7 @@
 				}
 			}
 			if (needRename) { // retry with a selector & a growing methodId
-				this.setSelector(CharOperation.concat(AccessMethodPrefix, String.valueOf(++methodId).toCharArray()));
+				this.setSelector(CharOperation.concat(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX, String.valueOf(++methodId).toCharArray()));
 			}
 		} while (needRename);
 	
@@ -283,6 +332,6 @@
 	}
 
 	protected boolean isConstructorRelated() {
-		return accessType == ConstructorAccess;
+		return kind == ConstructorAccess;
 	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
index 556a7c4..ffc6b55 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
@@ -10,36 +10,86 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+
 public interface TagBits {
+    
 	// Tag bits in the tagBits int of every TypeBinding
-	final int IsArrayType = 0x0001;
-	final int IsBaseType = 0x0002;
-	final int IsNestedType = 0x0004;
-	final int IsMemberType = 0x0008;
-	final int MemberTypeMask = IsNestedType | IsMemberType;
-	final int IsLocalType = 0x0010;
-	final int LocalTypeMask = IsNestedType | IsLocalType;
-	final int IsAnonymousType = 0x0020;
-	final int AnonymousTypeMask = LocalTypeMask | IsAnonymousType;
-	final int IsBinaryBinding = 0x0040;
-
-	// for the type hierarchy check used by ClassScope
-	final int BeginHierarchyCheck = 0x0100;
-	final int EndHierarchyCheck = 0x0200;
-
+	long IsArrayType = ASTNode.Bit1;
+	long IsBaseType = ASTNode.Bit2;
+	long IsNestedType = ASTNode.Bit3;
+	long IsMemberType = ASTNode.Bit4;
+	long MemberTypeMask = IsNestedType | IsMemberType;
+	long IsLocalType = ASTNode.Bit5;
+	long LocalTypeMask = IsNestedType | IsLocalType;
+	long IsAnonymousType = ASTNode.Bit6;
+	long AnonymousTypeMask = LocalTypeMask | IsAnonymousType;
+	long IsBinaryBinding = ASTNode.Bit7;
+	
+	// for the type cycle hierarchy check used by ClassScope
+	long BeginHierarchyCheck = ASTNode.Bit9;  // type
+	long EndHierarchyCheck = ASTNode.Bit10; // type
+	long HasParameterAnnotations = ASTNode.Bit11; // method
+	
 	// test bit to see if default abstract methods were computed
-	final int KnowsDefaultAbstractMethods = 0x0400;
+	long KnowsDefaultAbstractMethods = ASTNode.Bit11;
 
 	// Reusable bit currently used by Scopes
-	final int InterfaceVisited = 0x0800;
+	long InterfaceVisited = ASTNode.Bit12;
 
 	// test bits to see if parts of binary types are faulted
-	final int AreFieldsComplete = 0x1000;
-	final int AreMethodsComplete = 0x2000;
+	long AreFieldsComplete = ASTNode.Bit13;
+	long AreMethodsComplete = ASTNode.Bit14;
 
 	// test bit to avoid asking a type for a member type (includes inherited member types)
-	final int HasNoMemberTypes = 0x4000;
+	long HasNoMemberTypes = ASTNode.Bit15;
 
 	// test bit to identify if the type's hierarchy is inconsistent
-	final int HierarchyHasProblems = 0x8000;
+	long HierarchyHasProblems = ASTNode.Bit16;
+
+	// set for parameterized type NOT of the form X<?,?>
+	long IsBoundParameterizedType = ASTNode.Bit24; 
+
+	// used by BinaryTypeBinding
+	long HasUnresolvedTypeVariables = ASTNode.Bit25;
+	long HasUnresolvedSuperclass = ASTNode.Bit26;
+	long HasUnresolvedSuperinterfaces = ASTNode.Bit27;
+	long HasUnresolvedEnclosingType = ASTNode.Bit28;
+	long HasUnresolvedMemberTypes = ASTNode.Bit29;
+
+	long HasTypeVariable = ASTNode.Bit30; // set either for type variables (direct) or parameterized types indirectly referencing type variables
+	long HasDirectWildcard = ASTNode.Bit31; // set for parameterized types directly referencing wildcards
+	
+	// for the annotation cycle hierarchy check used by ClassScope
+	long BeginAnnotationCheck = ASTNode.Bit32L;
+	long EndAnnotationCheck = ASTNode.Bit33L;
+	
+	// standard annotations
+	// 9-bits for targets
+	long AnnotationResolved = ASTNode.Bit34L;
+	long AnnotationTarget = ASTNode.Bit35L; // @Target({}) only sets this bit
+	long AnnotationForType = ASTNode.Bit36L;
+	long AnnotationForField = ASTNode.Bit37L;
+	long AnnotationForMethod = ASTNode.Bit38L;
+	long AnnotationForParameter = ASTNode.Bit39L;
+	long AnnotationForConstructor = ASTNode.Bit40L;
+	long AnnotationForLocalVariable = ASTNode.Bit41L;
+	long AnnotationForAnnotationType = ASTNode.Bit42L;
+	long AnnotationForPackage = ASTNode.Bit43L;
+	long AnnotationTargetMASK = AnnotationTarget
+				| AnnotationForType | AnnotationForField
+				| AnnotationForMethod | AnnotationForParameter
+				| AnnotationForConstructor | AnnotationForLocalVariable
+				| AnnotationForAnnotationType | AnnotationForPackage;
+	// 2-bits for retention (should check (tagBits & RetentionMask) == RuntimeRetention
+	long AnnotationSourceRetention = ASTNode.Bit44L;
+	long AnnotationClassRetention = ASTNode.Bit45L;
+	long AnnotationRuntimeRetention = AnnotationSourceRetention | AnnotationClassRetention;
+	long AnnotationRetentionMASK = AnnotationSourceRetention | AnnotationClassRetention | AnnotationRuntimeRetention;
+	// marker annotations
+	long AnnotationDeprecated = ASTNode.Bit46L;
+	long AnnotationDocumented = ASTNode.Bit47L;
+	long AnnotationInherited = ASTNode.Bit48L;
+	long AnnotationOverride = ASTNode.Bit49L;
+	long AnnotationSuppressWarnings = ASTNode.Bit50L;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
index c6cd627..43455eb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
@@ -10,7 +10,9 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
+import java.util.Map;
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
 
 /*
  * Not all fields defined by this type (& its subclasses) are initialized when it is created.
@@ -24,13 +26,42 @@
  */
 abstract public class TypeBinding extends Binding implements BaseTypes, TagBits, TypeConstants, TypeIds {
 	public int id = NoId;
-	public int tagBits = 0; // See values in the interface TagBits below
+	public long tagBits = 0; // See values in the interface TagBits below
+/**
+ * Match a well-known type id to its binding
+ */
+public static final TypeBinding wellKnownType(Scope scope, int id) {
+		switch (id) { 
+			case T_boolean :
+				return BooleanBinding;
+			case T_byte :
+				return ByteBinding;
+			case T_char :
+				return CharBinding;
+			case T_short :
+				return ShortBinding;
+			case T_double :
+				return DoubleBinding;
+			case T_float :
+				return FloatBinding;
+			case T_int :
+				return IntBinding;
+			case T_long :
+				return LongBinding;
+			case T_JavaLangObject :
+				return scope.getJavaLangObject();
+			case T_JavaLangString :
+				return scope.getJavaLangString();
+			default : 
+				return null;
+		}
+	}
 /* API
  * Answer the receiver's binding type from Binding.BindingID.
  */
 
-public final int bindingType() {
-	return TYPE;
+public int kind() {
+	return Binding.TYPE;
 }
 /* Answer true if the receiver can be instantiated
  */
@@ -38,13 +69,26 @@
 	return !isBaseType();
 }
 /**
+ * Collect the substitutes into a map for certain type variables inside the receiver type
+ * e.g.   Collection<T>.findSubstitute(T, Collection<List<X>>):   T --> List<X>
+ */
+public void collectSubstitutes(TypeBinding otherType, Map substitutes) {
+    // no substitute by default
+}
+/*
+ * genericTypeSignature
+ */
+public char[] computeUniqueKey() {
+	return genericTypeSignature();
+}
+/**
  *  Answer the receiver's constant pool name.
  *  NOTE: This method should only be used during/after code gen.
  *  e.g. 'java/lang/Object' 
  */
 public abstract char[] constantPoolName();
 
-String debugName() {
+public String debugName() {
 	return new String(readableName());
 }
 /*
@@ -53,35 +97,101 @@
 public int dimensions(){
 	return 0;
 }
-public abstract PackageBinding getPackage();
-/* Answer true if the receiver is an array
+/* Answer the receiver's enclosing type... null if the receiver is a top level type.
 */
 
+public ReferenceBinding enclosingType() {
+	return null;
+}
+public TypeBinding erasure() {
+    return this;
+}
+/**
+ * Returns the type to use for generic cast, or null if none required
+ */
+public TypeBinding genericCast(TypeBinding otherType) {
+    if (this == otherType) return null;
+	if (otherType.isWildcard() && ((WildcardBinding)otherType).kind != Wildcard.EXTENDS) return null;
+	TypeBinding otherErasure = otherType.erasure();
+	if (otherErasure == this.erasure()) return null;
+	return otherErasure;
+}
+
+/**
+ * Answer the receiver classfile signature.
+ * Arrays & base types do not distinguish between signature() & constantPoolName().
+ * NOTE: This method should only be used during/after code gen.
+ */
+public char[] genericTypeSignature() {
+    return signature();
+}
+public abstract PackageBinding getPackage();
+public boolean isAnnotationType() {
+	return false;
+}
+/* Answer true if the receiver is an array
+*/
 public final boolean isArrayType() {
 	return (tagBits & IsArrayType) != 0;
 }
 /* Answer true if the receiver is a base type
 */
-
 public final boolean isBaseType() {
 	return (tagBits & IsBaseType) != 0;
 }
+
+	
+/**
+ *  Returns true if parameterized type AND not of the form List<?>
+ */
+public boolean isBoundParameterizedType() {
+	return (this.tagBits & TagBits.IsBoundParameterizedType) != 0;
+}
 public boolean isClass() {
 	return false;
 }
 /* Answer true if the receiver type can be assigned to the argument type (right)
 */
-	
 public abstract boolean isCompatibleWith(TypeBinding right);
+
+public boolean isEnum() {
+	return false;
+}
+/**
+ * Returns true if a type is identical to another one,
+ * or for generic types, true if compared to its raw type.
+ */
+public boolean isEquivalentTo(TypeBinding otherType) {
+    if (this == otherType) return true;
+    if (otherType == null) return false;
+    if (otherType.isWildcard()) // wildcard
+		return ((WildcardBinding) otherType).boundCheck(this);
+	return false;
+}
+
+public boolean isGenericType() {
+    return false;
+}
+
 /* Answer true if the receiver's hierarchy has problems (always false for arrays & base types)
 */
-
 public final boolean isHierarchyInconsistent() {
 	return (tagBits & HierarchyHasProblems) != 0;
 }
 public boolean isInterface() {
 	return false;
 }
+public final boolean isLocalType() {
+	return (tagBits & IsLocalType) != 0;
+}
+
+public final boolean isMemberType() {
+	return (tagBits & IsMemberType) != 0;
+}
+
+public final boolean isNestedType() {
+	return (tagBits & IsNestedType) != 0;
+}
 public final boolean isNumericType() {
 	switch (id) {
 		case T_int :
@@ -97,6 +207,170 @@
 	}
 }
 
+/**
+ * Returns true if the type is parameterized, e.g. List<String>
+ */
+public boolean isParameterizedType() {
+    return false;
+}
+	
+public boolean isPartOfRawType() {
+	TypeBinding current = this;
+	do {
+		if (current.isRawType())
+			return true;
+	} while ((current = current.enclosingType()) != null);
+    return false;
+}
+
+/**
+ * Returns true if the two types are statically known to be different at compile-time,
+ * e.g. a type variable is not probably known to be distinct from another type
+ */
+public boolean isProvablyDistinctFrom(TypeBinding otherType, int depth) {
+	if (this == otherType) return false;
+	if (depth > 1) return true;
+	switch (otherType.kind()) {
+		case Binding.TYPE_PARAMETER :
+		case Binding.WILDCARD_TYPE :
+			return false;
+	}
+	switch(kind()) {
+		
+		case Binding.TYPE_PARAMETER :
+		case Binding.WILDCARD_TYPE :
+			return false;
+			
+		case Binding.PARAMETERIZED_TYPE :
+			ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) this;
+			if (parameterizedType.type.isProvablyDistinctFrom(otherType.erasure(), depth)) return true;
+			switch (otherType.kind()) {
+				case Binding.GENERIC_TYPE :
+				case Binding.RAW_TYPE :
+					return false;
+				case Binding.PARAMETERIZED_TYPE :
+					TypeBinding[] arguments = parameterizedType.arguments;
+					if (arguments == null) return false;
+					ParameterizedTypeBinding otherParameterizedType = (ParameterizedTypeBinding) otherType;
+					TypeBinding[] otherArguments = otherParameterizedType.arguments;
+					if (otherArguments == null) return false;
+					for (int i = 0, length = arguments.length; i < length; i++) {
+						if (arguments[i].isProvablyDistinctFrom(otherArguments[i], depth+1)) return true;
+					}
+					return false;
+					
+			}
+			break;
+
+		case Binding.RAW_TYPE :
+			return this.erasure().isProvablyDistinctFrom(otherType.erasure(), 0);
+			
+		case Binding.GENERIC_TYPE :
+			return this != otherType.erasure();
+	}
+	return this != otherType;
+}
+
+public boolean isRawType() {
+    return false;
+}
+
+/**
+ * JLS(3) 4.7
+ */
+public boolean isReifiable() {
+	
+	TypeBinding leafType = leafComponentType();
+	if (!(leafType instanceof ReferenceBinding)) 
+		return true;
+	ReferenceBinding current = (ReferenceBinding) leafType;
+	do {
+		switch(current.kind()) {
+			
+			case Binding.TYPE_PARAMETER :
+			case Binding.WILDCARD_TYPE :
+			case Binding.GENERIC_TYPE :
+				return false;
+				
+			case Binding.PARAMETERIZED_TYPE :
+				if (isBoundParameterizedType()) 
+					return false;
+				break;
+				
+			case Binding.RAW_TYPE :
+				return true;
+		}
+		if (current.isStatic()) 
+			return true;
+	} while ((current = current.enclosingType()) != null);
+	return true;
+}
+
+// JLS3: 4.5.1.1
+public boolean isTypeArgumentContainedBy(TypeBinding otherArgument) {
+	if (this == otherArgument)
+		return true;
+	TypeBinding lowerBound = this;
+	TypeBinding upperBound = this;
+	if (isWildcard()) {
+		WildcardBinding wildcard = (WildcardBinding) this;
+		switch(wildcard.kind) {
+			case Wildcard.EXTENDS :
+				upperBound = wildcard.bound;
+				lowerBound = null;
+				break;
+			case Wildcard. SUPER :
+				upperBound = wildcard.typeVariable();
+				lowerBound = wildcard.bound;
+				break;
+			case Wildcard.UNBOUND :
+				upperBound = wildcard.typeVariable();
+				lowerBound = null;
+		}
+	}
+	if (otherArgument.isWildcard()) {
+		WildcardBinding otherWildcard = (WildcardBinding) otherArgument;
+		switch(otherWildcard.kind) {
+			case Wildcard.EXTENDS:
+				return upperBound != null && upperBound.isCompatibleWith(otherWildcard.bound);
+
+			case Wildcard.SUPER :
+				return lowerBound != null && otherWildcard.bound.isCompatibleWith(lowerBound);
+
+			case Wildcard.UNBOUND :
+				return true;
+		}
+	}
+	return false;
+}
+
+/**
+ * Returns true if the type was declared as a type variable
+ */
+public boolean isTypeVariable() {
+    return false;
+}
+/**
+ * Returns true if wildcard type of the form '?' (no bound)
+ */
+public boolean isUnboundWildcard() {
+	return false;
+}
+
+/**
+ * Returns true if the type is a wildcard
+ */
+public boolean isWildcard() {
+    return false;
+}
+	
+/**
+ * Meant to be invoked on compatible types, to figure if unchecked conversion is necessary
+ */
+public boolean needsUncheckedConversion(TypeBinding targetType) {
+	return false;
+}
+
 public TypeBinding leafComponentType(){
 	return this;
 }
@@ -121,45 +395,22 @@
 */
 
 public abstract char[] qualifiedSourceName();
-/* Answer the receiver's signature.
-*
-* Arrays & base types do not distinguish between signature() & constantPoolName().
-*
-* NOTE: This method should only be used during/after code gen.
-*/
 
+/**
+ * Answer the receiver classfile signature.
+ * Arrays & base types do not distinguish between signature() & constantPoolName().
+ * NOTE: This method should only be used during/after code gen.
+ */
 public char[] signature() {
 	return constantPoolName();
 }
+
 public abstract char[] sourceName();
 
-/**
- * Match a well-known type id to its binding
- */
-public static final TypeBinding wellKnownType(Scope scope, int id) {
-		switch (id) { 
-			case T_boolean :
-				return BooleanBinding;
-			case T_byte :
-				return ByteBinding;
-			case T_char :
-				return CharBinding;
-			case T_short :
-				return ShortBinding;
-			case T_double :
-				return DoubleBinding;
-			case T_float :
-				return FloatBinding;
-			case T_int :
-				return IntBinding;
-			case T_long :
-				return LongBinding;
-			case T_Object :
-				return scope.getJavaLangObject();
-			case T_String :
-				return scope.getJavaLangString();
-			default : 
-				return null;
-		}
-	}
+public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment environment) {
+	// subclasses must override if they wrap another type binding
+}
+public TypeVariableBinding[] typeVariables() {
+	return NoTypeVariables;
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
index 5f6064f..3a31669 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
@@ -11,67 +11,130 @@
 package org.eclipse.jdt.internal.compiler.lookup;
 
 public interface TypeConstants {
-	final char[] JAVA = "java".toCharArray(); //$NON-NLS-1$
-	final char[] LANG = "lang".toCharArray(); //$NON-NLS-1$
-	final char[] IO = "io".toCharArray(); //$NON-NLS-1$
-	final char[] REFLECT = "reflect".toCharArray(); //$NON-NLS-1$
-	final char[] CharArray_JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
-	final char[] LENGTH = "length".toCharArray(); //$NON-NLS-1$
-	final char[] CLONE = "clone".toCharArray(); //$NON-NLS-1$
-	final char[] OBJECT = "Object".toCharArray(); //$NON-NLS-1$
-	final char[] MAIN = "main".toCharArray(); //$NON-NLS-1$
-	final char[] SERIALVERSIONUID = "serialVersionUID".toCharArray(); //$NON-NLS-1$
-	final char[] SERIALPERSISTENTFIELDS = "serialPersistentFields".toCharArray(); //$NON-NLS-1$ 
-	final char[] READRESOLVE = "readResolve".toCharArray(); //$NON-NLS-1$
-	final char[] WRITEREPLACE = "writeReplace".toCharArray(); //$NON-NLS-1$
-	final char[] READOBJECT = "readObject".toCharArray(); //$NON-NLS-1$
-	final char[] WRITEOBJECT = "writeObject".toCharArray(); //$NON-NLS-1$
-	final char[] CharArray_JAVA_IO_OBJECTINPUTSTREAM = "java.io.ObjectInputStream".toCharArray(); //$NON-NLS-1$
-	final char[] CharArray_JAVA_IO_OBJECTOUTPUTSTREAM = "java.io.ObjectOutputStream".toCharArray(); //$NON-NLS-1$
-	final char[] CharArray_JAVA_IO_OBJECTSTREAMFIELD = "java.io.ObjectStreamField".toCharArray(); //$NON-NLS-1$
-	
-	
+	char[] JAVA = "java".toCharArray(); //$NON-NLS-1$
+	char[] LANG = "lang".toCharArray(); //$NON-NLS-1$
+	char[] IO = "io".toCharArray(); //$NON-NLS-1$
+	char[] ANNOTATION = "annotation".toCharArray(); //$NON-NLS-1$
+	char[] REFLECT = "reflect".toCharArray(); //$NON-NLS-1$
+	char[] LENGTH = "length".toCharArray(); //$NON-NLS-1$
+	char[] CLONE = "clone".toCharArray(); //$NON-NLS-1$
+	char[] GETCLASS = "getClass".toCharArray(); //$NON-NLS-1$
+	char[] OBJECT = "Object".toCharArray(); //$NON-NLS-1$
+	char[] MAIN = "main".toCharArray(); //$NON-NLS-1$
+	char[] SERIALVERSIONUID = "serialVersionUID".toCharArray(); //$NON-NLS-1$
+	char[] SERIALPERSISTENTFIELDS = "serialPersistentFields".toCharArray(); //$NON-NLS-1$ 
+	char[] READRESOLVE = "readResolve".toCharArray(); //$NON-NLS-1$
+	char[] WRITEREPLACE = "writeReplace".toCharArray(); //$NON-NLS-1$
+	char[] READOBJECT = "readObject".toCharArray(); //$NON-NLS-1$
+	char[] WRITEOBJECT = "writeObject".toCharArray(); //$NON-NLS-1$
+	char[] CharArray_JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
+	char[] CharArray_JAVA_LANG_ENUM = "java.lang.Enum".toCharArray(); //$NON-NLS-1$
+	char[] CharArray_JAVA_LANG_ANNOTATION_ANNOTATION = "java.lang.annotation.Annotation".toCharArray(); //$NON-NLS-1$
+	char[] CharArray_JAVA_IO_OBJECTINPUTSTREAM = "java.io.ObjectInputStream".toCharArray(); //$NON-NLS-1$
+	char[] CharArray_JAVA_IO_OBJECTOUTPUTSTREAM = "java.io.ObjectOutputStream".toCharArray(); //$NON-NLS-1$
+	char[] CharArray_JAVA_IO_OBJECTSTREAMFIELD = "java.io.ObjectStreamField".toCharArray(); //$NON-NLS-1$
+	char[] ANONYM_PREFIX = "new ".toCharArray(); //$NON-NLS-1$
+	char[] ANONYM_SUFFIX = "(){}".toCharArray(); //$NON-NLS-1$
+    char[] WILDCARD_NAME = { '?' };
+    char[] WILDCARD_SUPER = " super ".toCharArray(); //$NON-NLS-1$
+    char[] WILDCARD_EXTENDS = " extends ".toCharArray(); //$NON-NLS-1$
+    char[] WILDCARD_MINUS = { '-' };
+    char[] WILDCARD_STAR = { '*' };
+    char[] WILDCARD_PLUS = { '+' };
+	char[] BYTE = "byte".toCharArray(); //$NON-NLS-1$
+	char[] SHORT = "short".toCharArray(); //$NON-NLS-1$
+	char[] INT = "int".toCharArray(); //$NON-NLS-1$
+	char[] LONG = "long".toCharArray(); //$NON-NLS-1$
+	char[] FLOAT = "float".toCharArray(); //$NON-NLS-1$
+	char[] DOUBLE = "double".toCharArray(); //$NON-NLS-1$
+	char[] CHAR = "char".toCharArray(); //$NON-NLS-1$
+	char[] BOOLEAN = "boolean".toCharArray(); //$NON-NLS-1$
+	char[] NULL = "null".toCharArray(); //$NON-NLS-1$
+	char[] VOID = "void".toCharArray(); //$NON-NLS-1$
+    char[] VALUE = "value".toCharArray(); //$NON-NLS-1$
+    char[] VALUES = "values".toCharArray(); //$NON-NLS-1$
+    char[] VALUEOF = "valueOf".toCharArray(); //$NON-NLS-1$
+    char[] UPPER_SOURCE = "SOURCE".toCharArray(); //$NON-NLS-1$
+    char[] UPPER_CLASS = "CLASS".toCharArray(); //$NON-NLS-1$
+    char[] UPPER_RUNTIME = "RUNTIME".toCharArray(); //$NON-NLS-1$
+	char[] ANNOTATION_PREFIX = "@".toCharArray(); //$NON-NLS-1$
+	char[] ANNOTATION_SUFFIX = "()".toCharArray(); //$NON-NLS-1$
+    char[] TYPE = "TYPE".toCharArray(); //$NON-NLS-1$
+    char[] UPPER_FIELD = "FIELD".toCharArray(); //$NON-NLS-1$
+    char[] UPPER_METHOD = "METHOD".toCharArray(); //$NON-NLS-1$
+    char[] UPPER_PARAMETER = "PARAMETER".toCharArray(); //$NON-NLS-1$
+    char[] UPPER_CONSTRUCTOR = "CONSTRUCTOR".toCharArray(); //$NON-NLS-1$
+    char[] UPPER_LOCAL_VARIABLE = "LOCAL_VARIABLE".toCharArray(); //$NON-NLS-1$
+    char[] UPPER_ANNOTATION_TYPE = "ANNOTATION_TYPE".toCharArray(); //$NON-NLS-1$
+    char[] UPPER_PACKAGE = "PACKAGE".toCharArray(); //$NON-NLS-1$
+    
 	// Constant compound names
-	final char[][] JAVA_LANG = {JAVA, LANG};
-	final char[][] JAVA_IO = {JAVA, IO};
-	final char[][] JAVA_LANG_ASSERTIONERROR = {JAVA, LANG, "AssertionError".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_CLASS = {JAVA, LANG, "Class".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_CLASSNOTFOUNDEXCEPTION = {JAVA, LANG, "ClassNotFoundException".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_CLONEABLE = {JAVA, LANG, "Cloneable".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_EXCEPTION = {JAVA, LANG, "Exception".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_ERROR = {JAVA, LANG, "Error".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_NOCLASSDEFERROR = {JAVA, LANG, "NoClassDefError".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_OBJECT = {JAVA, LANG, OBJECT};
-	final char[][] JAVA_LANG_STRING = {JAVA, LANG, "String".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_STRINGBUFFER = {JAVA, LANG, "StringBuffer".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_SYSTEM = {JAVA, LANG, "System".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_RUNTIMEEXCEPTION = {JAVA, LANG, "RuntimeException".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_THROWABLE = {JAVA, LANG, "Throwable".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_REFLECT_CONSTRUCTOR = {JAVA, LANG, REFLECT, "Constructor".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_IO_PRINTSTREAM = {JAVA, IO, "PrintStream".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_IO_SERIALIZABLE = {JAVA, IO, "Serializable".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_BYTE = {JAVA, LANG, "Byte".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_SHORT = {JAVA, LANG, "Short".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_CHARACTER = {JAVA, LANG, "Character".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_INTEGER = {JAVA, LANG, "Integer".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_LONG = {JAVA, LANG, "Long".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_FLOAT = {JAVA, LANG, "Float".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_DOUBLE = {JAVA, LANG, "Double".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_BOOLEAN = {JAVA, LANG, "Boolean".toCharArray()}; //$NON-NLS-1$
-	final char[][] JAVA_LANG_VOID = {JAVA, LANG, "Void".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG = {JAVA, LANG};
+	char[][] JAVA_IO = {JAVA, IO};
+	char[][] JAVA_LANG_ANNOTATION_ANNOTATION = {JAVA, LANG, ANNOTATION, "Annotation".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_ASSERTIONERROR = {JAVA, LANG, "AssertionError".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_CLASS = {JAVA, LANG, "Class".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_CLASSNOTFOUNDEXCEPTION = {JAVA, LANG, "ClassNotFoundException".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_CLONEABLE = {JAVA, LANG, "Cloneable".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_ENUM = {JAVA, LANG, "Enum".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_EXCEPTION = {JAVA, LANG, "Exception".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_ERROR = {JAVA, LANG, "Error".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_ILLEGALARGUMENTEXCEPTION = {JAVA, LANG, "IllegalArgumentException".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_ITERABLE = {JAVA, LANG, "Iterable".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_NOCLASSDEFERROR = {JAVA, LANG, "NoClassDefError".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_OBJECT = {JAVA, LANG, OBJECT};
+	char[][] JAVA_LANG_STRING = {JAVA, LANG, "String".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_STRINGBUFFER = {JAVA, LANG, "StringBuffer".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_STRINGBUILDER = {JAVA, LANG, "StringBuilder".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_SYSTEM = {JAVA, LANG, "System".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_RUNTIMEEXCEPTION = {JAVA, LANG, "RuntimeException".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_THROWABLE = {JAVA, LANG, "Throwable".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_REFLECT_CONSTRUCTOR = {JAVA, LANG, REFLECT, "Constructor".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_IO_PRINTSTREAM = {JAVA, IO, "PrintStream".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_IO_SERIALIZABLE = {JAVA, IO, "Serializable".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_BYTE = {JAVA, LANG, "Byte".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_SHORT = {JAVA, LANG, "Short".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_CHARACTER = {JAVA, LANG, "Character".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_INTEGER = {JAVA, LANG, "Integer".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_LONG = {JAVA, LANG, "Long".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_FLOAT = {JAVA, LANG, "Float".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_DOUBLE = {JAVA, LANG, "Double".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_BOOLEAN = {JAVA, LANG, "Boolean".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_VOID = {JAVA, LANG, "Void".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_UTIL_ITERATOR = {JAVA, "util".toCharArray(), "Iterator".toCharArray()}; //$NON-NLS-1$//$NON-NLS-2$
+	char[][] JAVA_LANG_DEPRECATED = {JAVA, LANG, "Deprecated".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_ANNOTATION_DOCUMENTED = {JAVA, LANG, ANNOTATION, "Documented".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_ANNOTATION_INHERITED = {JAVA, LANG, ANNOTATION, "Inherited".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_OVERRIDE = {JAVA, LANG, "Override".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_ANNOTATION_RETENTION = {JAVA, LANG, ANNOTATION, "Retention".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_SUPPRESSWARNINGS = {JAVA, LANG, "SuppressWarnings".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_ANNOTATION_TARGET = {JAVA, LANG, ANNOTATION, "Target".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_ANNOTATION_RETENTIONPOLICY = {JAVA, LANG, ANNOTATION, "RetentionPolicy".toCharArray()}; //$NON-NLS-1$
+	char[][] JAVA_LANG_ANNOTATION_ELEMENTTYPE = {JAVA, LANG, ANNOTATION, "ElementType".toCharArray()}; //$NON-NLS-1$
+	
 
 	// Constants used by the flow analysis
-	final int EqualOrMoreSpecific = -1;
-	final int NotRelated = 0;
-	final int MoreGeneric = 1;
+	int EqualOrMoreSpecific = -1;
+	int NotRelated = 0;
+	int MoreGeneric = 1;
 
-	// Method collections
-	final TypeBinding[] NoParameters = new TypeBinding[0];
-	final ReferenceBinding[] NoExceptions = new ReferenceBinding[0];
-	final ReferenceBinding[] AnyException = new ReferenceBinding[] { null }; // special handler for all exceptions
-	// Type collections
-	final FieldBinding[] NoFields = new FieldBinding[0];
-	final MethodBinding[] NoMethods = new MethodBinding[0];
-	final ReferenceBinding[] NoSuperInterfaces = new ReferenceBinding[0];
-	final ReferenceBinding[] NoMemberTypes = new ReferenceBinding[0];
+	// Shared binding collections
+	TypeBinding[] NoParameters = new TypeBinding[0];
+	ReferenceBinding[] NoExceptions = new ReferenceBinding[0];
+	ReferenceBinding[] AnyException = new ReferenceBinding[] { null }; // special handler for all exceptions
+	FieldBinding[] NoFields = new FieldBinding[0];
+	MethodBinding[] NoMethods = new MethodBinding[0];
+	ReferenceBinding[] NoSuperInterfaces = new ReferenceBinding[0];
+	ReferenceBinding[] NoMemberTypes = new ReferenceBinding[0];
+	TypeVariableBinding[] NoTypeVariables = new TypeVariableBinding[0];
+	
+	// Synthetics
+	char[] INIT = "<init>".toCharArray(); //$NON-NLS-1$
+	char[] CLINIT = "<clinit>".toCharArray(); //$NON-NLS-1$
+	char[] SYNTHETIC_ENUM_VALUES = "ENUM$VALUES".toCharArray(); //$NON-NLS-1$
+	char[] SYNTHETIC_ASSERT_DISABLED = "$assertionsDisabled".toCharArray(); //$NON-NLS-1$
+	char[] SYNTHETIC_CLASS = "class$".toCharArray(); //$NON-NLS-1$
+	char[] SYNTHETIC_OUTER_LOCAL_PREFIX = "val$".toCharArray(); //$NON-NLS-1$
+	char[] SYNTHETIC_ENCLOSING_INSTANCE_PREFIX = "this$".toCharArray(); //$NON-NLS-1$
+	char[] SYNTHETIC_ACCESS_METHOD_PREFIX =  "access$".toCharArray(); //$NON-NLS-1$
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
index 5fe8af0..0e8beeb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
@@ -11,11 +11,12 @@
 package org.eclipse.jdt.internal.compiler.lookup;
 
 public interface TypeIds {
-	//base type void null undefined Object String
-	//should have an id that is 0<= id <= 15
 
+    //base type void null undefined Object String
+	//should have an id that is 0<= id <= 15
+    // The IDs below must be representable using 4 bits so as to fit in operator signatures.
 	final int T_undefined = 0; // should not be changed
-	final int T_Object = 1;
+	final int T_JavaLangObject = 1;
 	final int T_char = 2;
 	final int T_byte = 3;
 	final int T_short = 4;
@@ -25,16 +26,11 @@
 	final int T_double = 8;
 	final int T_float = 9;
 	final int T_int = 10;
-	final int T_String = 11;
+	final int T_JavaLangString = 11;
 	final int T_null = 12;
-	//final int T_extendedDouble = 13;
-	//final int T_extendedLong = 14
 
 	//=========end of 4 bits constraint===========
 
-	final int T_JavaLangObject = T_Object; // for consistency
-	final int T_JavaLangString = T_String; // for consistency
-
 	// well-known exception types
 	final int T_JavaLangClass = 16;
 	final int T_JavaLangStringBuffer = 17;
@@ -58,18 +54,38 @@
 	final int T_JavaLangBoolean = 33;
 	final int T_JavaLangVoid = 34;
 
-	// 1.4 feature
+	// 1.4 features
 	final int T_JavaLangAssertionError = 35;
-
+	
 	// array interfaces
 	final int T_JavaLangCloneable = 36;
 	final int T_JavaIoSerializable = 37;
+	    
+	// 1.5 features
+	final int T_JavaLangIterable = 38;
+	final int T_JavaUtilIterator = 39;
+	final int T_JavaLangStringBuilder = 40;
+	final int T_JavaLangEnum = 41;
+	final int T_JavaLangIllegalArgumentException = 42;
+	final int T_JavaLangAnnotationAnnotation = 43;
+	final int T_JavaLangDeprecated = 44;
+	final int T_JavaLangAnnotationDocumented = 45;
+	final int T_JavaLangAnnotationInherited = 46;
+	final int T_JavaLangOverride = 47;
+	final int T_JavaLangAnnotationRetention = 48;
+	final int T_JavaLangSuppressWarnings = 49;
+	final int T_JavaLangAnnotationTarget = 50;
+	final int T_JavaLangAnnotationRetentionPolicy = 51;
+	final int T_JavaLangAnnotationElementType = 52;
 	
 	final int NoId = Integer.MAX_VALUE;
 
+	public static final int IMPLICIT_CONVERSION_MASK = 0xFF;
+	public static final int COMPILE_TYPE_MASK = 0xF;
+
 	// implicit conversions: <compileType> to <runtimeType>  (note: booleans are integers at runtime)
 	final int Boolean2Int = T_boolean + (T_int << 4);
-	final int Boolean2String = T_boolean + (T_String << 4);
+	final int Boolean2String = T_boolean + (T_JavaLangString << 4);
 	final int Boolean2Boolean = T_boolean + (T_boolean << 4);
 	final int Byte2Byte = T_byte + (T_byte << 4);
 	final int Byte2Short = T_byte + (T_short << 4);
@@ -78,7 +94,7 @@
 	final int Byte2Long = T_byte + (T_long << 4);
 	final int Byte2Float = T_byte + (T_float << 4);
 	final int Byte2Double = T_byte + (T_double << 4);
-	final int Byte2String = T_byte + (T_String << 4);
+	final int Byte2String = T_byte + (T_JavaLangString << 4);
 	final int Short2Byte = T_short + (T_byte << 4);
 	final int Short2Short = T_short + (T_short << 4);
 	final int Short2Char = T_short + (T_char << 4);
@@ -86,7 +102,7 @@
 	final int Short2Long = T_short + (T_long << 4);
 	final int Short2Float = T_short + (T_float << 4);
 	final int Short2Double = T_short + (T_double << 4);
-	final int Short2String = T_short + (T_String << 4);
+	final int Short2String = T_short + (T_JavaLangString << 4);
 	final int Char2Byte = T_char + (T_byte << 4);
 	final int Char2Short = T_char + (T_short << 4);
 	final int Char2Char = T_char + (T_char << 4);
@@ -94,7 +110,7 @@
 	final int Char2Long = T_char + (T_long << 4);
 	final int Char2Float = T_char + (T_float << 4);
 	final int Char2Double = T_char + (T_double << 4);
-	final int Char2String = T_char + (T_String << 4);
+	final int Char2String = T_char + (T_JavaLangString << 4);
 	final int Int2Byte = T_int + (T_byte << 4);
 	final int Int2Short = T_int + (T_short << 4);
 	final int Int2Char = T_int + (T_char << 4);
@@ -102,7 +118,7 @@
 	final int Int2Long = T_int + (T_long << 4);
 	final int Int2Float = T_int + (T_float << 4);
 	final int Int2Double = T_int + (T_double << 4);
-	final int Int2String = T_int + (T_String << 4);
+	final int Int2String = T_int + (T_JavaLangString << 4);
 	final int Long2Byte = T_long + (T_byte << 4);
 	final int Long2Short = T_long + (T_short << 4);
 	final int Long2Char = T_long + (T_char << 4);
@@ -110,7 +126,7 @@
 	final int Long2Long = T_long + (T_long << 4);
 	final int Long2Float = T_long + (T_float << 4);
 	final int Long2Double = T_long + (T_double << 4);
-	final int Long2String = T_long + (T_String << 4);
+	final int Long2String = T_long + (T_JavaLangString << 4);
 	final int Float2Byte = T_float + (T_byte << 4);
 	final int Float2Short = T_float + (T_short << 4);
 	final int Float2Char = T_float + (T_char << 4);
@@ -118,7 +134,7 @@
 	final int Float2Long = T_float + (T_long << 4);
 	final int Float2Float = T_float + (T_float << 4);
 	final int Float2Double = T_float + (T_double << 4);
-	final int Float2String = T_float + (T_String << 4);
+	final int Float2String = T_float + (T_JavaLangString << 4);
 	final int Double2Byte = T_double + (T_byte << 4);
 	final int Double2Short = T_double + (T_short << 4);
 	final int Double2Char = T_double + (T_char << 4);
@@ -126,9 +142,11 @@
 	final int Double2Long = T_double + (T_long << 4);
 	final int Double2Float = T_double + (T_float << 4);
 	final int Double2Double = T_double + (T_double << 4);
-	final int Double2String = T_double + (T_String << 4);
-	final int String2String = T_String + (T_String << 4);
-	final int Object2String = T_Object + (T_String << 4);
-	final int Null2String = T_null + (T_String << 4);
-	final int Object2Object = T_Object + (T_Object << 4);
+	final int Double2String = T_double + (T_JavaLangString << 4);
+	final int String2String = T_JavaLangString + (T_JavaLangString << 4);
+	final int Object2String = T_JavaLangObject + (T_JavaLangString << 4);
+	final int Null2String = T_null + (T_JavaLangString << 4);
+	final int Object2Object = T_JavaLangObject + (T_JavaLangObject << 4);
+	final int BOXING = 0x200;
+	final int UNBOXING = 0x400;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
new file mode 100644
index 0000000..7292cf2
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
@@ -0,0 +1,347 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import java.util.Map;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+
+/**
+ * Binding for a type parameter, held by source/binary type or method.
+ */
+public class TypeVariableBinding extends ReferenceBinding {
+
+	public Binding declaringElement; // binding of declaring type or method 
+	public int rank; // declaration rank, can be used to match variable in parameterized type
+
+	/**
+	 * Denote the first explicit (binding) bound amongst the supertypes (from declaration in source)
+	 * If no superclass was specified, then it denotes the first superinterface, or null if none was specified.
+	 */
+	public ReferenceBinding firstBound; 
+
+	// actual resolved variable supertypes (if no superclass bound, then associated to Object)
+	public ReferenceBinding superclass;
+	public ReferenceBinding[] superInterfaces; 
+	public char[] genericTypeSignature;
+
+	public TypeVariableBinding(char[] sourceName, Binding declaringElement, int rank) {
+		this.sourceName = sourceName;
+		this.declaringElement = declaringElement;
+		this.rank = rank;
+		this.modifiers = AccPublic | AccGenericSignature; // treat type var as public
+		this.tagBits |= HasTypeVariable;
+	}
+
+	public int kind() {
+		return TYPE_PARAMETER;
+	}	
+	
+	/**
+	 * Returns true if the argument type satisfies all bounds of the type parameter
+	 */
+	public boolean boundCheck(Substitution substitution, TypeBinding argumentType) {
+		if (argumentType == NullBinding || this == argumentType) 
+			return true;
+		if (!(argumentType instanceof ReferenceBinding || argumentType.isArrayType()))
+			return false;	
+		
+	    if (argumentType.isWildcard()) {
+	        WildcardBinding wildcard = (WildcardBinding) argumentType;
+	        switch (wildcard.kind) {
+	        	case Wildcard.SUPER :
+		            if (!boundCheck(substitution, wildcard.bound)) return false;
+		            break;
+				case Wildcard.UNBOUND :
+					if (this == wildcard.typeVariable()) 
+						return true;
+					break;	        		
+	        }
+	    }
+//		if (this == argumentType) 
+//			return true;
+		boolean hasSubstitution = substitution != null;
+		if (this.superclass.id != T_JavaLangObject && !argumentType.isCompatibleWith(hasSubstitution ? substitution.substitute(this.superclass) : this.superclass)) {
+		    return false;
+		}
+	    for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
+	        if (!argumentType.isCompatibleWith(hasSubstitution ? substitution.substitute(this.superInterfaces[i]) : this.superInterfaces[i])) {
+				return false;
+	        }
+	    }
+	    return true;
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#canBeInstantiated()
+	 */
+	public boolean canBeInstantiated() {
+		return false;
+	}
+	/**
+	 * Collect the substitutes into a map for certain type variables inside the receiver type
+	 * e.g.   Collection<T>.findSubstitute(T, Collection<List<X>>):   T --> List<X>
+	 */
+	public void collectSubstitutes(TypeBinding otherType, Map substitutes) {
+		// cannot infer anything from a null type
+		if (otherType == NullBinding) return;
+		
+	    TypeBinding[] variableSubstitutes = (TypeBinding[])substitutes.get(this);
+	    if (variableSubstitutes != null) {
+	        int length = variableSubstitutes.length;
+	        for (int i = 0; i < length; i++) {
+	        	TypeBinding substitute = variableSubstitutes[i];
+	            if (substitute == otherType) return; // already there
+	            if (substitute == null) {
+	                variableSubstitutes[i] = otherType;
+	                return;
+	            }
+	        }
+	        // no free spot found, need to grow
+	        System.arraycopy(variableSubstitutes, 0, variableSubstitutes = new TypeBinding[2*length], 0, length);
+	        variableSubstitutes[length] = otherType;
+	        substitutes.put(this, variableSubstitutes);
+	    }
+	}
+	
+	public char[] constantPoolName() { /* java/lang/Object */ 
+	    if (this.firstBound != null) {
+			return this.firstBound.constantPoolName();
+	    }
+	    return this.superclass.constantPoolName(); // java/lang/Object
+	}
+	/*
+	 * declaringUniqueKey : genericTypeSignature
+	 * p.X<T> { ... } --> Lp/X<TT;>;:TT;
+	 */
+	public char[] computeUniqueKey() {
+		char[] declaringKey = this.declaringElement.computeUniqueKey();
+		int declaringLength = declaringKey.length;
+		char[] sig = genericTypeSignature();
+		int sigLength = sig.length;
+		char[] uniqueKey = new char[declaringLength + 1 + sigLength];
+		System.arraycopy(declaringKey, 0, uniqueKey, 0, declaringLength);
+		uniqueKey[declaringLength] = ':';
+		System.arraycopy(sig, 0, uniqueKey, declaringLength+1, sigLength);
+		return uniqueKey;
+	}
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName()
+	 */
+	public String debugName() {
+	    return new String(this.sourceName);		
+	}		
+	public TypeBinding erasure() {
+	    if (this.firstBound != null) {
+			return this.firstBound.erasure();
+	    }
+	    return this.superclass; // java/lang/Object
+	}	
+
+/**
+ * Find supertype which erases to a given well-known type, or null if not found
+ * (using id avoids triggering the load of well-known type: 73740)
+ * NOTE: only works for erasures of well-known types, as random other types may share
+ * same id though being distincts.
+ * Override super-method since erasure() is answering firstBound (first supertype) already
+ */
+public ReferenceBinding findSuperTypeErasingTo(int erasureId, boolean erasureIsClass) {
+
+//    if (this.id == erasureId) return this; // no ID for type variable
+    ReferenceBinding currentType = this;
+    // iterate superclass to avoid recording interfaces if searched supertype is class
+    if (erasureIsClass) {
+		while ((currentType = currentType.superclass()) != null) { 
+			if (currentType.id == erasureId || currentType.erasure().id == erasureId) return currentType;
+		}    
+		return null;
+    }
+	ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
+	int lastPosition = -1;
+	do {
+		ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+		if (itsInterfaces != NoSuperInterfaces) {
+			if (++lastPosition == interfacesToVisit.length)
+				System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+			interfacesToVisit[lastPosition] = itsInterfaces;
+		}
+	} while ((currentType = currentType.superclass()) != null);
+			
+	for (int i = 0; i <= lastPosition; i++) {
+		ReferenceBinding[] interfaces = interfacesToVisit[i];
+		for (int j = 0, length = interfaces.length; j < length; j++) {
+			if ((currentType = interfaces[j]).id == erasureId || currentType.erasure().id == erasureId)
+				return currentType;
+
+			ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+			if (itsInterfaces != NoSuperInterfaces) {
+				if (++lastPosition == interfacesToVisit.length)
+					System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+				interfacesToVisit[lastPosition] = itsInterfaces;
+			}
+		}
+	}
+	return null;
+}
+/**
+ * Find supertype which erases to a given type, or null if not found
+ * Override super-method since erasure() is answering firstBound (first supertype) already
+ */
+public ReferenceBinding findSuperTypeErasingTo(ReferenceBinding erasure) {
+
+    if (this == erasure) return this;
+    ReferenceBinding currentType = this;
+    if (erasure.isClass()) {
+		while ((currentType = currentType.superclass()) != null) {
+			if (currentType == erasure || currentType.erasure() == erasure) return currentType;
+		}
+		return null;
+    }
+	ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
+	int lastPosition = -1;
+	do {
+		ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+		if (itsInterfaces != NoSuperInterfaces) {
+			if (++lastPosition == interfacesToVisit.length)
+				System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+			interfacesToVisit[lastPosition] = itsInterfaces;
+		}
+	} while ((currentType = currentType.superclass()) != null);
+			
+	for (int i = 0; i <= lastPosition; i++) {
+		ReferenceBinding[] interfaces = interfacesToVisit[i];
+		for (int j = 0, length = interfaces.length; j < length; j++) {
+			if ((currentType = interfaces[j]) == erasure || currentType.erasure() == erasure)
+				return currentType;
+
+			ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+			if (itsInterfaces != NoSuperInterfaces) {
+				if (++lastPosition == interfacesToVisit.length)
+					System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+				interfacesToVisit[lastPosition] = itsInterfaces;
+			}
+		}
+	}
+	return null;
+}
+	
+	/**
+	 * T::Ljava/util/Map;:Ljava/io/Serializable;
+	 * T:LY<TT;>
+	 */
+	public char[] genericSignature() {
+	    StringBuffer sig = new StringBuffer(10);
+	    sig.append(this.sourceName).append(':');
+	   	int interfaceLength = this.superInterfaces.length;
+	    if (interfaceLength == 0 || this.firstBound == this.superclass) {
+	        sig.append(this.superclass.genericTypeSignature());
+	    }
+		for (int i = 0; i < interfaceLength; i++) {
+		    sig.append(':').append(this.superInterfaces[i].genericTypeSignature());
+		}
+		int sigLength = sig.length();
+		char[] genericSignature = new char[sigLength];
+		sig.getChars(0, sigLength, genericSignature, 0);					
+		return genericSignature;
+	}
+	/**
+	 * T::Ljava/util/Map;:Ljava/io/Serializable;
+	 * T:LY<TT;>
+	 */
+	public char[] genericTypeSignature() {
+	    if (this.genericTypeSignature != null) return this.genericTypeSignature;
+		return this.genericTypeSignature = CharOperation.concat('T', this.sourceName, ';');
+	}
+
+	/**
+	 * Returns true if the type variable is directly bound to a given type
+	 */
+	public boolean isErasureBoundTo(TypeBinding type) {
+		if (this.superclass.erasure() == type) 
+			return true;
+		for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
+			if (this.superInterfaces[i].erasure() == type)
+				return true;
+		}
+		return false;
+	}
+	/**
+	 * Returns true if the type was declared as a type variable
+	 */
+	public boolean isTypeVariable() {
+	    return true;
+	}
+	/**
+     * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#readableName()
+     */
+    public char[] readableName() {
+        return this.sourceName;
+    }
+   
+	ReferenceBinding resolve(LookupEnvironment environment) {
+		if ((this.modifiers & AccUnresolved) == 0)
+			return this;
+	
+		if (this.superclass != null)
+			this.superclass = BinaryTypeBinding.resolveUnresolvedType(this.superclass, environment, true);
+		if (this.firstBound != null)
+			this.firstBound = BinaryTypeBinding.resolveUnresolvedType(this.firstBound, environment, true);
+		ReferenceBinding[] interfaces = this.superInterfaces;
+		for (int i = interfaces.length; --i >= 0;)
+			interfaces[i] = BinaryTypeBinding.resolveUnresolvedType(interfaces[i], environment, true);
+		this.modifiers &= ~AccUnresolved;
+	
+		// finish resolving the types
+		if (this.superclass != null)
+			this.superclass = BinaryTypeBinding.resolveType(this.superclass, environment, true);
+		if (this.firstBound != null)
+			this.firstBound = BinaryTypeBinding.resolveType(this.firstBound, environment, true);
+		for (int i = interfaces.length; --i >= 0;)
+			interfaces[i] = BinaryTypeBinding.resolveType(interfaces[i], environment, true);
+		return this;
+	}
+	
+	/**
+     * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#shortReadableName()
+     */
+    public char[] shortReadableName() {
+        return this.readableName();
+    }
+	public ReferenceBinding superclass() {
+		return superclass;
+	}
+	public ReferenceBinding[] superInterfaces() {
+		return superInterfaces;
+	}	
+	/**
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+		StringBuffer buffer = new StringBuffer(10);
+		buffer.append('<').append(this.sourceName);//.append('[').append(this.rank).append(']');
+		if (this.superclass != null && this.firstBound == this.superclass) {
+		    buffer.append(" extends ").append(this.superclass.debugName()); //$NON-NLS-1$
+		}
+		if (this.superInterfaces != null && this.superInterfaces != NoSuperInterfaces) {
+		   if (this.firstBound != this.superclass) {
+		        buffer.append(" extends "); //$NON-NLS-1$
+	        }
+		    for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
+		        if (i > 0 || this.firstBound == this.superclass) {
+		            buffer.append(" & "); //$NON-NLS-1$
+		        }
+				buffer.append(this.superInterfaces[i].debugName());
+			}
+		}
+		buffer.append('>');
+		return buffer.toString();
+	}	
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
index 65ff088..3b4e74b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
@@ -13,29 +13,67 @@
 import org.eclipse.jdt.core.compiler.CharOperation;
 
 public class UnresolvedReferenceBinding extends ReferenceBinding {
-	ReferenceBinding resolvedType;
+
+ReferenceBinding resolvedType;
+TypeBinding[] wrappers;
+
 UnresolvedReferenceBinding(char[][] compoundName, PackageBinding packageBinding) {
 	this.compoundName = compoundName;
 	this.sourceName = compoundName[compoundName.length - 1]; // reasonable guess
 	this.fPackage = packageBinding;
+	this.wrappers = null;
 }
-String debugName() {
+void addWrapper(TypeBinding wrapper) {
+	if (this.wrappers == null) {
+		this.wrappers = new TypeBinding[] {wrapper};
+	} else {
+		int length = this.wrappers.length;
+		System.arraycopy(this.wrappers, 0, this.wrappers = new TypeBinding[length + 1], 0, length);
+		this.wrappers[length] = wrapper;
+	}
+}
+public String debugName() {
 	return toString();
 }
-ReferenceBinding resolve(LookupEnvironment environment) {
-	if (resolvedType != null) return resolvedType;
-
-	ReferenceBinding environmentType = fPackage.getType0(compoundName[compoundName.length - 1]);
-	if (environmentType == this)
-		environmentType = environment.askForType(compoundName);
-	if (environmentType != null && environmentType != this) { // could not resolve any better, error was already reported against it
-		resolvedType = environmentType;
-		environment.updateArrayCache(this, environmentType);
-		return environmentType; // when found, it replaces the unresolved type in the cache
+ReferenceBinding resolve(LookupEnvironment environment, boolean convertGenericToRawType) {
+    ReferenceBinding targetType = this.resolvedType;
+	if (targetType == null) {
+		targetType = this.fPackage.getType0(this.compoundName[this.compoundName.length - 1]);
+		if (targetType == this)
+			targetType = environment.askForType(this.compoundName);
+		if (targetType != null && targetType != this) { // could not resolve any better, error was already reported against it
+			setResolvedType(targetType, environment);
+		} else {
+			environment.problemReporter.isClassPathCorrect(this.compoundName, null);
+			return null; // will not get here since the above error aborts the compilation
+		}
 	}
+	if (convertGenericToRawType) {
+		boolean rawEnclosing = false;
+		ReferenceBinding targetEnclosingType = targetType.enclosingType();
+		if (targetEnclosingType != null && targetEnclosingType.isGenericType()) { // convert to raw type since wasn't parameterized
+			rawEnclosing = true;
+			targetEnclosingType = environment.createRawType(targetEnclosingType, targetEnclosingType.enclosingType());
+		}
+		if (targetType.isGenericType()) { // raw reference to generic ?
+		    return environment.createRawType(targetType, targetEnclosingType);
+		} else if (rawEnclosing) {
+			return environment.createParameterizedType(targetType, null, targetEnclosingType);
+		}
+	}
+	return targetType;
+}
+void setResolvedType(ReferenceBinding targetType, LookupEnvironment environment) {
+	if (this.resolvedType == targetType) return; // already resolved
 
-	environment.problemReporter.isClassPathCorrect(compoundName, null);
-	return null; // will not get here since the above error aborts the compilation
+	// targetType may be a source or binary type
+	this.resolvedType = targetType;
+	// must ensure to update any other type bindings that can contain the resolved type
+	// otherwise we could create 2 : 1 for this unresolved type & 1 for the resolved type
+	if (this.wrappers != null)
+		for (int i = 0, l = this.wrappers.length; i < l; i++)
+			this.wrappers[i].swapUnresolved(this, targetType, environment);
+	environment.updateCaches(this, targetType);
 }
 public String toString() {
 	return "Unresolved type " + ((compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED"); //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
index 2e06558..00bf26f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
@@ -13,32 +13,48 @@
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 
 public abstract class VariableBinding extends Binding {
+    
 	public int modifiers;
 	public TypeBinding type;
 	public char[] name;
-	public Constant constant;
+	private Constant constant;
 	public int id; // for flow-analysis (position in flowInfo bit vector)
+	public long tagBits;
 
-public boolean isConstantValue() {
-	return constant != Constant.NotAConstant;
-}
-
-public final boolean isBlankFinal(){
-	return (modifiers & AccBlankFinal) != 0;
-}
-/* Answer true if the receiver is final and cannot be changed
-*/
-
-public final boolean isFinal() {
-	return (modifiers & AccFinal) != 0;
-}
-public char[] readableName() {
-	return name;
-}
-public String toString() {
-	String s = (type != null) ? type.debugName() : "UNDEFINED TYPE"; //$NON-NLS-1$
-	s += " "; //$NON-NLS-1$
-	s += (name != null) ? new String(name) : "UNNAMED FIELD"; //$NON-NLS-1$
-	return s;
-}
+	public VariableBinding(char[] name, TypeBinding type, int modifiers, Constant constant) {
+		this.name = name;
+		this.type = type;
+		this.modifiers = modifiers;
+		this.constant = constant;
+	}
+	
+	public Constant constant() {
+		return this.constant;
+	}
+	
+	public final boolean isBlankFinal(){
+		return (modifiers & AccBlankFinal) != 0;
+	}
+	/* Answer true if the receiver is final and cannot be changed
+	*/
+	
+	public boolean isConstantValue() {
+		return constant != Constant.NotAConstant;
+	}
+	
+	public final boolean isFinal() {
+		return (modifiers & AccFinal) != 0;
+	}
+	public char[] readableName() {
+		return name;
+	}
+	public void setConstant(Constant constant) {
+		this.constant = constant;
+	}
+	public String toString() {
+		String s = (type != null) ? type.debugName() : "UNDEFINED TYPE"; //$NON-NLS-1$
+		s += " "; //$NON-NLS-1$
+		s += (name != null) ? new String(name) : "UNNAMED FIELD"; //$NON-NLS-1$
+		return s;
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
new file mode 100644
index 0000000..5e7de03
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
@@ -0,0 +1,323 @@
+/*******************************************************************************
+ * Copyright (c) 2000-2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import java.util.Map;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+
+/*
+ * A wildcard acts as an argument for parameterized types, allowing to
+ * abstract parameterized types, e.g. List<String> is not compatible with List<Object>, 
+ * but compatible with List<?>.
+ */
+public class WildcardBinding extends ReferenceBinding {
+
+	ReferenceBinding genericType;
+	int rank;
+    public TypeBinding bound; // when unbound denotes the corresponding type variable (so as to retrieve its bound lazily)
+	char[] genericSignature;
+	public int kind;
+	ReferenceBinding superclass;
+	ReferenceBinding[] superInterfaces;
+	TypeVariableBinding typeVariable; // corresponding variable
+	LookupEnvironment environment;
+	
+	/**
+	 * When unbound, the bound denotes the corresponding type variable (so as to retrieve its bound lazily)
+	 */
+	public WildcardBinding(ReferenceBinding genericType, int rank, TypeBinding bound, int kind, LookupEnvironment environment) {
+		this.genericType = genericType;
+		this.rank = rank;
+	    this.kind = kind;
+		this.modifiers = AccPublic | AccGenericSignature; // treat wildcard as public
+		this.environment = environment;
+		initialize(genericType, bound);
+
+		if (genericType instanceof UnresolvedReferenceBinding)
+			((UnresolvedReferenceBinding) genericType).addWrapper(this);
+		if (bound instanceof UnresolvedReferenceBinding)
+			((UnresolvedReferenceBinding) bound).addWrapper(this);
+	}
+
+	public int kind() {
+		return WILDCARD_TYPE;
+	}	
+		
+	/**
+	 * Returns true if the argument type satisfies all bounds of the type parameter
+	 */
+	public boolean boundCheck(TypeBinding argumentType) {
+	    switch (this.kind) {
+	        case Wildcard.UNBOUND :
+	            return true;
+	        case Wildcard.EXTENDS :
+	            return argumentType.isCompatibleWith(this.bound);
+	        default: // SUPER
+	        	// allowed as long as one is compatible with other (either way)
+	        	// ? super Exception   ok for:  IOException, since it would be ok for (Exception)ioException
+	            return this.bound.isCompatibleWith(argumentType)
+					|| argumentType.isCompatibleWith(this.bound);
+	    }
+    }
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#canBeInstantiated()
+	 */
+	public boolean canBeInstantiated() {
+		// cannot be asked per construction
+		return false;
+	}
+	/**
+	 * Collect the substitutes into a map for certain type variables inside the receiver type
+	 * e.g.   Collection<T>.findSubstitute(T, Collection<List<X>>):   T --> List<X>
+	 */
+	public void collectSubstitutes(TypeBinding otherType, Map substitutes) {
+
+		if (this.bound == null)
+			return;
+		if (otherType.isWildcard()) {
+			WildcardBinding otherWildcard = (WildcardBinding) otherType;
+			if (otherWildcard.bound != null) {
+				this.bound.collectSubstitutes(otherWildcard.bound, substitutes);
+			}
+		} else {
+            this.bound.collectSubstitutes(otherType, substitutes);
+		}	    
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName()
+	 */
+	public String debugName() {
+	    return toString();		
+	}	
+	
+    /* (non-Javadoc)
+     * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#erasure()
+     */
+    public TypeBinding erasure() {
+    	if (this.kind == Wildcard.EXTENDS)
+	        return this.bound.erasure();
+    	return typeVariable().erasure();
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#signature()
+     */
+    public char[] genericTypeSignature() {
+        if (this.genericSignature == null) {
+            switch (this.kind) {
+                case Wildcard.UNBOUND : 
+                    this.genericSignature = WILDCARD_STAR;
+                    break;
+                case Wildcard.EXTENDS :
+                    this.genericSignature = CharOperation.concat(WILDCARD_PLUS, this.bound.genericTypeSignature());
+					break;
+				default: // SUPER
+				    this.genericSignature = CharOperation.concat(WILDCARD_MINUS, this.bound.genericTypeSignature());
+            }
+        } 
+        return this.genericSignature;
+    }
+    
+	public int hashCode() {
+		return this.genericType.hashCode();
+	}
+
+	void initialize(ReferenceBinding someGenericType, TypeBinding someBound) {
+		this.genericType = someGenericType;
+		this.bound = someBound;
+		if (someGenericType != null) {
+			this.fPackage = someGenericType.getPackage();
+		}
+		if (someBound != null) {
+		    if (someBound.isTypeVariable())
+		        this.tagBits |= HasTypeVariable;
+		}
+	}
+
+	/**
+     * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#isSuperclassOf(org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding)
+     */
+    public boolean isSuperclassOf(ReferenceBinding otherType) {
+        if (this.kind == Wildcard.SUPER) {
+            if (this.bound instanceof ReferenceBinding) {
+                return ((ReferenceBinding) this.bound).isSuperclassOf(otherType);
+            } else { // array bound
+                return otherType.id == T_JavaLangObject;
+            }
+        }
+        return false;
+    }
+
+    /**
+	 * Returns true if the type is a wildcard
+	 */
+	public boolean isUnboundWildcard() {
+	    return this.kind == Wildcard.UNBOUND;
+	}
+	
+    /**
+	 * Returns true if the type is a wildcard
+	 */
+	public boolean isWildcard() {
+	    return true;
+	}
+
+    /* (non-Javadoc)
+     * @see org.eclipse.jdt.internal.compiler.lookup.Binding#readableName()
+     */
+    public char[] readableName() {
+        switch (this.kind) {
+            case Wildcard.UNBOUND : 
+                return WILDCARD_NAME;
+            case Wildcard.EXTENDS :
+                return CharOperation.concat(WILDCARD_NAME, WILDCARD_EXTENDS, this.bound.readableName());
+			default: // SUPER
+			    return CharOperation.concat(WILDCARD_NAME, WILDCARD_SUPER, this.bound.readableName());
+        }
+    }
+    
+	ReferenceBinding resolve() {
+		BinaryTypeBinding.resolveType(this.genericType, this.environment, null, 0);
+	    switch(this.kind) {
+	        case Wildcard.EXTENDS :
+	        case Wildcard.SUPER :
+				BinaryTypeBinding.resolveType(this.bound, this.environment, null, 0);
+				break;
+			case Wildcard.UNBOUND :
+	    }
+		return this;
+	}
+	
+    /* (non-Javadoc)
+     * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName()
+     */
+    public char[] shortReadableName() {
+        switch (this.kind) {
+            case Wildcard.UNBOUND : 
+                return WILDCARD_NAME;
+            case Wildcard.EXTENDS :
+                return CharOperation.concat(WILDCARD_NAME, WILDCARD_EXTENDS, this.bound.shortReadableName());
+			default: // SUPER
+			    return CharOperation.concat(WILDCARD_NAME, WILDCARD_SUPER, this.bound.shortReadableName());
+        }
+    }
+    
+    /**
+     * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#signature()
+     */
+    public char[] signature() {
+     	// should not be called directly on a wildcard; signature should only be asked on
+    	// original methods or type erasures (which cannot denote wildcards at first level)
+		if (this.signature == null) {
+	        switch (this.kind) {
+	            case Wildcard.EXTENDS :
+	                return this.bound.signature();
+				default: // SUPER | UNBOUND
+				    return this.typeVariable().signature();
+	        }        
+		}
+		return this.signature;
+    }
+    
+    /* (non-Javadoc)
+     * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#sourceName()
+     */
+    public char[] sourceName() {
+        switch (this.kind) {
+            case Wildcard.UNBOUND : 
+                return WILDCARD_NAME;
+            case Wildcard.EXTENDS :
+                return CharOperation.concat(WILDCARD_NAME, WILDCARD_EXTENDS, this.bound.sourceName());
+			default: // SUPER
+			    return CharOperation.concat(WILDCARD_NAME, WILDCARD_SUPER, this.bound.sourceName());
+        }        
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding#superclass()
+     */
+    public ReferenceBinding superclass() {
+		if (this.superclass == null) {
+			TypeBinding superType = this.typeVariable().firstBound;
+			if (this.kind == Wildcard.EXTENDS) {
+				if (this.bound.isClass()) {
+					superType = this.bound;
+				}
+			}
+			this.superclass = superType != null && superType.isClass()
+				? (ReferenceBinding) superType
+				: environment.getType(JAVA_LANG_OBJECT);
+		}
+
+		return this.superclass;
+    }
+    /* (non-Javadoc)
+     * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superInterfaces()
+     */
+    public ReferenceBinding[] superInterfaces() {
+        if (this.superInterfaces == null) {
+        	if (this.typeVariable() != null) {
+        		this.superInterfaces = this.typeVariable.superInterfaces();
+        	} else {
+        		this.superInterfaces = NoSuperInterfaces;
+        	}
+			if (this.kind == Wildcard.EXTENDS) {
+				if (this.bound.isInterface()) {
+					// augment super interfaces with the wildcard bound
+					int length = this.superInterfaces.length;
+					System.arraycopy(this.superInterfaces, 0, this.superInterfaces = new ReferenceBinding[length+1], 1, length);
+					this.superInterfaces[0] = (ReferenceBinding) this.bound; // make bound first
+				}
+			}
+        }
+        return this.superInterfaces;
+    }
+
+	public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) {
+		boolean affected = false;
+		if (this.genericType == unresolvedType) {
+			this.genericType = resolvedType; // no raw conversion
+			affected = true;
+		} else if (this.bound == unresolvedType) {
+			this.bound = resolvedType.isGenericType() ? env.createRawType(resolvedType, resolvedType.enclosingType()) : resolvedType;
+			affected = true;
+		}
+		if (affected) 
+			initialize(this.genericType, this.bound);
+	}
+
+	/**
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+        switch (this.kind) {
+            case Wildcard.UNBOUND : 
+                return new String(WILDCARD_NAME);
+            case Wildcard.EXTENDS :
+                return new String(CharOperation.concat(WILDCARD_NAME, WILDCARD_EXTENDS, this.bound.debugName().toCharArray()));
+			default: // SUPER
+			    return new String(CharOperation.concat(WILDCARD_NAME, WILDCARD_SUPER, this.bound.debugName().toCharArray()));
+        }        
+	}		
+	/**
+	 * Returns associated type variable, or null in case of inconsistency
+	 */
+	public TypeVariableBinding typeVariable() {
+		if (this.typeVariable == null) {
+			TypeVariableBinding[] typeVariables = this.genericType.typeVariables();
+			if (this.rank < typeVariables.length)
+				this.typeVariable = typeVariables[this.rank];
+		}
+		return this.typeVariable;
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
index e206e5b..9b5dd5d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
@@ -32,6 +32,22 @@
 	public static final char[] TAG_LINK = "link".toCharArray(); //$NON-NLS-1$
 	public static final char[] TAG_LINKPLAIN = "linkplain".toCharArray(); //$NON-NLS-1$
 	public static final char[] TAG_INHERITDOC = "inheritDoc".toCharArray(); //$NON-NLS-1$
+	public static final char[] TAG_VALUE = "value".toCharArray(); //$NON-NLS-1$
+
+	// tags value
+	public static final int NO_TAG_VALUE = 0;
+	public static final int TAG_DEPRECATED_VALUE = 1;
+	public static final int TAG_PARAM_VALUE = 2;
+	public static final int TAG_RETURN_VALUE = 3;
+	public static final int TAG_THROWS_VALUE = 4;
+	public static final int TAG_EXCEPTION_VALUE = 5;
+	public static final int TAG_SEE_VALUE = 6;
+	public static final int TAG_LINK_VALUE = 7;
+	public static final int TAG_LINKPLAIN_VALUE = 8;
+	public static final int TAG_INHERITDOC_VALUE = 9;
+	public static final int TAG_VALUE_VALUE = 10;
+	public static final int TAG_OTHERS_VALUE = 11;
+	protected int tagValue = NO_TAG_VALUE;
 	
 	// tags expected positions
 	public final static int ORDERED_TAGS_NUMBER = 3;
@@ -43,26 +59,32 @@
 	public final static int COMPIL_PARSER = 0x00000001;
 	public final static int DOM_PARSER = 0x00000002;
 	
-	// Public fields
+	// Parse infos
 	public Scanner scanner;
-	public boolean checkDocComment = false;
+	public char[] source;
+	protected Parser sourceParser;
+	private int currentTokenType = -1;
 	
-	// Protected fields
+	// Options
+	public boolean checkDocComment = false;
+	public boolean reportProblems;
+	protected boolean jdk15;
+	
+	// Results
 	protected boolean inherited, deprecated;
-	protected char[] source;
+	protected Object returnStatement;
+	
+	// Positions
 	protected int index, endComment, lineEnd;
-	protected int tokenPreviousPosition;
+	protected int tokenPreviousPosition, lastIdentifierEndPosition, starPosition;
 	protected int textStart, memberStart;
 	protected int tagSourceStart, tagSourceEnd;
 	protected int inlineTagStart;
-	protected Parser sourceParser;
-	protected Object returnStatement;
-	protected boolean lineStarted = false, inlineTagStarted = false;
-	protected int kind;
 	protected int[] lineEnds;
 	
-	// Private fields
-	private int currentTokenType = -1;
+	// Flags
+	protected boolean lineStarted = false, inlineTagStarted = false;
+	protected int kind;
 	
 	// Line pointers
 	private int linePtr, lastLinePtr;
@@ -88,6 +110,7 @@
 		this.identifierLengthStack = new int[10];
 		this.astStack = new Object[30];
 		this.astLengthStack = new int[20];
+		this.reportProblems = sourceParser != null;
 	}
 
 	/* (non-Javadoc)
@@ -96,7 +119,7 @@
 	 * If javadoc checking is enabled, will also construct an Javadoc node, which will be stored into Parser.javadoc
 	 * slot for being consumed later on.
 	 */
-	protected boolean parseComment(int javadocStart, int javadocEnd) {
+	protected boolean commentParse(int javadocStart, int javadocEnd) {
 
 		boolean validComment = true;
 		try {
@@ -121,7 +144,7 @@
 			this.deprecated = false;
 			this.linePtr = getLineNumber(javadocStart);
 			this.lastLinePtr = getLineNumber(javadocEnd);
-			this.lineEnd = (this.linePtr == this.lastLinePtr) ? this.endComment : getLineEnd(this.linePtr);
+			this.lineEnd = (this.linePtr == this.lastLinePtr) ? this.endComment : this.scanner.getLineEnd(this.linePtr);
 			this.textStart = -1;
 			char previousChar = 0;
 			int invalidTagLineEnd = -1;
@@ -161,15 +184,14 @@
 				
 				switch (nextCharacter) {
 					case '@' :
-						boolean valid = false;
-						// Start tag parsing only if we have a java identifier start character and if we are on line beginning or at inline tag beginning
+						// Start tag parsing only if we are on line beginning or at inline tag beginning
 						if ((!this.lineStarted || previousChar == '{')) {
 							this.lineStarted = true;
 							if (this.inlineTagStarted) {
 								this.inlineTagStarted = false;
 								// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53279
 								// Cannot have @ inside inline comment
-								if (this.sourceParser != null) {
+								if (this.reportProblems) {
 									int end = previousPosition<invalidInlineTagLineEnd ? previousPosition : invalidInlineTagLineEnd;
 									this.sourceParser.problemReporter().javadocUnterminatedInlineTag(this.inlineTagStart, end);
 								}
@@ -191,173 +213,14 @@
 							this.scanner.resetTo(this.index, this.endComment);
 							this.currentTokenType = -1; // flush token cache at line begin
 							try {
-								int token = readTokenAndConsume();
-								this.tagSourceStart = this.scanner.getCurrentTokenStartPosition();
-								this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
-								char[] tag = this.scanner.getCurrentIdentifierSource(); // first token is either an identifier or a keyword
-								if (this.kind == DOM_PARSER) {
-									// For DOM parser, try to get tag name other than java identifier
-									// (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51660)
-									int tk = token;
-									int le = this.lineEnd;
-									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 '<':
-											case '>':
-											case '*': // break for '*' as this is perhaps the end of comment (bug 65288)
-												break tagNameToken;
-											default:
-												if (pc == ' ' || Character.isWhitespace(pc)) break tagNameToken;
-										}
-										tk = readTokenAndConsume();
-										pc = peekChar();
-									}
-									int length = this.tagSourceEnd-this.tagSourceStart+1;
-									tag = new char[length];
-									System.arraycopy(this.source, this.tagSourceStart, tag, 0, length);
-									this.index = this.tagSourceEnd+1;
-									this.scanner.currentPosition = this.tagSourceEnd+1;
-									this.tagSourceStart = previousPosition;
-									this.lineEnd = le;
-								}
-								switch (token) {
-									case TerminalTokens.TokenNameIdentifier :
-										if (CharOperation.equals(tag, TAG_DEPRECATED)) {
-											this.deprecated = true;
-											if (this.kind == DOM_PARSER) {
-												valid = parseTag();
-											} else {
-												valid = true;
-											}
-										} else if (CharOperation.equals(tag, TAG_INHERITDOC)) {
-											// 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
-											// was encountered in comment. But it cannot be the case for COMPILER_PARSER
-											// and so is enough as it is only this parser which signals the missing tag warnings...
-											this.inherited = this.astPtr==-1;
-											if (this.kind == DOM_PARSER) {
-												valid = parseTag();
-											} else {
-												valid = true;
-											}
-										} else if (CharOperation.equals(tag, TAG_PARAM)) {
-											valid = parseParam();
-										} else if (CharOperation.equals(tag, TAG_EXCEPTION)) {
-											valid = parseThrows(false);
-										} else if (CharOperation.equals(tag, TAG_SEE)) {
-											if (this.inlineTagStarted) {
-												// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
-												// Cannot have @see inside inline comment
-												valid = false;
-												if (this.sourceParser != null)
-													this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd);
-											} else {
-												valid = parseSee(false);
-											}
-										} else if (CharOperation.equals(tag, TAG_LINK)) {
-											if (this.inlineTagStarted) {
-												valid = parseSee(false);
-											} else {
-												// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
-												// Cannot have @link outside inline comment
-												valid = false;
-												if (this.sourceParser != null)
-													this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd);
-											}
-										} else if (CharOperation.equals(tag, TAG_LINKPLAIN)) {
-											if (this.inlineTagStarted) {
-												valid = parseSee(true);
-											} else {
-												valid = parseTag();
-											}
-										} else {
-											valid = parseTag();
-										}
-										break;
-									case TerminalTokens.TokenNamereturn :
-										valid = parseReturn();
-										break;
-									case TerminalTokens.TokenNamethrows :
-										valid = parseThrows(true);
-										break;
-									default:
-										if (this.kind == DOM_PARSER) {
-											switch (token) {
-												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:
-													valid = parseTag();
-													break;
-											}
-										}
-								}
-								this.textStart = this.index;
-								if (!valid) {
+								if (!parseTag(previousPosition)) {
 									// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51600
 									// do not stop the inline tag when error is encountered to get text after
 									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) {
-										parseTag();
+										createTag();
 										this.textStart = this.tagSourceEnd+1;
 										invalidTagLineEnd  = this.lineEnd;
 									}
@@ -396,7 +259,7 @@
 							this.inlineTagStarted = false;
 							// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53279
 							// Cannot have opening brace in inline comment
-							if (this.sourceParser != null) {
+							if (this.reportProblems) {
 								int end = previousPosition<invalidInlineTagLineEnd ? previousPosition : invalidInlineTagLineEnd;
 								this.sourceParser.problemReporter().javadocUnterminatedInlineTag(this.inlineTagStart, end);
 							}
@@ -412,22 +275,24 @@
 						this.inlineTagStart = previousPosition;
 						break;
 					case '*' :
-						// do nothing for '*' character
+					case '\u000c' :	/* FORM FEED               */
+					case ' ' :			/* SPACE                   */
+					case '\t' :			/* HORIZONTAL TABULATION   */
+						// do nothing for space or '*' characters
 						break;
 					default :
-						if (!CharOperation.isWhitespace(nextCharacter)) {
-							if (!this.lineStarted) {
-								this.textStart = previousPosition;
-							}
-							this.lineStarted = true;
+						if (!this.lineStarted) {
+							this.textStart = previousPosition;
 						}
+						this.lineStarted = true;
+						break;
 				}
 			}
 			// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53279
 			// Cannot leave comment inside inline comment
 			if (this.inlineTagStarted) {
 				this.inlineTagStarted = false;
-				if (this.sourceParser != null) {
+				if (this.reportProblems) {
 					int end = previousPosition<invalidInlineTagLineEnd ? previousPosition : invalidInlineTagLineEnd;
 					if (this.index >= this.endComment) end = invalidInlineTagLineEnd;
 					this.sourceParser.problemReporter().javadocUnterminatedInlineTag(this.inlineTagStart, end);
@@ -457,16 +322,59 @@
 	protected abstract Object createFieldReference(Object receiver) throws InvalidInputException;
 	protected abstract Object createMethodReference(Object receiver, List arguments) throws InvalidInputException;
 	protected Object createReturnStatement() { return null; }
+	protected abstract void createTag();
 	protected abstract Object createTypeReference(int primitiveToken);
+
+	private int getIndexPosition() {
+		if (this.index > this.lineEnd) {
+			return this.lineEnd;
+		} else {
+			return this.index-1;
+		}
+	}
+
+	/**
+	 * Search the line number corresponding to a specific position.
+	 * Warning: returned position is 1-based index!
+	 * @see Scanner#getLineNumber(int) We cannot directly use this method
+	 * when linePtr field is not initialized.
+	 */
+	private int getLineNumber(int position) {
 	
-	private int getEndPosition() {
+		if (this.scanner.linePtr != -1) {
+			return this.scanner.getLineNumber(position);
+		}
+		if (this.lineEnds == null)
+			return 1;
+		int length = this.lineEnds.length;
+		if (length == 0)
+			return 1;
+		int g = 0, d = length - 1;
+		int m = 0;
+		while (g <= d) {
+			m = (g + d) /2;
+			if (position < this.lineEnds[m]) {
+				d = m-1;
+			} else if (position > this.lineEnds[m]) {
+				g = m+1;
+			} else {
+				return m + 1;
+			}
+		}
+		if (position < this.lineEnds[m]) {
+			return m+1;
+		}
+		return m+2;
+	}
+
+	private int getTokenEndPosition() {
 		if (this.scanner.getCurrentTokenEndPosition() > this.lineEnd) {
 			return this.lineEnd;
 		} else {
 			return this.scanner.getCurrentTokenEndPosition();
 		}
 	}
-
+	
 	/*
 	 * Parse argument in @see tag method reference
 	 */
@@ -498,9 +406,11 @@
 			}
 			if (typeRef == null) {
 				if (firstArg && this.currentTokenType == TerminalTokens.TokenNameRPAREN) {
-					char pc = peekChar();
-					if (!Character.isWhitespace(pc) && (!this.inlineTagStarted || pc != '}')) {
-						if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, this.lineEnd);
+					// verify characters after arguments declaration (expecting white space or end comment)
+					if (!verifySpaceOrEndComment()) {
+						int end = this.starPosition == -1 ? this.lineEnd : this.starPosition;
+						if (this.source[end]=='\n') end--;
+						if (this.reportProblems) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
 						return null;
 					}
 					this.lineStarted = true;
@@ -566,9 +476,11 @@
 				consumeToken();
 				iToken++;
 			} else if (token == TerminalTokens.TokenNameRPAREN) {
-				char pc = peekChar();
-				if (!Character.isWhitespace(pc) && (!this.inlineTagStarted || pc != '}')) {
-					if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, this.lineEnd);
+				// verify characters after arguments declaration (expecting white space or end comment)
+				if (!verifySpaceOrEndComment()) {
+					int end = this.starPosition == -1 ? this.lineEnd : this.starPosition;
+					if (this.source[end]=='\n') end--;
+					if (this.reportProblems) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
 					return null;
 				}
 				// Create new argument
@@ -593,28 +505,48 @@
 		if (Character.toLowerCase(readChar()) == 'a') {
 			this.scanner.currentPosition = this.index;
 			if (readToken() == TerminalTokens.TokenNameIdentifier) {
-				this.currentTokenType = -1; // do not update line end
+				consumeToken();
 				try {
 					if (CharOperation.equals(this.scanner.getCurrentIdentifierSource(), new char[]{'h', 'r', 'e', 'f'}, false) &&
 						readToken() == TerminalTokens.TokenNameEQUAL) {
-						this.currentTokenType = -1; // do not update line end
+						consumeToken();
 						if (readToken() == TerminalTokens.TokenNameStringLiteral) {
-							this.currentTokenType = -1; // do not update line end
-							if (readToken() == TerminalTokens.TokenNameGREATER) {
+							consumeToken();
+							// Skip all characters after string literal until closing '>' (see bug 68726)
+							while (readToken() != TerminalTokens.TokenNameGREATER) {
+								if (this.scanner.currentPosition >= this.scanner.eofPosition || this.scanner.currentCharacter == '@' ||
+									(this.inlineTagStarted && this.scanner.currentCharacter == '}')) {
+									// Reset position: we want to rescan last token
+									this.index = this.tokenPreviousPosition;
+									this.scanner.currentPosition = this.tokenPreviousPosition;
+									this.currentTokenType = -1;
+									// Signal syntax error
+									if (this.tagValue != TAG_VALUE_VALUE) { // do not report error for @value tag, this will be done after...
+										if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidSeeUrlReference(start, this.lineEnd);
+									}
+									return false;
+								}
+								this.currentTokenType = -1; // do not update line end
+							}
+							if (this.currentTokenType == TerminalTokens.TokenNameGREATER) {
 								consumeToken(); // update line end as new lines are allowed in URL description
 								while (readToken() != TerminalTokens.TokenNameLESS) {
-									if (this.scanner.currentPosition >= this.scanner.eofPosition || this.scanner.currentCharacter == '@') {
+									if (this.scanner.currentPosition >= this.scanner.eofPosition || this.scanner.currentCharacter == '@' ||
+										(this.inlineTagStarted && this.scanner.currentCharacter == '}')) {
 										// Reset position: we want to rescan last token
 										this.index = this.tokenPreviousPosition;
 										this.scanner.currentPosition = this.tokenPreviousPosition;
 										this.currentTokenType = -1;
 										// Signal syntax error
-										if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeUrlReference(start, this.lineEnd);
+										if (this.tagValue != TAG_VALUE_VALUE) { // do not report error for @value tag, this will be done after...
+											if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidSeeUrlReference(start, this.lineEnd);
+										}
 										return false;
 									}
 									consumeToken();
 								}
-								this.currentTokenType = -1; // do not update line end
+								consumeToken();
+								start = this.scanner.getCurrentTokenStartPosition();
 								if (readChar() == '/') {
 									if (Character.toLowerCase(readChar()) == 'a') {
 										if (readChar() == '>') {
@@ -636,7 +568,9 @@
 		this.scanner.currentPosition = this.tokenPreviousPosition;
 		this.currentTokenType = -1;
 		// Signal syntax error
-		if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeUrlReference(start, this.lineEnd);
+		if (this.tagValue != TAG_VALUE_VALUE) { // do not report error for @value tag, this will be done after...
+			if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidSeeUrlReference(start, this.lineEnd);
+		}
 		return false;
 	}
 
@@ -649,11 +583,12 @@
 		this.identifierLengthPtr = -1;
 		int start = this.scanner.getCurrentTokenStartPosition();
 		this.memberStart = start;
-
+	
 		// Get member identifier
 		if (readToken() == TerminalTokens.TokenNameIdentifier) {
 			consumeToken();
 			pushIdentifier(true);
+			// Look for next token to know whether it's a field or method reference
 			int previousPosition = this.index;
 			if (readToken() == TerminalTokens.TokenNameLPAREN) {
 				consumeToken();
@@ -665,21 +600,28 @@
 							this.scanner.getCurrentTokenEndPosition() :
 							this.scanner.getCurrentTokenStartPosition();
 					end = end < this.lineEnd ? end : this.lineEnd;
-					if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReferenceArgs(start, end);
+					if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidSeeReferenceArgs(start, end);
 				}
 				return null;
 			}
+	
 			// Reset position: we want to rescan last token
-			if (this.currentTokenType != -1) {
-				this.index = previousPosition;
-				this.scanner.currentPosition = previousPosition;
-				this.currentTokenType = -1;
+			this.index = previousPosition;
+			this.scanner.currentPosition = previousPosition;
+			this.currentTokenType = -1;
+	
+			// Verify character(s) after identifier (expecting space or end comment)
+			if (!verifySpaceOrEndComment()) {
+				int end = this.starPosition == -1 ? this.lineEnd : this.starPosition;
+				if (this.source[end]=='\n') end--;
+				if (this.reportProblems) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
+				return null;
 			}
 			return createFieldReference(receiver);
 		}
-		int end = getEndPosition() - 1;
-		end = start > end ? getEndPosition() : end;
-		if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(start, end);
+		int end = getTokenEndPosition() - 1;
+		end = start > end ? start : end;
+		if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidReference(start, end);
 		// Reset position: we want to rescan last token
 		this.index = this.tokenPreviousPosition;
 		this.scanner.currentPosition = this.tokenPreviousPosition;
@@ -690,38 +632,201 @@
 	/*
 	 * Parse @param tag declaration
 	 */
-	protected boolean parseParam() {
+	protected boolean parseParam() throws InvalidInputException {
 
-		// Store current token state
+		// Store current state
 		int start = this.tagSourceStart;
 		int end = this.tagSourceEnd;
-
-		try {
-			// Push identifier next
-			int token = readToken();
+		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) {
+			if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidTag(start, this.scanner.getCurrentTokenEndPosition());
+			this.scanner.currentPosition = start;
+			this.index = start;
+			this.currentTokenType = -1;
+			this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
+			return false;
+		}
+		
+		// Get first non whitespace token
+		this.identifierPtr = -1;
+		this.identifierLengthPtr = -1;
+		boolean hasMultiLines = this.scanner.currentPosition > (this.lineEnd+1);
+		boolean isTypeParam = false;
+		boolean valid = true, empty = true;
+		nextToken: while (true) {
+			this.currentTokenType = -1;
+			try {
+				token = readToken();
+			} catch (InvalidInputException e) {
+				valid = false;
+			}
 			switch (token) {
 				case TerminalTokens.TokenNameIdentifier :
-					consumeToken();
-					return pushParamName();
-				case TerminalTokens.TokenNameEOF :
-					break;
-				default :
-					start = this.scanner.getCurrentTokenStartPosition();
-					end = getEndPosition();
-					if (end < start) start = this.tagSourceStart;
-					break;
+					if (valid) { 
+						// store param name id
+						pushIdentifier(true);
+						start = this.scanner.getCurrentTokenStartPosition();
+						end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+						break nextToken;
+					}
+					// fall through next case to report error
+				case TerminalTokens.TokenNameLESS:
+					if (valid && this.jdk15) {
+						// store '<' in identifiers stack as we need to add it to tag element (bug 79809)
+						pushIdentifier(true);
+						start = this.scanner.getCurrentTokenStartPosition();
+						end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+						isTypeParam = true;
+						break nextToken;
+					}
+					// fall through next case to report error
+				default:
+					if (token == TerminalTokens.TokenNameLEFT_SHIFT) isTypeParam = true;
+					if (valid && !hasMultiLines) start = this.scanner.getCurrentTokenStartPosition();
+					valid = false;
+					if (!hasMultiLines) {
+						empty = false;
+						end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+						break;
+					}
+					end = this.lineEnd;
+					// when several lines, fall through next case to report problem immediately
+				case TerminalTokens.TokenNameWHITESPACE:
+					if (this.scanner.currentPosition > (this.lineEnd+1)) hasMultiLines = true;
+					if (valid) break;
+					// if not valid fall through next case to report error
+				case TerminalTokens.TokenNameEOF:
+					if (this.reportProblems)
+						if (empty)
+							this.sourceParser.problemReporter().javadocMissingParamName(start, end, this.sourceParser.modifiers);
+						else if (this.jdk15 && isTypeParam)
+							this.sourceParser.problemReporter().javadocInvalidParamTypeParameter(start, end);
+						else
+							this.sourceParser.problemReporter().javadocInvalidParamTagName(start, end);
+					this.scanner.currentPosition = start;
+					this.index = start;
+					this.currentTokenType = -1;
+					this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
+					return false;
 			}
-		} catch (InvalidInputException e) {
-			end = getEndPosition();
 		}
-
-		// Reset position to avoid missing tokens when new line was encountered
-		this.index = this.tokenPreviousPosition;
-		this.scanner.currentPosition = this.tokenPreviousPosition;
-		this.currentTokenType = -1;
-
+		
+		// Scan more tokens for type parameter declaration
+		if (isTypeParam && this.jdk15) {
+			// Get type parameter name
+			nextToken: while (true) {
+				this.currentTokenType = -1;
+				try {
+					token = readToken();
+				} catch (InvalidInputException e) {
+					valid = false;
+				}
+				switch (token) {
+					case TerminalTokens.TokenNameWHITESPACE:
+						if (valid && this.scanner.currentPosition <= (this.lineEnd+1)) break;
+						// 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;
+						this.currentTokenType = -1;
+						this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
+						return false;
+					case TerminalTokens.TokenNameIdentifier :
+						end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+						if (valid) {
+							// store param name id
+							pushIdentifier(false);
+							break nextToken;
+						}
+						break;
+					default:
+						end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+						valid = false;
+						break;
+				}
+			}
+			
+			// Get last character of type parameter declaration
+			boolean spaces = false;
+			nextToken: while (true) {
+				this.currentTokenType = -1;
+				try {
+					token = readToken();
+				} catch (InvalidInputException e) {
+					valid = false;
+				}
+				switch (token) {
+					case TerminalTokens.TokenNameWHITESPACE:
+						if (this.scanner.currentPosition > (this.lineEnd+1)) {
+							// do not accept type parameter declaration on several lines
+							hasMultiLines = true;
+							valid = false;
+						}
+						spaces = true;
+						if (valid) break;
+						// 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;
+						this.currentTokenType = -1;
+						this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
+						return false;
+					case TerminalTokens.TokenNameGREATER:
+						end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+						if (valid) {
+							// store '>' in identifiers stack as we need to add it to tag element (bug 79809)
+							pushIdentifier(false);
+							break nextToken;
+						}
+						break;
+					default:
+						if (!spaces) end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+						valid = false;
+						break;
+				}
+			}
+		}
+		
+		// Verify that tag name is well followed by white spaces
+		if (valid) {
+			this.currentTokenType = -1;
+			int restart = this.scanner.currentPosition;
+			try {
+				token = readToken();
+			} catch (InvalidInputException e) {
+				valid = false;
+			}
+			if (token == TerminalTokens.TokenNameWHITESPACE) {
+				this.scanner.currentPosition = restart;
+				this.index = restart;
+				this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
+				return pushParamName(isTypeParam);
+			}
+		}
+		
 		// Report problem
-		if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMissingParamName(start, end);
+		this.currentTokenType = -1;
+		end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+		while (readToken() != TerminalTokens.TokenNameWHITESPACE) {
+			this.currentTokenType = -1;
+			end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+		}
+		if (this.reportProblems)
+			if (this.jdk15 && isTypeParam)
+				this.sourceParser.problemReporter().javadocInvalidParamTypeParameter(start, end);
+			else
+				this.sourceParser.problemReporter().javadocInvalidParamTagName(start, end);
+		this.scanner.currentPosition = start;
+		this.index = start;
+		this.currentTokenType = -1;
+		this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
 		return false;
 	}
 
@@ -795,129 +900,144 @@
 			this.scanner.currentPosition = this.tokenPreviousPosition;
 			this.currentTokenType = -1;
 		}
+		this.lastIdentifierEndPosition = (int) this.identifierPositionStack[this.identifierPtr];
 		return createTypeReference(primitiveToken);
 	}
 
 	/*
 	 * Parse a reference in @see tag
 	 */
-	protected boolean parseReference(boolean plain) throws InvalidInputException {
-		Object typeRef = null;
-		Object reference = null;
-		int previousPosition = -1;
-		nextToken : while (this.index < this.scanner.eofPosition) {
-			previousPosition = this.index;
-			int token = readToken();
-			switch (token) {
-				case TerminalTokens.TokenNameStringLiteral :
-					// @see "string"
-					int start = this.scanner.getCurrentTokenStartPosition();
-					if (typeRef == null) {
+	protected boolean parseReference() throws InvalidInputException {
+		int currentPosition = this.scanner.currentPosition;
+		try {
+			Object typeRef = null;
+			Object reference = null;
+			int previousPosition = -1;
+			int typeRefStartPosition = -1;
+			
+			// Get reference tokens
+			nextToken : while (this.index < this.scanner.eofPosition) {
+				previousPosition = this.index;
+				int token = readToken();
+				switch (token) {
+					case TerminalTokens.TokenNameStringLiteral : // @see "string"
 						consumeToken();
-						while (Character.isWhitespace(this.source[this.index])) {
-							if (this.source[this.index] == '\r' || this.source[this.index] == '\n') {
-								if (this.kind == DOM_PARSER) {
-									parseTag();
-									pushText(previousPosition, this.index);
-								}
-								return true;
-							}
-							this.index++;
+						int start = this.scanner.getCurrentTokenStartPosition();
+						if (this.tagValue == TAG_VALUE_VALUE) {
+							// String reference are not allowed for @value tag
+							if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidValueReference(start, getTokenEndPosition(), this.sourceParser.modifiers);
+							return false;
 						}
-					}
-					if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(start, this.lineEnd);
-					return false;
-				case TerminalTokens.TokenNameLESS :
-					// @see "<a href="URL#Value">label</a>
-					consumeToken();
-					start = this.scanner.getCurrentTokenStartPosition();
-					if (parseHref()) {
-						if (typeRef == null) {
+						// If typeRef != null we may raise a warning here to let user know there's an unused reference...
+						// Currently as javadoc 1.4.2 ignore it, we do the same (see bug 69302)
+						if (typeRef != null) {
+							start = this.tagSourceEnd+1;
+							previousPosition = start;
+							typeRef = null;
+						}
+						// verify end line
+						if (verifyEndLine(previousPosition)) {
+							return true;
+						}
+						if (this.reportProblems) this.sourceParser.problemReporter().javadocUnexpectedText(this.scanner.currentPosition, this.lineEnd);
+						return false;
+					case TerminalTokens.TokenNameLESS : // @see "<a href="URL#Value">label</a>
+						consumeToken();
+						start = this.scanner.getCurrentTokenStartPosition();
+						if (parseHref()) {
 							consumeToken();
-							while (Character.isWhitespace(this.source[this.index])) {
-								if (this.source[this.index] == '\r' || this.source[this.index] == '\n') {
-									if (this.kind == DOM_PARSER) {
-										parseTag();
-										pushText(previousPosition, this.index);
-									}
-									return true;
-								}
-								this.index++;
+							// If typeRef != null we may raise a warning here to let user know there's an unused reference...
+							// Currently as javadoc 1.4.2 ignore it, we do the same (see bug 69302)
+							if (typeRef != null) {
+								start = this.tagSourceEnd+1;
+								previousPosition = start;
+								typeRef = null;
 							}
+							if (this.tagValue == TAG_VALUE_VALUE) {
+								// String reference are not allowed for @value tag
+								if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidValueReference(start, getIndexPosition(), this.sourceParser.modifiers);
+								return false;
+							}
+							// verify end line
+							if (verifyEndLine(previousPosition)) return true;
+							if (this.reportProblems) this.sourceParser.problemReporter().javadocUnexpectedText(this.scanner.currentPosition, this.lineEnd);
 						}
-						if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(start, this.lineEnd);
-					}
-					return false;
-				case TerminalTokens.TokenNameERROR :
-					if (this.scanner.currentCharacter == '#') { // @see ...#member
-						consumeToken();
-						reference = parseMember(typeRef);
-						if (reference != null) {
-							return pushSeeRef(reference, plain);
+						else if (this.tagValue == TAG_VALUE_VALUE) {
+							if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidValueReference(start, getIndexPosition(), this.sourceParser.modifiers);
 						}
 						return false;
-					}
-					break nextToken;
-				case TerminalTokens.TokenNameIdentifier :
-					if (typeRef == null) {
-						typeRef = parseQualifiedName(true);
-						break;
-					}
-					break nextToken;
-				default :
-					break nextToken;
-			}
-		}
-		
-		// Verify that we got a reference
-		if (reference == null) reference = typeRef;
-		if (reference == null) {
-			this.index = this.tokenPreviousPosition;
-			this.scanner.currentPosition = this.tokenPreviousPosition;
-			this.currentTokenType = -1;
-			if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMissingSeeReference(this.tagSourceStart, this.tagSourceEnd);
-			return false;
-		}
-
-		// Verify that line end does not start with an open parenthese (which could be a constructor reference wrongly written...)
-		// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=47215
-		int start = this.scanner.getCurrentTokenStartPosition();
-		try {
-			int token = readToken();
-			if (token != TerminalTokens.TokenNameLPAREN) {
-				// Reset position: we want to rescan last token
-				if (this.currentTokenType != -1) {
-					this.index = this.tokenPreviousPosition;
-					this.scanner.currentPosition = this.tokenPreviousPosition;
-					this.currentTokenType = -1;
+					case TerminalTokens.TokenNameERROR :
+						if (this.scanner.currentCharacter == '#') { // @see ...#member
+							consumeToken();
+							reference = parseMember(typeRef);
+							if (reference != null) {
+								return pushSeeRef(reference);
+							}
+							return false;
+						}
+						break nextToken;
+					case TerminalTokens.TokenNameIdentifier :
+						if (typeRef == null) {
+							typeRefStartPosition = this.scanner.getCurrentTokenStartPosition();
+							typeRef = parseQualifiedName(true);
+							break;
+						}
+					default :
+						break nextToken;
 				}
-				return pushSeeRef(reference, plain);
 			}
-		} catch (InvalidInputException e) {
-			// Do nothing as we report an error after
+
+			// Verify that we got a reference
+			if (reference == null) reference = typeRef;
+			if (reference == null) {
+				this.index = this.tokenPreviousPosition;
+				this.scanner.currentPosition = this.tokenPreviousPosition;
+				this.currentTokenType = -1;
+				if (this.tagValue == TAG_VALUE_VALUE) {
+					if (this.kind == DOM_PARSER) createTag();
+					return true;
+				}
+				if (this.reportProblems) {
+					this.sourceParser.problemReporter().javadocMissingReference(this.tagSourceStart, this.tagSourceEnd, this.sourceParser.modifiers);
+				}
+				return false;
+			}
+
+			// Reset position at the end of type reference
+			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)
+			if (this.tagValue == TAG_VALUE_VALUE) {
+				if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidReference(typeRefStartPosition, this.lineEnd);
+				return false;
+			}
+
+			// Verify that line end does not start with an open parenthese (which could be a constructor reference wrongly written...)
+			// See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=47215
+			char ch = peekChar();
+			if (ch == '(') {
+				if (this.reportProblems) this.sourceParser.problemReporter().javadocMissingHashCharacter(typeRefStartPosition, this.lineEnd, String.valueOf(this.source, typeRefStartPosition, this.lineEnd-typeRefStartPosition+1));
+				return false;
+			}
+
+			// Verify that we get white space after reference
+			if (!verifySpaceOrEndComment()) {
+				this.index = this.tokenPreviousPosition;
+				this.scanner.currentPosition = this.tokenPreviousPosition;
+				this.currentTokenType = -1;
+				int end = this.starPosition == -1 ? this.lineEnd : this.starPosition;
+				if (this.source[end]=='\n') end--;
+				if (this.reportProblems) this.sourceParser.problemReporter().javadocMalformedSeeReference(typeRefStartPosition, end);
+				return false;
+			}
+			
+			// Everything is OK, store reference
+			return pushSeeRef(reference);
 		}
-		// Reset position to avoid missing tokens when new line was encountered
-		this.index = this.tokenPreviousPosition;
-		this.scanner.currentPosition = this.tokenPreviousPosition;
-		this.currentTokenType = -1;
-		if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(start, this.lineEnd);
-		return false;
-	}
-
-	/*
-	 * Parse @return tag declaration
-	 */
-	protected abstract boolean parseReturn();
-
-	/*
-	 * Parse @see tag declaration
-	 */
-	protected boolean parseSee(boolean plain) {
-		int start = this.scanner.currentPosition;
-		try {
-			return parseReference(plain);
-		} catch (InvalidInputException ex) {
-				if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(start, getEndPosition());
+		catch (InvalidInputException ex) {
+			if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidReference(currentPosition, getTokenEndPosition());
 		}
 		// Reset position to avoid missing tokens when new line was encountered
 		this.index = this.tokenPreviousPosition;
@@ -927,28 +1047,49 @@
 	}
 
 	/*
-	 * Parse @return tag declaration
+	 * Parse tag declaration
 	 */
-	protected abstract boolean parseTag();
+	protected abstract boolean parseTag(int previousPosition) throws InvalidInputException;
 
 	/*
 	 * Parse @throws tag declaration
 	 */
-	protected boolean parseThrows(boolean real) {
+	protected boolean parseThrows() {
 		int start = this.scanner.currentPosition;
 		try {
 			Object typeRef = parseQualifiedName(true);
 			if (typeRef == null) {
-				if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMissingThrowsClassName(this.tagSourceStart, this.tagSourceEnd);
+				if (this.reportProblems)
+					this.sourceParser.problemReporter().javadocMissingThrowsClassName(this.tagSourceStart, this.tagSourceEnd, this.sourceParser.modifiers);
 			} else {
-				return pushThrowName(typeRef, real);
+				return pushThrowName(typeRef);
 			}
 		} catch (InvalidInputException ex) {
-			if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidThrowsClass(start, getEndPosition());
+			if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidThrowsClass(start, getTokenEndPosition());
 		}
 		return false;
 	}
-	
+
+	/*
+	 * Return current character without move index position.
+	 */
+	protected char peekChar() {
+		int idx = this.index;
+		char c = this.source[idx++];
+		if (c == '\\' && this.source[idx] == 'u') {
+			int c1, c2, c3, c4;
+			idx++;
+			while (this.source[idx] == 'u')
+				idx++;
+			if (!(((c1 = Character.getNumericValue(this.source[idx++])) > 15 || c1 < 0)
+					|| ((c2 = Character.getNumericValue(this.source[idx++])) > 15 || c2 < 0)
+					|| ((c3 = Character.getNumericValue(this.source[idx++])) > 15 || c3 < 0) || ((c4 = Character.getNumericValue(this.source[idx++])) > 15 || c4 < 0))) {
+				c = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+			}
+		}
+		return c;
+	}
+
 	/*
 	 * push the consumeToken on the identifier stack. Increase the total number of identifier in the stack.
 	 */
@@ -1020,42 +1161,22 @@
 	/*
 	 * Push a param name in ast node stack.
 	 */
-	protected abstract boolean pushParamName();
+	protected abstract boolean pushParamName(boolean isTypeParam);
 
 	/*
 	 * Push a reference statement in ast node stack.
 	 */
-	protected abstract boolean pushSeeRef(Object statement, boolean plain);
-
-	protected abstract void pushText(int start, int end);
-	protected void refreshInlineTagPosition(int previousPosition) {
-		// do nothing by default
-	}
+	protected abstract boolean pushSeeRef(Object statement);
 
 	/*
-	 * Return current character without move index position.
+	 * Push a text element in ast node stack
 	 */
-	private char peekChar() {
-		int idx = this.index;
-		char c = this.source[idx++];
-		if (c == '\\' && this.source[idx] == 'u') {
-			int c1, c2, c3, c4;
-			idx++;
-			while (this.source[idx] == 'u')
-				idx++;
-			if (!(((c1 = Character.getNumericValue(this.source[idx++])) > 15 || c1 < 0)
-					|| ((c2 = Character.getNumericValue(this.source[idx++])) > 15 || c2 < 0)
-					|| ((c3 = Character.getNumericValue(this.source[idx++])) > 15 || c3 < 0) || ((c4 = Character.getNumericValue(this.source[idx++])) > 15 || c4 < 0))) {
-				c = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
-			}
-		}
-		return c;
-	}
+	protected abstract void pushText(int start, int end);
 
 	/*
 	 * Push a throws type ref in ast node stack.
 	 */
-	protected abstract boolean pushThrowName(Object typeRef, boolean real);
+	protected abstract boolean pushThrowName(Object typeRef);
 
 	/*
 	 * Read current character and move index position.
@@ -1101,11 +1222,18 @@
 		return this.currentTokenType;
 	}
 
-	private int readTokenAndConsume() throws InvalidInputException {
+	protected int readTokenAndConsume() throws InvalidInputException {
 		int token = readToken();
 		consumeToken();
 		return token;
 	}
+	
+	/*
+	 * Refresh start position and length of an inline tag.
+	 */
+	protected void refreshInlineTagPosition(int previousPosition) {
+		// do nothing by default
+	}
 
 	public String toString() {
 		StringBuffer buffer = new StringBuffer();
@@ -1159,73 +1287,127 @@
 	}
 
 	/*
+	 * Update 
+	 */
+	protected abstract void updateDocComment();
+
+	/*
 	 * Update line end
 	 */
 	protected void updateLineEnd() {
 		while (this.index > (this.lineEnd+1)) { // be sure to be on next line (lineEnd is still on the same line)
 			if (this.linePtr < this.lastLinePtr) {
-				this.lineEnd = getLineEnd(++this.linePtr) - 1;
+				this.lineEnd = this.scanner.getLineEnd(++this.linePtr) - 1;
 			} else {
 				this.lineEnd = this.endComment;
 				return;
 			}
 		}
 	}
-	protected abstract void updateDocComment();
 
-	/**
-	 * Search the line number corresponding to a specific position.
-	 * Warning: returned position is 1-based index!
-	 * @see Scanner#getLineNumber(int) We cannot directly use this method
-	 * when linePtr field is not initialized.
+	/*
+	 * 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.
 	 */
-	public final int getLineNumber(int position) {
-	
-		if (this.scanner.linePtr != -1) {
-			return this.scanner.getLineNumber(position);
-		}
-		if (this.lineEnds == null)
-			return 1;
-		int length = this.lineEnds.length;
-		if (length == 0)
-			return 1;
-		int g = 0, d = length - 1;
-		int m = 0;
-		while (g <= d) {
-			m = (g + d) /2;
-			if (position < this.lineEnds[m]) {
-				d = m-1;
-			} else if (position > this.lineEnds[m]) {
-				g = m+1;
-			} else {
-				return m + 1;
+	private boolean verifyEndLine(int textPosition) {
+		// Special case for inline tag
+		if (this.inlineTagStarted) {
+			// expecting closing brace
+			if (peekChar() == '}') {
+				if (this.kind == DOM_PARSER) {
+					createTag();
+					pushText(textPosition, this.starPosition);
+				}
+				return true;
 			}
+			return false;
 		}
-		if (position < this.lineEnds[m]) {
-			return m+1;
+		
+		int startPosition = this.index;
+		int previousPosition = this.index;
+		this.starPosition = -1;
+		char ch = readChar();
+		nextChar: while (true) {
+			switch (ch) {
+				case '\r':
+				case '\n':
+					if (this.kind == DOM_PARSER) {
+						createTag();
+						pushText(textPosition, previousPosition);
+					}
+					this.index = previousPosition;
+					return true;
+				case '\u000c' :	/* FORM FEED               */
+				case ' ' :			/* SPACE                   */
+				case '\t' :			/* HORIZONTAL TABULATION   */
+					if (this.starPosition >= 0) break nextChar;
+					break;
+				case '*':
+					this.starPosition = previousPosition;
+					break;
+				case '/':
+					if (this.starPosition >= textPosition) {
+						if (this.kind == DOM_PARSER) {
+							createTag();
+							pushText(textPosition, this.starPosition);
+						}
+						return true;
+					}
+				default :
+					// leave loop
+					break nextChar;
+				
+			}
+			previousPosition = this.index;
+			ch = readChar();
 		}
-		return m+2;
+		this.index = startPosition;
+		return false;
 	}
 
-	/**
-	 * Search the source position corresponding to the end of a given line number.
-	 * Warning: returned position is 1-based index!
-	 * @see Scanner#getLineEnd(int) We cannot directly use this method
-	 * when linePtr field is not initialized.
+	/*
+	 * Verify characters after a name matches one of following conditions:
+	 * 	1- first character is a white space
+	 * 	2- first character is a closing brace *and* we're currently parsing an inline tag
+	 * 	3- are the end of comment (several contiguous star ('*') characters may be
+	 * 	    found before the last slash ('/') character).
 	 */
-	public final int getLineEnd(int lineNumber) {
-	
-		if (this.scanner.linePtr != -1) {
-			return this.scanner.getLineEnd(lineNumber);
+	private boolean verifySpaceOrEndComment() {
+		int startPosition = this.index;
+		// Whitespace or inline tag closing brace
+		char ch = peekChar();
+		switch (ch) {
+			case '}':
+				return this.inlineTagStarted;
+			default:
+				if (Character.isWhitespace(ch)) {
+					return true;
+				}
 		}
-		if (this.lineEnds == null) 
-			return -1;
-		if (lineNumber > this.lineEnds.length+1) 
-			return -1;
-		if (lineNumber <= 0) 
-			return -1;
-		if (lineNumber == this.lineEnds.length + 1) 
-			return this.scanner.eofPosition;
-		return this.lineEnds[lineNumber-1]; // next line start one character behind the lineEnd of the previous line
+		// End of comment
+		int previousPosition = this.index;
+		this.starPosition = -1;
+		ch = readChar();
+		nextChar: while (this.index<this.source.length) {
+			switch (ch) {
+				case '*':
+					// valid whatever the number of star before last '/'
+					this.starPosition = previousPosition;
+					break;
+				case '/':
+					if (this.starPosition >= startPosition) { // valid only if a star was previous character
+						return true;
+					}
+				default :
+					// invalid whatever other character, even white spaces
+					this.index = startPosition;
+					return false;
+				
+			}
+			previousPosition = this.index;
+			ch = readChar();
+		}
+		this.index = startPosition;
+		return false;
 	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java
index e6adf1d..a136baf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java
@@ -14,20 +14,8 @@
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
-import org.eclipse.jdt.internal.compiler.ast.Expression;
-import org.eclipse.jdt.internal.compiler.ast.ImplicitDocTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.Javadoc;
-import org.eclipse.jdt.internal.compiler.ast.JavadocAllocationExpression;
-import org.eclipse.jdt.internal.compiler.ast.JavadocArgumentExpression;
-import org.eclipse.jdt.internal.compiler.ast.JavadocArrayQualifiedTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.JavadocArraySingleTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.JavadocFieldReference;
-import org.eclipse.jdt.internal.compiler.ast.JavadocMessageSend;
-import org.eclipse.jdt.internal.compiler.ast.JavadocQualifiedTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.JavadocReturnStatement;
-import org.eclipse.jdt.internal.compiler.ast.JavadocSingleNameReference;
-import org.eclipse.jdt.internal.compiler.ast.JavadocSingleTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 
@@ -41,12 +29,16 @@
 	
 	// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51600
 	// Store param references for tag with invalid syntax
-	private int invParamsPtr = -1;
-	private JavadocSingleNameReference[] invParamsStack;
+	private int invalidParamReferencesPtr = -1;
+	private ASTNode[] invalidParamReferencesStack;
 
-	JavadocParser(Parser sourceParser) {
+	// Store current tag stack pointer
+	private int currentAstPtr= -2;
+
+	public JavadocParser(Parser sourceParser) {
 		super(sourceParser);
 		this.checkDocComment = this.sourceParser.options.docCommentSupport;
+		this.jdk15 = this.sourceParser.options.sourceLevel >= ClassFileConstants.JDK1_5;
 		this.kind = COMPIL_PARSER;
 	}
 
@@ -68,7 +60,7 @@
 				this.scanner.linePtr = this.sourceParser.scanner.linePtr;
 				this.lineEnds = this.scanner.lineEnds;
 				this.docComment = new Javadoc(javadocStart, javadocEnd);
-				parseComment(javadocStart, javadocEnd);
+				commentParse(javadocStart, javadocEnd);
 			} else {
 				// Init javadoc if necessary
 				if (this.sourceParser.options.getSeverity(CompilerOptions.MissingJavadocComments) != ProblemSeverities.Ignore) {
@@ -93,12 +85,13 @@
 					nextCharacter : while (this.index < this.lineEnd) {
 						char c = readChar(); // consider unicodes
 						switch (c) {
-						    default : 
-						        if (Character.isWhitespace(c)) {
-						            continue nextCharacter;
-						        }
-						        break;
-						    case '*' :
+							case '*' :
+							case '\u000c' :	/* FORM FEED               */
+							case ' ' :			/* SPACE                   */
+							case '\t' :			/* HORIZONTAL TABULATION   */
+							case '\n' :			/* LINE FEED   */
+							case '\r' :			/* CR */
+								// do nothing for space or '*' characters
 						        continue nextCharacter;
 						    case '@' :
 						        if ((readChar() == 'd') && (readChar() == 'e') &&
@@ -165,7 +158,7 @@
 			// Get receiver type
 			TypeReference typeRef = (TypeReference) receiver;
 			if (typeRef == null) {
-				char[] name = this.sourceParser.compilationUnit.compilationResult.compilationUnit.getMainTypeName();
+				char[] name = this.sourceParser.compilationUnit.getMainTypeName();
 				typeRef = new ImplicitDocTypeReference(name, this.memberStart);
 			}
 			// Create field
@@ -173,10 +166,11 @@
 			field.receiver = typeRef;
 			field.tagSourceStart = this.tagSourceStart;
 			field.tagSourceEnd = this.tagSourceEnd;
+			field.tagValue = this.tagValue;
 			return field;
 		}
 		catch (ClassCastException ex) {
-				throw new InvalidInputException();
+			throw new InvalidInputException();
 		}
 	}
 	/* (non-Javadoc)
@@ -189,7 +183,7 @@
 			// Decide whether we have a constructor or not
 			boolean isConstructor = false;
 			if (typeRef == null) {
-				char[] name = this.sourceParser.compilationUnit.compilationResult.compilationUnit.getMainTypeName();
+				char[] name = this.sourceParser.compilationUnit.getMainTypeName();
 				isConstructor = CharOperation.equals(this.identifierStack[0], name);
 				typeRef = new ImplicitDocTypeReference(name, this.memberStart);
 			} else {
@@ -207,12 +201,14 @@
 			// Create node
 			if (arguments == null) {
 				if (isConstructor) {
-					JavadocAllocationExpression expr = new JavadocAllocationExpression(this.identifierPositionStack[0]);
-					expr.type = typeRef;
-					return expr;
+					JavadocAllocationExpression alloc = new JavadocAllocationExpression(this.identifierPositionStack[0]);
+					alloc.type = typeRef;
+					alloc.tagValue = this.tagValue;
+					return alloc;
 				} else {
 					JavadocMessageSend msg = new JavadocMessageSend(this.identifierStack[0], this.identifierPositionStack[0]);
 					msg.receiver = typeRef;
+					msg.tagValue = this.tagValue;
 					return msg;
 				}
 			} else {
@@ -222,10 +218,12 @@
 					JavadocAllocationExpression alloc = new JavadocAllocationExpression(this.identifierPositionStack[0]);
 					alloc.arguments = expressions;
 					alloc.type = typeRef;
+					alloc.tagValue = this.tagValue;
 					return alloc;
 				} else {
 					JavadocMessageSend msg = new JavadocMessageSend(this.identifierStack[0], this.identifierPositionStack[0], expressions);
 					msg.receiver = typeRef;
+					msg.tagValue = this.tagValue;
 					return msg;
 				}
 			}
@@ -271,6 +269,7 @@
 	protected boolean parseReturn() {
 		if (this.returnStatement == null) {
 			this.returnStatement = createReturnStatement();
+			this.currentAstPtr = this.astPtr;
 			return true;
 		}
 		if (this.sourceParser != null) this.sourceParser.problemReporter().javadocDuplicatedReturnTag(
@@ -279,45 +278,185 @@
 		return false;
 	}
 
-	/*
-	 * Parse @return tag declaration
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#parseTag(int)
 	 */
-	protected boolean parseTag() {
-		return true;
+	protected boolean parseTag(int previousPosition) throws InvalidInputException {
+		boolean valid = false;
+
+		// In case of previous return tag, set it to not empty if parsing an inline tag
+		if (this.currentAstPtr != -2 && this.returnStatement != null) {
+			this.currentAstPtr = -2;
+			JavadocReturnStatement javadocReturn = (JavadocReturnStatement) this.returnStatement;
+			javadocReturn.empty = javadocReturn.empty && !this.inlineTagStarted;
+		}
+
+		// Read tag name
+		int token = readTokenAndConsume();
+		this.tagSourceStart = this.scanner.getCurrentTokenStartPosition();
+		this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
+		char[] tag = this.scanner.getCurrentIdentifierSource(); // first token is either an identifier or a keyword
+
+		// Decide which parse to perform depending on tag name
+		this.tagValue = NO_TAG_VALUE;
+		switch (token) {
+			case TerminalTokens.TokenNameIdentifier :
+				switch (tag[0]) {
+					case 'd':
+						if (CharOperation.equals(tag, TAG_DEPRECATED)) {
+							this.deprecated = true;
+							valid = true;
+							this.tagValue = TAG_DEPRECATED_VALUE;
+						}
+					break;
+					case 'i':
+						if (CharOperation.equals(tag, TAG_INHERITDOC)) {
+							// 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
+							// was encountered in comment. But it cannot be the case for COMPILER_PARSER
+							// and so is enough as it is only this parser which signals the missing tag warnings...
+							this.inherited = this.astPtr==-1;
+							valid = true;
+							this.tagValue = TAG_INHERITDOC_VALUE;
+						}
+					break;
+					case 'p':
+						if (CharOperation.equals(tag, TAG_PARAM)) {
+							this.tagValue = TAG_PARAM_VALUE;
+							valid = parseParam();
+						}
+					break;
+					case 'e':
+						if (CharOperation.equals(tag, TAG_EXCEPTION)) {
+							this.tagValue = TAG_EXCEPTION_VALUE;
+							valid = parseThrows();
+						}
+					break;
+					case 's':
+						if (CharOperation.equals(tag, TAG_SEE)) {
+							if (this.inlineTagStarted) {
+								// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
+								// Cannot have @see inside inline comment
+								valid = false;
+								if (this.sourceParser != null)
+									this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd);
+							} else {
+								this.tagValue = TAG_SEE_VALUE;
+								valid = parseReference();
+							}
+						}
+					break;
+					case 'l':
+						if (CharOperation.equals(tag, TAG_LINK)) {
+							this.tagValue = TAG_LINK_VALUE;
+							if (this.inlineTagStarted) {
+								valid= parseReference();
+							} else {
+								// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
+								// Cannot have @link outside inline comment
+								valid = false;
+								if (this.sourceParser != null)
+									this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd);
+							}
+						} else if (CharOperation.equals(tag, TAG_LINKPLAIN)) {
+							this.tagValue = TAG_LINKPLAIN_VALUE;
+							if (this.inlineTagStarted) {
+								valid = parseReference();
+							} else {
+								valid = false;
+								if (this.sourceParser != null)
+									this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd);
+							}
+						}
+					break;
+					case 'v':
+						if (this.jdk15 && CharOperation.equals(tag, TAG_VALUE)) {
+							this.tagValue = TAG_VALUE_VALUE;
+							if (this.inlineTagStarted) {
+								valid = parseReference();
+							} else {
+								valid = false;
+								if (this.sourceParser != null)
+									this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd);
+							}
+						} else {
+							createTag();
+						}
+					break;
+				}
+				break;
+			case TerminalTokens.TokenNamereturn :
+				this.tagValue = TAG_RETURN_VALUE;
+				valid = parseReturn();
+				/* verify characters after return tag (we're expecting text description)
+				if(!verifyCharsAfterReturnTag(this.index)) {
+					if (this.sourceParser != null) {
+						int end = this.starPosition == -1 || this.lineEnd<this.starPosition ? this.lineEnd : this.starPosition;
+						this.sourceParser.problemReporter().javadocEmptyReturnTag(this.tagSourceStart, end);
+					}
+				}
+				*/
+				break;
+			case TerminalTokens.TokenNamethrows :
+				this.tagValue = TAG_THROWS_VALUE;
+				valid = parseThrows();
+				break;
+		}
+		this.textStart = this.index;
+		return valid;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#parseTagName()
+	 */
+	protected void createTag() {
+		this.tagValue = TAG_OTHERS_VALUE;
 	}
 
 	/*
 	 * Push a param name in ast node stack.
 	 */
-	protected boolean pushParamName() {
-		// Create name reference
-		JavadocSingleNameReference nameRef = new JavadocSingleNameReference(this.scanner.getCurrentIdentifierSource(),
-				this.scanner.getCurrentTokenStartPosition(),
-				this.scanner.getCurrentTokenEndPosition());
-		nameRef.tagSourceStart = this.tagSourceStart;
-		nameRef.tagSourceEnd = this.tagSourceEnd;
+	protected boolean pushParamName(boolean isTypeParam) {
+		// Create param reference
+		ASTNode nameRef = null;
+		if (isTypeParam) {
+			JavadocSingleTypeReference ref = new JavadocSingleTypeReference(this.identifierStack[1],
+				this.identifierPositionStack[1],
+				this.tagSourceStart,
+				this.tagSourceEnd);
+			nameRef = ref;
+		} else {
+			JavadocSingleNameReference ref = new JavadocSingleNameReference(this.identifierStack[0],
+				this.identifierPositionStack[0],
+				this.tagSourceStart,
+				this.tagSourceEnd);
+			nameRef = ref;
+		}
 		// Push ref on stack
 		if (this.astLengthPtr == -1) { // First push
 			pushOnAstStack(nameRef, true);
 		} else {
 			// Verify that no @throws has been declared before
-			for (int i=THROWS_TAG_EXPECTED_ORDER; i<=this.astLengthPtr; i+=ORDERED_TAGS_NUMBER) {
-				if (this.astLengthStack[i] != 0) {
-					if (this.sourceParser != null) this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd);
-					// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51600
-					// store param references in specific array
-					if (this.invParamsPtr == -1l) {
-						this.invParamsStack = new JavadocSingleNameReference[10];
+			if (!isTypeParam) { // do not verify for type parameters as @throws may be invalid tag (when declared in class)
+				for (int i=THROWS_TAG_EXPECTED_ORDER; i<=this.astLengthPtr; i+=ORDERED_TAGS_NUMBER) {
+					if (this.astLengthStack[i] != 0) {
+						if (this.sourceParser != null) this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd);
+						// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51600
+						// store invalid param references in specific array
+						if (this.invalidParamReferencesPtr == -1l) {
+							this.invalidParamReferencesStack = new JavadocSingleNameReference[10];
+						}
+						int stackLength = this.invalidParamReferencesStack.length;
+						if (++this.invalidParamReferencesPtr >= stackLength) {
+							System.arraycopy(
+								this.invalidParamReferencesStack, 0,
+								this.invalidParamReferencesStack = new JavadocSingleNameReference[stackLength + AstStackIncrement], 0,
+								stackLength);
+						}
+						this.invalidParamReferencesStack[this.invalidParamReferencesPtr] = nameRef;
+						return false;
 					}
-					int stackLength = this.invParamsStack.length;
-					if (++this.invParamsPtr >= stackLength) {
-						System.arraycopy(
-							this.invParamsStack, 0,
-							this.invParamsStack = new JavadocSingleNameReference[stackLength + AstStackIncrement], 0,
-							stackLength);
-					}
-					this.invParamsStack[this.invParamsPtr] = nameRef;
-					return false;
 				}
 			}
 			switch (this.astLengthPtr % ORDERED_TAGS_NUMBER) {
@@ -339,7 +478,7 @@
 	/*
 	 * Push a reference statement in ast node stack.
 	 */
-	protected boolean pushSeeRef(Object statement, boolean plain) {
+	protected boolean pushSeeRef(Object statement) {
 		if (this.astLengthPtr == -1) { // First push
 			pushOnAstStack(null, true);
 			pushOnAstStack(null, true);
@@ -370,13 +509,40 @@
 	 * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#pushText(int, int)
 	 */
 	protected void pushText(int start, int end) {
-		// compiler does not matter of text
+		// In case of previous return tag, verify that text make it not empty
+		if (this.currentAstPtr != -2 && this.returnStatement != null) {
+			int position = this.index;
+			this.index = start;
+			boolean empty = true;
+			boolean star = false;
+			char ch = readChar();
+			// Look for first character other than white or '*'
+			if (Character.isWhitespace(ch) || start>(this.tagSourceEnd+1)) {
+				while (this.index <= end && empty) {
+					if (!star) {
+						empty = Character.isWhitespace(ch) || ch == '*';
+						star = ch == '*';
+					} else if (ch != '*') {
+						empty = false;
+						break;
+					}
+					ch = readChar();
+				}
+			}
+			// Store result in previous return tag
+			((JavadocReturnStatement)this.returnStatement).empty = empty;
+			// Reset position and current ast ptr if we are on a different tag than previous return one
+			this.index = position;
+			if (this.currentAstPtr != this.astPtr) {
+				this.currentAstPtr = -2;
+			}
+		}
 	}
 
 	/*
 	 * Push a throws type ref in ast node stack.
 	 */
-	protected boolean pushThrowName(Object typeRef, boolean real) {
+	protected boolean pushThrowName(Object typeRef) {
 		if (this.astLengthPtr == -1) { // First push
 			pushOnAstStack(null, true);
 			pushOnAstStack(typeRef, true);
@@ -403,7 +569,7 @@
 	}
 
 	/*
-	 * Fill javadoc fields with information in ast nodes stack.
+	 * Fill associated comment fields with ast nodes information stored in stack.
 	 */
 	protected void updateDocComment() {
 		
@@ -416,9 +582,9 @@
 		}
 		
 		// Copy array of invalid syntax param tags
-		if (this.invParamsPtr >= 0) {
-			this.docComment.invalidParameters = new JavadocSingleNameReference[this.invParamsPtr+1];
-			System.arraycopy(this.invParamsStack, 0, this.docComment.invalidParameters, 0, this.invParamsPtr+1);
+		if (this.invalidParamReferencesPtr >= 0) {
+			this.docComment.invalidParameters = new JavadocSingleNameReference[this.invalidParamReferencesPtr+1];
+			System.arraycopy(this.invalidParamReferencesStack, 0, this.docComment.invalidParameters, 0, this.invalidParamReferencesPtr+1);
 		}
 
 		// If no nodes stored return
@@ -431,36 +597,56 @@
 		for (int i=0; i<=this.astLengthPtr; i++) {
 			sizes[i%ORDERED_TAGS_NUMBER] += this.astLengthStack[i];
 		}
-		this.docComment.references = new Expression[sizes[SEE_TAG_EXPECTED_ORDER]];
-		this.docComment.thrownExceptions = new TypeReference[sizes[THROWS_TAG_EXPECTED_ORDER]];
-		this.docComment.parameters = new JavadocSingleNameReference[sizes[PARAM_TAG_EXPECTED_ORDER]];
+		this.docComment.seeReferences = new Expression[sizes[SEE_TAG_EXPECTED_ORDER]];
+		this.docComment.exceptionReferences = new TypeReference[sizes[THROWS_TAG_EXPECTED_ORDER]];
+		this.docComment.paramReferences = new JavadocSingleNameReference[sizes[PARAM_TAG_EXPECTED_ORDER]];
+		int paramRefPtr = sizes[PARAM_TAG_EXPECTED_ORDER];
+		this.docComment.paramTypeParameters = new JavadocSingleTypeReference[sizes[PARAM_TAG_EXPECTED_ORDER]];
+		int paramTypeParamPtr = sizes[PARAM_TAG_EXPECTED_ORDER];
 
 		// Store nodes in arrays
 		while (this.astLengthPtr >= 0) {
 			int ptr = this.astLengthPtr % ORDERED_TAGS_NUMBER;
 			// Starting with the stack top, so get references (eg. Expression) coming from @see declarations
-			if (ptr == SEE_TAG_EXPECTED_ORDER) {
-				int size = this.astLengthStack[this.astLengthPtr--];
-				for (int i=0; i<size; i++) {
-					this.docComment.references[--sizes[ptr]] = (Expression) this.astStack[this.astPtr--];
-				}
-			}
+			switch(ptr) {
+				case SEE_TAG_EXPECTED_ORDER:
+					int size = this.astLengthStack[this.astLengthPtr--];
+					for (int i=0; i<size; i++) {
+						this.docComment.seeReferences[--sizes[ptr]] = (Expression) this.astStack[this.astPtr--];
+					}
+					break;
 
-			// Then continuing with class names (eg. TypeReference) coming from @throw/@exception declarations
-			else if (ptr == THROWS_TAG_EXPECTED_ORDER) {
-				int size = this.astLengthStack[this.astLengthPtr--];
-				for (int i=0; i<size; i++) {
-					this.docComment.thrownExceptions[--sizes[ptr]] = (TypeReference) this.astStack[this.astPtr--];
-				}
-			}
+				// Then continuing with class names (eg. TypeReference) coming from @throw/@exception declarations
+				case THROWS_TAG_EXPECTED_ORDER:
+					size = this.astLengthStack[this.astLengthPtr--];
+					for (int i=0; i<size; i++) {
+						this.docComment.exceptionReferences[--sizes[ptr]] = (TypeReference) this.astStack[this.astPtr--];
+					}
+					break;
 
-			// Finally, finishing with parameters nales (ie. Argument) coming from @param declaration
-			else if (ptr == PARAM_TAG_EXPECTED_ORDER) {
-				int size = this.astLengthStack[this.astLengthPtr--];
-				for (int i=0; i<size; i++) {
-					this.docComment.parameters[--sizes[ptr]] = (JavadocSingleNameReference) this.astStack[this.astPtr--];
-				}
+				// Finally, finishing with parameters nales (ie. Argument) coming from @param declaration
+				case PARAM_TAG_EXPECTED_ORDER:
+					size = this.astLengthStack[this.astLengthPtr--];
+					for (int i=0; i<size; i++) {
+						Expression reference = (Expression) this.astStack[this.astPtr--];
+						if (reference instanceof JavadocSingleNameReference)
+							this.docComment.paramReferences[--paramRefPtr] = (JavadocSingleNameReference) reference;
+						else if (reference instanceof JavadocSingleTypeReference)
+							this.docComment.paramTypeParameters[--paramTypeParamPtr] = (JavadocSingleTypeReference) reference;
+					}
+					break;
 			}
 		}
+		
+		// Resize param tag references arrays
+		if (paramRefPtr == 0) { // there's no type parameters references
+			this.docComment.paramTypeParameters = null;
+		} else if (paramTypeParamPtr == 0) { // there's no names references
+			this.docComment.paramReferences = null;
+		} else { // there both of references => resize arrays
+			int size = sizes[PARAM_TAG_EXPECTED_ORDER];
+			System.arraycopy(this.docComment.paramReferences, paramRefPtr, this.docComment.paramReferences = new JavadocSingleNameReference[size - paramRefPtr], 0, size - paramRefPtr);
+			System.arraycopy(this.docComment.paramTypeParameters, paramTypeParamPtr, this.docComment.paramTypeParameters = new JavadocSingleTypeReference[size - paramTypeParamPtr], 0, size - paramTypeParamPtr);
+		}
 	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
index 81fd8d4..cedccfe 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
@@ -24,10 +24,12 @@
 import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
-import org.eclipse.jdt.internal.compiler.lookup.BindingIds;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
 import org.eclipse.jdt.internal.compiler.parser.diagnose.DiagnoseParser;
@@ -36,119 +38,151 @@
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
-public class Parser implements BindingIds, ParserBasicInformation, TerminalTokens, CompilerModifiers, OperatorIds, TypeIds {
-	protected ProblemReporter problemReporter;
-	protected CompilerOptions options;
-	public int firstToken ; // handle for multiple parsing goals
-	public int lastAct ; //handle for multiple parsing goals
-	public ReferenceContext referenceContext;
-	public int currentToken;
-	private int synchronizedBlockSourceStart;
+public class Parser implements  ParserBasicInformation, TerminalTokens, CompilerModifiers, OperatorIds, TypeIds {
+	protected static final int THIS_CALL = ExplicitConstructorCall.This;
+	protected static final int SUPER_CALL = ExplicitConstructorCall.Super;
 
-	//error recovery management
-	protected int lastCheckPoint;
-	protected RecoveredElement currentElement;
-	public static boolean VERBOSE_RECOVERY = false;
-	protected boolean restartRecovery;
-	protected int listLength; // for recovering some incomplete list (interfaces, throws or parameters)
-	protected boolean hasError;
-	protected boolean hasReportedError;
-	public boolean reportSyntaxErrorIsRequired = true;
-	public boolean reportOnlyOneSyntaxError = false;
-	protected int recoveredStaticInitializerStart;
-	protected int lastIgnoredToken, nextIgnoredToken;
-	protected int lastErrorEndPosition;
-	protected boolean ignoreNextOpeningBrace;
+	public static char asb[] = null;
+	public static char asr[] = null;
+	//ast stack
+	protected final static int AstStackIncrement = 100;
+	public static char base_action[] = null;
+	public static final int BracketKinds = 3;
+    
+	public static short check_table[] = null;
+	public static final int CurlyBracket = 2;
+	// TODO remove once testing is done
+	private static final boolean DEBUG = false;
+	private static final String EOF_TOKEN = "$eof" ; //$NON-NLS-1$
+	private static final String ERROR_TOKEN = "$error" ; //$NON-NLS-1$
+	//expression stack
+	protected final static int ExpressionStackIncrement = 100;
+
+	protected final static int GenericsStackIncrement = 10;
+    
+	private final static String FILEPREFIX = "parser"; //$NON-NLS-1$
+    public static char in_symb[] = null;
+	private static final String INVALID_CHARACTER = "Invalid Character" ; //$NON-NLS-1$
+	public static char lhs[] =  null;
+
+	public static String name[] = null;
+	public static char nasb[] = null;
+	public static char nasr[] = null;
+	public static char non_terminal_index[] = null;
+	private final static String READABLE_NAMES_FILE = "readableNames"; //$NON-NLS-1$
+	private final static String READABLE_NAMES_FILE_NAME =
+		"org.eclipse.jdt.internal.compiler.parser." + READABLE_NAMES_FILE; //$NON-NLS-1$
+	public static String readableName[] = null;
+	
+	public static byte rhs[] = null;
+	
+	public static long rules_compliance[] =  null;
+	
+	public static final int RoundBracket = 0;
+    
+    public static byte scope_la[] = null;
+    public static char scope_lhs[] = null;
+	
+	public static char scope_prefix[] = null;
+    public static char scope_rhs[] = null;
+    public static char scope_state[] = null;
+
+    public static char scope_state_set[] = null;
+    public static char scope_suffix[] = null;
+	public static final int SquareBracket = 1;
 		
 	//internal data for the automat 
 	protected final static int StackIncrement = 255;
-	protected int stateStackTop;
-	protected int[] stack = new int[StackIncrement];
-	//scanner token 
-	public Scanner scanner;
-	//ast stack
-	final static int AstStackIncrement = 100;
-	protected int astPtr;
-	protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
-	protected int astLengthPtr;
-	protected int[] astLengthStack;
-	public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/
-	ASTNode [] noAstNodes = new ASTNode[AstStackIncrement];
-	//expression stack
-	final static int ExpressionStackIncrement = 100;
-	protected int expressionPtr;
-	protected Expression[] expressionStack = new Expression[ExpressionStackIncrement];
-	protected int expressionLengthPtr;
-	protected int[] expressionLengthStack;
-	Expression [] noExpressions = new Expression[ExpressionStackIncrement];
-	//identifiers stacks 
-	protected int identifierPtr;
-	protected char[][] identifierStack;
-	protected int identifierLengthPtr;
-	protected int[] identifierLengthStack;
-	protected long[] identifierPositionStack;
-	//positions , dimensions , .... (int stacks)
-	protected int intPtr;
-	protected int[] intStack;
-	protected int endPosition; //accurate only when used ! (the start position is pushed into intStack while the end the current one)
-	protected int endStatementPosition;
-	protected int lParenPos,rParenPos; //accurate only when used !
-	protected int rBraceStart, rBraceEnd, rBraceSuccessorStart; //accurate only when used !
-	//modifiers dimensions nestedType etc.......
-	protected boolean optimizeStringLiterals =true;
-	protected int modifiers;
-	protected int modifiersSourceStart;
-	protected int nestedType, dimensions;
-	protected int[] nestedMethod; //the ptr is nestedType
-	protected int[] realBlockStack;
-	protected int realBlockPtr;
-	protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies
-	protected int dietInt = 0; // if > 0 force the none-diet-parsing mode (even if diet if requested) [field parsing with anonymous inner classes...]
-	protected int[] variablesCounter;
-
-	// javadoc
-	public JavadocParser javadocParser;
-	public Javadoc javadoc;
-	
-	public static byte rhs[] = null;
-	public static char asb[] = null;
-	public static char asr[] = null;
-	public static char nasb[] = null;
-	public static char nasr[] = null;
-
-	public static char terminal_index[] = null;
-	public static char non_terminal_index[] = null;
 	
 	public static char term_action[] = null;
 	public static byte term_check[] = null;
 
+	public static char terminal_index[] = null;
+
 	private static final String UNEXPECTED_EOF = "Unexpected End Of File" ; //$NON-NLS-1$
-	private static final String INVALID_CHARACTER = "Invalid Character" ; //$NON-NLS-1$
-	private static final String EOF_TOKEN = "$eof" ; //$NON-NLS-1$
-	private static final String ERROR_TOKEN = "$error" ; //$NON-NLS-1$
+	public static boolean VERBOSE_RECOVERY = false;
 
-	public static String name[] = null;
-	public static String readableName[] = null;
-    
-	public static short check_table[] = null;
-	public static char lhs[] =  null;
-	public static char base_action[] = lhs;
+
+
+	protected int astLengthPtr;
+	protected int[] astLengthStack;
+	protected int astPtr;
+	protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
+	public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/
+	protected RecoveredElement currentElement;
+	public int currentToken;
+	protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies
+	protected int dietInt = 0; // if > 0 force the none-diet-parsing mode (even if diet if requested) [field parsing with anonymous inner classes...]
+	protected int endPosition; //accurate only when used ! (the start position is pushed into intStack while the end the current one)
+	protected int endStatementPosition;
+	protected int expressionLengthPtr;
+	protected int[] expressionLengthStack;
+	protected int expressionPtr;
+	protected Expression[] expressionStack = new Expression[ExpressionStackIncrement];
+	public int firstToken ; // handle for multiple parsing goals
+
+	// generics management
+	protected int genericsIdentifiersLengthPtr;
+	protected int[] genericsIdentifiersLengthStack = new int[GenericsStackIncrement];
+	protected int genericsLengthPtr;
+	protected int[] genericsLengthStack = new int[GenericsStackIncrement];
+	protected int genericsPtr;
+	protected ASTNode[] genericsStack = new ASTNode[GenericsStackIncrement];
 	
-	public static char scope_prefix[] = null;
-    public static char scope_suffix[] = null;
-    public static char scope_lhs[] = null;
-    
-    public static byte scope_la[] = null;
+	protected boolean hasError;
+	protected boolean hasReportedError;
 
-    public static char scope_state_set[] = null;
-    public static char scope_rhs[] = null;
-    public static char scope_state[] = null;
-    public static char in_symb[] = null;
-    
-	private final static String FILEPREFIX = "parser"; //$NON-NLS-1$
-	private final static String READABLE_NAMES_FILE = "readableNames"; //$NON-NLS-1$
-	private final static String READABLE_NAMES =
-		"org.eclipse.jdt.internal.compiler.parser." + READABLE_NAMES_FILE; //$NON-NLS-1$
+	//identifiers stacks 
+	protected int identifierLengthPtr;
+	protected int[] identifierLengthStack;
+	protected long[] identifierPositionStack;
+	protected int identifierPtr;
+	protected char[][] identifierStack;
+	
+	protected boolean ignoreNextOpeningBrace;
+	//positions , dimensions , .... (int stacks)
+	protected int intPtr;
+	protected int[] intStack;
+	public int lastAct ; //handle for multiple parsing goals
+
+	//error recovery management
+	protected int lastCheckPoint;
+	protected int lastErrorEndPosition;
+	protected int lastErrorEndPositionBeforeRecovery = -1;
+	protected int lastIgnoredToken, nextIgnoredToken;
+	protected int listLength; // for recovering some incomplete list (interfaces, throws or parameters)
+	protected int listTypeParameterLength; // for recovering some incomplete list (type parameters)
+	protected int lParenPos,rParenPos; //accurate only when used !
+	protected int modifiers;
+	protected int modifiersSourceStart;
+	protected int[] nestedMethod; //the ptr is nestedType
+	protected int nestedType, dimensions;
+	ASTNode [] noAstNodes = new ASTNode[AstStackIncrement];
+	Expression [] noExpressions = new Expression[ExpressionStackIncrement];
+	//modifiers dimensions nestedType etc.......
+	protected boolean optimizeStringLiterals =true;
+	protected CompilerOptions options;
+	protected ProblemReporter problemReporter;
+	protected int rBraceStart, rBraceEnd, rBraceSuccessorStart; //accurate only when used !
+	protected int realBlockPtr;
+	protected int[] realBlockStack;
+	protected int recoveredStaticInitializerStart;
+	public ReferenceContext referenceContext;
+	public boolean reportOnlyOneSyntaxError = false;
+	public boolean reportSyntaxErrorIsRequired = true;
+	protected boolean restartRecovery;
+	//scanner token 
+	public Scanner scanner;
+	protected int[] stack = new int[StackIncrement];
+	protected int stateStackTop;
+	protected int synchronizedBlockSourceStart;
+	protected int[] variablesCounter;
+
+	// javadoc
+	public Javadoc javadoc;
+	public JavadocParser javadocParser;
+	// used for recovery
+	protected int lastJavadocEnd;
 
 	static {
 		try{
@@ -157,136 +191,21 @@
 			throw new ExceptionInInitializerError(ex.getMessage());
 		}
 	}
-
-	public static final int RoundBracket = 0;
-	public static final int SquareBracket = 1;
-	public static final int CurlyBracket = 2;
-	public static final int BracketKinds = 3;
-
-public Parser(ProblemReporter problemReporter, boolean optimizeStringLiterals) {
-		
-	this.problemReporter = problemReporter;
-	this.options = problemReporter.options;
-	this.optimizeStringLiterals = optimizeStringLiterals;
-	this.initializeScanner();
-	this.astLengthStack = new int[50];
-	this.expressionLengthStack = new int[30];
-	this.intStack = new int[50];
-	this.identifierStack = new char[30][];
-	this.identifierLengthStack = new int[30];
-	this.nestedMethod = new int[30];
-	this.realBlockStack = new int[30];
-	this.identifierPositionStack = new long[30];
-	this.variablesCounter = new int[30];
-	
-	// javadoc support
-	this.javadocParser = new JavadocParser(this);	
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void adjustInterfaceModifiers() {
-	this.intStack[this.intPtr - 1] |= AccInterface;
-}
-public final void arrayInitializer(int length) {
-	//length is the size of the array Initializer
-	//expressionPtr points on the last elt of the arrayInitializer, 
-	// in other words, it has not been decremented yet.
-
-	ArrayInitializer ai = new ArrayInitializer();
-	if (length != 0) {
-		this.expressionPtr -= length;
-		System.arraycopy(this.expressionStack, this.expressionPtr + 1, ai.expressions = new Expression[length], 0, length);
-	}
-	pushOnExpressionStack(ai);
-	//positionning
-	ai.sourceEnd = this.endStatementPosition;
-	int searchPosition = length == 0 ? this.endPosition + 1 : ai.expressions[0].sourceStart;
-	try {
-		//does not work with comments(that contain '{') nor '{' describes as a unicode....		
-		while (this.scanner.source[--searchPosition] != '{'){/*empty*/}
-	} catch (IndexOutOfBoundsException ex) {
-		//should never occur (except for strange cases like whose describe above)
-		searchPosition = (length == 0 ? this.endPosition : ai.expressions[0].sourceStart) - 1;
-	}
-	ai.sourceStart = searchPosition;
-}
 public static int asi(int state) {
 
 	return asb[original_state(state)]; 
 }
-protected void blockReal() {
-	// See consumeLocalVariableDeclarationStatement in case of change: duplicated code
-	// increment the amount of declared variables for this block
-	this.realBlockStack[this.realBlockPtr]++;
+public final static short base_check(int i) {
+	return check_table[i - (NUM_RULES + 1)];
 }
-private final static void buildFileOfByteFor(String filename, String tag, String[] tokens) throws java.io.IOException {
-
-	//transform the String tokens into chars before dumping then into file
-
-	int i = 0;
-	//read upto the tag
-	while (!tokens[i++].equals(tag)){/*empty*/}
-	//read upto the }
-	
-	byte[] bytes = new byte[tokens.length]; //can't be bigger
-	int ic = 0;
-	String token;
-	while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
-		int c = Integer.parseInt(token);
-		bytes[ic++] = (byte) c;
+private final static void buildFile(String filename, List listToDump) throws java.io.IOException {
+	BufferedWriter writer = new BufferedWriter(new FileWriter(filename));
+	for (Iterator iterator = listToDump.iterator(); iterator.hasNext(); ) {
+		writer.write(String.valueOf(iterator.next()));
 	}
-
-	//resize
-	System.arraycopy(bytes, 0, bytes = new byte[ic], 0, ic);
-
-	buildFileForTable(filename, bytes);
-}
-private final static char[] buildFileOfIntFor(String filename, String tag, String[] tokens) throws java.io.IOException {
-
-	//transform the String tokens into chars before dumping then into file
-
-	int i = 0;
-	//read upto the tag
-	while (!tokens[i++].equals(tag)){/*empty*/}
-	//read upto the }
-	
-	char[] chars = new char[tokens.length]; //can't be bigger
-	int ic = 0;
-	String token;
-	while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
-		int c = Integer.parseInt(token);
-		chars[ic++] = (char) c;
-	}
-
-	//resize
-	System.arraycopy(chars, 0, chars = new char[ic], 0, ic);
-
-	buildFileForTable(filename, chars);
-	return chars;
-}
-private final static void buildFileOfShortFor(String filename, String tag, String[] tokens) throws java.io.IOException {
-
-	//transform the String tokens into chars before dumping then into file
-
-	int i = 0;
-	//read upto the tag
-	while (!tokens[i++].equals(tag)){/*empty*/}
-	//read upto the }
-	
-	char[] chars = new char[tokens.length]; //can't be bigger
-	int ic = 0;
-	String token;
-	while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
-		int c = Integer.parseInt(token);
-		chars[ic++] = (char) (c + 32768);
-	}
-
-	//resize
-	System.arraycopy(chars, 0, chars = new char[ic], 0, ic);
-
-	buildFileForTable(filename, chars);
+	writer.flush();
+	writer.close();
+	System.out.println(filename + " creation complete"); //$NON-NLS-1$
 }
 private final static String[] buildFileForName(String filename, String contents) throws java.io.IOException {
 	String[] result = new String[contents.length()];
@@ -351,16 +270,18 @@
 	
 	boolean[] alreadyAdded = new boolean[newName.length];
 	
-	for (int i = 0; i < tokens.length; i = i + 2) {
-		int index = newNonTerminalIndex[newLhs[Integer.parseInt(tokens[i])]];
-		StringBuffer buffer = new StringBuffer();
-		if(!alreadyAdded[index]) {
-			alreadyAdded[index] = true;
-			buffer.append(newName[index]);
-			buffer.append('=');
-			buffer.append(tokens[i+1].trim());
-			buffer.append('\n');
-			entries.add(String.valueOf(buffer));
+	for (int i = 0; i < tokens.length; i = i + 3) {
+		if("1".equals(tokens[i])) { //$NON-NLS-1$
+			int index = newNonTerminalIndex[newLhs[Integer.parseInt(tokens[i + 1])]];
+			StringBuffer buffer = new StringBuffer();
+			if(!alreadyAdded[index]) {
+				alreadyAdded[index] = true;
+				buffer.append(newName[index]);
+				buffer.append('=');
+				buffer.append(tokens[i+2].trim());
+				buffer.append('\n');
+				entries.add(String.valueOf(buffer));
+			}
 		}
 	}
 	int i = 1;
@@ -374,13 +295,44 @@
 	Collections.sort(entries);
 	buildFile(file, entries);
 }
-private final static void buildFile(String filename, List listToDump) throws java.io.IOException {
-	BufferedWriter writer = new BufferedWriter(new FileWriter(filename));
-	for (Iterator iterator = listToDump.iterator(); iterator.hasNext(); ) {
-		writer.write(String.valueOf(iterator.next()));
+private static void buildFileForCompliance(
+		String file,
+		int length,
+		String[] tokens) throws java.io.IOException {
+
+		byte[] result = new byte[length * 8];
+		
+		for (int i = 0; i < tokens.length; i = i + 3) {
+			if("2".equals(tokens[i])) { //$NON-NLS-1$
+				int index = Integer.parseInt(tokens[i + 1]);
+				String token = tokens[i + 2].trim();
+				long compliance = 0;
+				if("1.4".equals(token)) { //$NON-NLS-1$
+					compliance = ClassFileConstants.JDK1_4;
+				} else if("1.5".equals(token)) { //$NON-NLS-1$
+					compliance = ClassFileConstants.JDK1_5;
+				} else if("recovery".equals(token)) { //$NON-NLS-1$
+					compliance = ClassFileConstants.JDK_DEFERRED;
+				}
+				
+				int j = index * 8;
+				result[j] = 	(byte)(compliance >>> 56);
+				result[j + 1] = (byte)(compliance >>> 48);
+				result[j + 2] = (byte)(compliance >>> 40);
+				result[j + 3] = (byte)(compliance >>> 32);
+				result[j + 4] = (byte)(compliance >>> 24);
+				result[j + 5] = (byte)(compliance >>> 16);
+				result[j + 6] = (byte)(compliance >>> 8);
+				result[j + 7] = (byte)(compliance);
+			}
+		}
+
+		buildFileForTable(file, result); //$NON-NLS-1$
 	}
-	writer.flush();
-	writer.close();
+private final static void buildFileForTable(String filename, byte[] bytes) throws java.io.IOException {
+	java.io.FileOutputStream stream = new java.io.FileOutputStream(filename);
+	stream.write(bytes);
+	stream.close();
 	System.out.println(filename + " creation complete"); //$NON-NLS-1$
 }
 private final static void buildFileForTable(String filename, char[] chars) throws java.io.IOException {
@@ -396,11 +348,73 @@
 	stream.close();
 	System.out.println(filename + " creation complete"); //$NON-NLS-1$
 }
-private final static void buildFileForTable(String filename, byte[] bytes) throws java.io.IOException {
-	java.io.FileOutputStream stream = new java.io.FileOutputStream(filename);
-	stream.write(bytes);
-	stream.close();
-	System.out.println(filename + " creation complete"); //$NON-NLS-1$
+private final static byte[] buildFileOfByteFor(String filename, String tag, String[] tokens) throws java.io.IOException {
+
+	//transform the String tokens into chars before dumping then into file
+
+	int i = 0;
+	//read upto the tag
+	while (!tokens[i++].equals(tag)){/*empty*/}
+	//read upto the }
+	
+	byte[] bytes = new byte[tokens.length]; //can't be bigger
+	int ic = 0;
+	String token;
+	while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
+		int c = Integer.parseInt(token);
+		bytes[ic++] = (byte) c;
+	}
+
+	//resize
+	System.arraycopy(bytes, 0, bytes = new byte[ic], 0, ic);
+
+	buildFileForTable(filename, bytes);
+	return bytes;
+}
+private final static char[] buildFileOfIntFor(String filename, String tag, String[] tokens) throws java.io.IOException {
+
+	//transform the String tokens into chars before dumping then into file
+
+	int i = 0;
+	//read upto the tag
+	while (!tokens[i++].equals(tag)){/*empty*/}
+	//read upto the }
+	
+	char[] chars = new char[tokens.length]; //can't be bigger
+	int ic = 0;
+	String token;
+	while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
+		int c = Integer.parseInt(token);
+		chars[ic++] = (char) c;
+	}
+
+	//resize
+	System.arraycopy(chars, 0, chars = new char[ic], 0, ic);
+
+	buildFileForTable(filename, chars);
+	return chars;
+}
+private final static void buildFileOfShortFor(String filename, String tag, String[] tokens) throws java.io.IOException {
+
+	//transform the String tokens into chars before dumping then into file
+
+	int i = 0;
+	//read upto the tag
+	while (!tokens[i++].equals(tag)){/*empty*/}
+	//read upto the }
+	
+	char[] chars = new char[tokens.length]; //can't be bigger
+	int ic = 0;
+	String token;
+	while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
+		int c = Integer.parseInt(token);
+		chars[ic++] = (char) (c + 32768);
+	}
+
+	//resize
+	System.arraycopy(chars, 0, chars = new char[ic], 0, ic);
+
+	buildFileForTable(filename, chars);
 }
 public final static void buildFilesFromLPG(String dataFilename, String dataFilename2)	throws java.io.IOException {
 
@@ -410,7 +424,6 @@
 	//lhs check_table asb asr symbol_index
 
 	//[org.eclipse.jdt.internal.compiler.parser.Parser.buildFilesFromLPG("d:/leapfrog/grammar/javadcl.java")]
-
 	char[] contents = new char[] {};
 	try {
 		contents = Util.getFileCharContent(new File(dataFilename), null);
@@ -421,12 +434,12 @@
 	java.util.StringTokenizer st = 
 		new java.util.StringTokenizer(new String(contents), " \t\n\r[]={,;");  //$NON-NLS-1$
 	String[] tokens = new String[st.countTokens()];
-	int i = 0;
+	int j = 0;
 	while (st.hasMoreTokens()) {
-		tokens[i++] = st.nextToken();
+		tokens[j++] = st.nextToken();
 	}
 	final String prefix = FILEPREFIX;
-	i = 0;
+	int i = 0;
 	
 	char[] newLhs = buildFileOfIntFor(prefix + (++i) + ".rsc", "lhs", tokens); //$NON-NLS-1$ //$NON-NLS-2$
 	buildFileOfShortFor(prefix + (++i) + ".rsc", "check_table", tokens); //$NON-NLS-2$ //$NON-NLS-1$
@@ -446,7 +459,7 @@
 	buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_state", tokens); //$NON-NLS-2$ //$NON-NLS-1$
 	buildFileOfIntFor(prefix + (++i) + ".rsc", "in_symb", tokens); //$NON-NLS-2$ //$NON-NLS-1$
 	
-	buildFileOfByteFor(prefix + (++i) + ".rsc", "rhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	byte[] newRhs = buildFileOfByteFor(prefix + (++i) + ".rsc", "rhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$
 	buildFileOfByteFor(prefix + (++i) + ".rsc", "term_check", tokens); //$NON-NLS-2$ //$NON-NLS-1$
 	buildFileOfByteFor(prefix + (++i) + ".rsc", "scope_la", tokens); //$NON-NLS-2$ //$NON-NLS-1$
 	
@@ -459,16 +472,255 @@
 		System.out.println(Util.bind("parser.incorrectPath")); //$NON-NLS-1$
 		return;
 	}
-	st = new java.util.StringTokenizer(new String(contents), "\t\n\r=");  //$NON-NLS-1$
+	st = new java.util.StringTokenizer(new String(contents), "\t\n\r=#");  //$NON-NLS-1$
 	tokens = new String[st.countTokens()];
-	i = 0;
+	j = 0;
 	while (st.hasMoreTokens()) {
-		tokens[i++] = st.nextToken();
+		tokens[j++] = st.nextToken();
 	}
+	
+	buildFileForCompliance(prefix + (++i) + ".rsc", newRhs.length, tokens);//$NON-NLS-1$
 	buildFileForReadableName(READABLE_NAMES_FILE+".properties", newLhs, newNonTerminalIndex, newName, tokens);//$NON-NLS-1$
 	
 	System.out.println(Util.bind("parser.moveFiles")); //$NON-NLS-1$
 }
+public static int in_symbol(int state) {
+	return in_symb[original_state(state)];
+}
+public final static void initTables() throws java.io.IOException {
+
+	final String prefix = FILEPREFIX;
+	int i = 0;
+	lhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	char[] chars = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	check_table = new short[chars.length];
+	for (int c = chars.length; c-- > 0;) {
+		check_table[c] = (short) (chars[c] - 32768);
+	}
+	asb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	asr = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	nasb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	nasr = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	terminal_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	non_terminal_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	term_action = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	
+	scope_prefix = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	scope_suffix = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	scope_lhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	scope_state_set = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	scope_rhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	scope_state = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	in_symb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	
+	rhs = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	term_check = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	scope_la = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	
+	name = readNameTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	
+	rules_compliance = readLongTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	
+	readableName = readReadableNameTable(READABLE_NAMES_FILE_NAME);
+	
+	base_action = lhs;
+}
+public static int nasi(int state) {
+	return nasb[original_state(state)];
+}
+public static int ntAction(int state, int sym) {
+	return base_action[state + sym];
+}
+protected static int original_state(int state) {
+	return -base_check(state);
+}
+protected static byte[] readByteTable(String filename) throws java.io.IOException {
+
+	//files are located at Parser.class directory
+
+	InputStream stream = Parser.class.getResourceAsStream(filename);
+	if (stream == null) {
+		throw new java.io.IOException(Util.bind("parser.missingFile",filename)); //$NON-NLS-1$
+	}
+	byte[] bytes = null;
+	try {
+		stream = new BufferedInputStream(stream);
+		bytes = Util.getInputStreamAsByteArray(stream, -1);
+	} finally {
+		try {
+			stream.close();
+		} catch (IOException e) {
+			// ignore
+		}
+	}
+	return bytes;
+}
+	
+protected static String[] readNameTable(String filename) throws java.io.IOException {
+	char[] contents = readTable(filename);
+	char[][] nameAsChar = CharOperation.splitOn('\n', contents);
+
+	String[] result = new String[nameAsChar.length + 1];
+	result[0] = null;
+	for (int i = 0; i < nameAsChar.length; i++) {
+		result[i + 1] = new String(nameAsChar[i]);
+	}
+	
+	return result;
+}
+protected static String[] readReadableNameTable(String filename) {
+	String[] result = new String[name.length];
+
+	ResourceBundle bundle;
+	try {
+		bundle = ResourceBundle.getBundle(filename, Locale.getDefault());
+	} catch(MissingResourceException e) {
+		System.out.println("Missing resource : " + filename.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
+		throw e;
+	}
+	for (int i = 0; i < NT_OFFSET + 1; i++) {
+		result[i] = name[i];
+	}
+	for (int i = NT_OFFSET; i < name.length; i++) {
+		try {
+			String n = bundle.getString(name[i]);
+			if(n != null && n.length() > 0) {
+				result[i] = n;
+			} else {
+				result[i] = name[i];
+			}
+		} catch(MissingResourceException e) {
+			result[i] = name[i];
+		}
+	}
+	return result;
+}
+protected static char[] readTable(String filename) throws java.io.IOException {
+
+	//files are located at Parser.class directory
+
+	InputStream stream = Parser.class.getResourceAsStream(filename);
+	if (stream == null) {
+		throw new java.io.IOException(Util.bind("parser.missingFile",filename)); //$NON-NLS-1$
+	}
+	byte[] bytes = null;
+	try {
+		stream = new BufferedInputStream(stream);
+		bytes = Util.getInputStreamAsByteArray(stream, -1);
+	} finally {
+		try {
+			stream.close();
+		} catch (IOException e) {
+			// ignore
+		}
+	}
+
+	//minimal integrity check (even size expected)
+	int length = bytes.length;
+	if (length % 2 != 0)
+		throw new java.io.IOException(Util.bind("parser.corruptedFile",filename)); //$NON-NLS-1$
+
+	// convert bytes into chars
+	char[] chars = new char[length / 2];
+	int i = 0;
+	int charIndex = 0;
+
+	while (true) {
+		chars[charIndex++] = (char) (((bytes[i++] & 0xFF) << 8) + (bytes[i++] & 0xFF));
+		if (i == length)
+			break;
+	}
+	return chars;
+}
+protected static long[] readLongTable(String filename) throws java.io.IOException {
+
+	//files are located at Parser.class directory
+
+	InputStream stream = Parser.class.getResourceAsStream(filename);
+	if (stream == null) {
+		throw new java.io.IOException(Util.bind("parser.missingFile",filename)); //$NON-NLS-1$
+	}
+	byte[] bytes = null;
+	try {
+		stream = new BufferedInputStream(stream);
+		bytes = Util.getInputStreamAsByteArray(stream, -1);
+	} finally {
+		try {
+			stream.close();
+		} catch (IOException e) {
+			// ignore
+		}
+	}
+
+	//minimal integrity check (even size expected)
+	int length = bytes.length;
+	if (length % 8 != 0)
+		throw new java.io.IOException(Util.bind("parser.corruptedFile",filename)); //$NON-NLS-1$
+
+	// convert bytes into longs
+	long[] longs = new long[length / 8];
+	int i = 0;
+	int longIndex = 0;
+
+	while (true) {
+		longs[longIndex++] = 
+		  (((long) (bytes[i++] & 0xFF)) << 56)
+		+ (((long) (bytes[i++] & 0xFF)) << 48)
+		+ (((long) (bytes[i++] & 0xFF)) << 40)
+		+ (((long) (bytes[i++] & 0xFF)) << 32)
+		+ (((long) (bytes[i++] & 0xFF)) << 24)
+		+ (((long) (bytes[i++] & 0xFF)) << 16)
+		+ (((long) (bytes[i++] & 0xFF)) << 8)
+		+ (bytes[i++] & 0xFF);
+		
+		if (i == length)
+			break;
+	}
+	return longs;
+}
+public static int tAction(int state, int sym) {
+	return term_action[term_check[base_action[state]+sym] == sym ? base_action[state] + sym : base_action[state]];
+}
+
+public Parser(ProblemReporter problemReporter, boolean optimizeStringLiterals) {
+		
+	this.problemReporter = problemReporter;
+	this.options = problemReporter.options;
+	this.optimizeStringLiterals = optimizeStringLiterals;
+	this.initializeScanner();
+	this.astLengthStack = new int[50];
+	this.expressionLengthStack = new int[30];
+	this.intStack = new int[50];
+	this.identifierStack = new char[30][];
+	this.identifierLengthStack = new int[30];
+	this.nestedMethod = new int[30];
+	this.realBlockStack = new int[30];
+	this.identifierPositionStack = new long[30];
+	this.variablesCounter = new int[30];
+	
+	// javadoc support
+	this.javadocParser = new JavadocParser(this);	
+}
+public void arrayInitializer(int length) {
+	//length is the size of the array Initializer
+	//expressionPtr points on the last elt of the arrayInitializer, 
+	// in other words, it has not been decremented yet.
+
+	ArrayInitializer ai = new ArrayInitializer();
+	if (length != 0) {
+		this.expressionPtr -= length;
+		System.arraycopy(this.expressionStack, this.expressionPtr + 1, ai.expressions = new Expression[length], 0, length);
+	}
+	pushOnExpressionStack(ai);
+	//positionning
+	ai.sourceEnd = this.endStatementPosition;
+	ai.sourceStart = this.intStack[this.intPtr--];
+}
+protected void blockReal() {
+	// See consumeLocalVariableDeclarationStatement in case of change: duplicated code
+	// increment the amount of declared variables for this block
+	this.realBlockStack[this.realBlockPtr]++;
+}
 /*
  * Build initial recovery state.
  * Recovery state is inferred from the current state of the parser (reduced node stack).
@@ -479,6 +731,7 @@
 	 * also rebuild bracket balance 
 	 */
 	this.lastCheckPoint = 0;
+	this.lastErrorEndPositionBeforeRecovery = this.scanner.currentPosition;
 
 	RecoveredElement element = null;
 	if (this.referenceContext instanceof CompilationUnitDeclaration){
@@ -492,6 +745,7 @@
 			this.compilationUnit.types = null;
 			this.currentToken = 0;
 			this.listLength = 0;
+			this.listTypeParameterLength = 0;
 			this.endPosition = 0;
 			this.endStatementPosition = 0;
 			return element;
@@ -513,7 +767,7 @@
 				for (int i = 0; i < type.fields.length; i++){
 					FieldDeclaration field = type.fields[i];					
 					if (field != null
-						&& !field.isField()
+						&& field.getKind() == AbstractVariableDeclaration.INITIALIZER
 						&& field.declarationSourceStart <= this.scanner.initialPosition
 						&& this.scanner.initialPosition <= field.declarationSourceEnd
 						&& this.scanner.eofPosition <= field.declarationSourceEnd+1){
@@ -586,16 +840,14 @@
 	}
 	return element;
 }
-public final static short base_check(int i) {
-	return check_table[i - (NUM_RULES + 1)];
-}
-public final void checkAndSetModifiers(int flag){
+
+protected void checkAndSetModifiers(int flag){
 	/*modify the current modifiers buffer.
 	When the startPosition of the modifiers is 0
 	it means that the modifier being parsed is the first
 	of a list of several modifiers. The startPosition
 	is zeroed when a copy of modifiers-buffer is push
-	onto the astStack. */
+	onto the this.astStack. */
 
 	if ((this.modifiers & flag) != 0){ // duplicate modifier
 		this.modifiers |= AccAlternateModifierProblem;
@@ -606,8 +858,9 @@
 }
 public void checkComment() {
 
-	if (this.currentElement != null && this.scanner.commentPtr >= 0) {
-		flushCommentsDefinedPriorTo(this.endStatementPosition); // discard obsolete comments during recovery
+	// discard obsolete comments while inside methods or fields initializer (see bug 74369)
+	if (!(this.diet && this.dietInt==0) && this.scanner.commentPtr >= 0) {
+		flushCommentsDefinedPriorTo(this.endStatementPosition);
 	}
 	
 	int lastComment = this.scanner.commentPtr;
@@ -623,12 +876,14 @@
 		// check deprecation in last comment if javadoc (can be followed by non-javadoc comments which are simply ignored)	
 		while (lastComment >= 0 && this.scanner.commentStops[lastComment] < 0) lastComment--; // non javadoc comment have negative end positions
 		if (lastComment >= 0 && this.javadocParser != null) {
-			if (this.javadocParser.checkDeprecation(
-					this.scanner.commentStarts[lastComment],
-					this.scanner.commentStops[lastComment] - 1)) { //stop is one over,
+			int commentEnd = this.scanner.commentStops[lastComment] - 1; //stop is one over,
+			// do not report problem before last parsed comment while recovering code...
+			this.javadocParser.reportProblems = this.currentElement == null || commentEnd > this.lastJavadocEnd;
+			if (this.javadocParser.checkDeprecation(this.scanner.commentStarts[lastComment], commentEnd)) {
 				checkAndSetModifiers(AccDeprecated);
 			}
-			this.javadoc = this.javadocParser.docComment;	// null if check javadoc is not activated 
+			this.javadoc = this.javadocParser.docComment;	// null if check javadoc is not activated
+			if (currentElement == null) this.lastJavadocEnd = commentEnd;
 		}
 	}
 }
@@ -656,25 +911,7 @@
 		}
 	}
 }
-protected char getNextCharacter(char[] comment, int[] index) {
-	char nextCharacter = comment[index[0]++];
-	switch(nextCharacter) {
-		case '\\' :
-			int c1, c2, c3, c4;
-			index[0]++;
-			while (comment[index[0]] == 'u') index[0]++;
-			if (!(((c1 = Character.getNumericValue(comment[index[0]++])) > 15
-				|| c1 < 0)
-				|| ((c2 = Character.getNumericValue(comment[index[0]++])) > 15 || c2 < 0)
-				|| ((c3 = Character.getNumericValue(comment[index[0]++])) > 15 || c3 < 0)
-				|| ((c4 = Character.getNumericValue(comment[index[0]++])) > 15 || c4 < 0))) {
-					nextCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
-			}
-			break;
-	}
-	return nextCharacter;
-}
-protected void classInstanceCreation(boolean alwaysQualified) {
+protected void classInstanceCreation(boolean hasClassBody) {
 	// ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
 
 	// ClassBodyopt produces a null item on the astStak if it produces NO class body
@@ -686,7 +923,7 @@
 		&& (this.astStack[this.astPtr] == null)) {
 		//NO ClassBody
 		this.astPtr--;
-		if (alwaysQualified) {
+		if (hasClassBody) {
 			alloc = new QualifiedAllocationExpression();
 		} else {
 			alloc = new AllocationExpression();
@@ -703,6 +940,7 @@
 				length); 
 		}
 		alloc.type = getTypeReference(0);
+		
 		//the default constructor with the correct number of argument
 		//will be created and added by the TC (see createsInternalConstructorWithBinding)
 		alloc.sourceStart = this.intStack[this.intPtr--];
@@ -720,30 +958,46 @@
 		}
 		this.astPtr--;
 		this.astLengthPtr--;
-		
+
 		// mark initializers with local type mark if needed
 		markInitializersWithLocalType(anonymousTypeDeclaration);
 	}
 }
-protected final void concatExpressionLists() {
+protected void concatExpressionLists() {
 	this.expressionLengthStack[--this.expressionLengthPtr]++;
 }
-private final void concatNodeLists() {
+protected void concatGenericsLists() {
+	this.genericsLengthStack[this.genericsLengthPtr - 1] += this.genericsLengthStack[this.genericsLengthPtr--];
+}
+protected void concatNodeLists() {
 	/*
-	 * This is a case where you have two sublists into the astStack that you want
-	 * to merge in one list. There is no action required on the astStack. The only
+	 * This is a case where you have two sublists into the this.astStack that you want
+	 * to merge in one list. There is no action required on the this.astStack. The only
 	 * thing you need to do is merge the two lengths specified on the astStackLength.
 	 * The top two length are for example:
 	 * ... p   n
 	 * and you want to result in a list like:
 	 * ... n+p 
 	 * This means that the p could be equals to 0 in case there is no astNode pushed
-	 * on the astStack.
+	 * on the this.astStack.
 	 * Look at the InterfaceMemberDeclarations for an example.
 	 */
 
 	this.astLengthStack[this.astLengthPtr - 1] += this.astLengthStack[this.astLengthPtr--];
 }
+protected void consumeAdditionalBound() {
+	pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--]));
+}
+protected void consumeAdditionalBound1() {
+	// nothing to be done.
+	// The reference type1 is consumed by consumeReferenceType1 method.
+}
+protected void consumeAdditionalBoundList() {
+	concatGenericsLists();
+}
+protected void consumeAdditionalBoundList1() {
+	concatGenericsLists();
+}
 protected void consumeAllocationHeader() {
 	// ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
 
@@ -764,7 +1018,6 @@
 		alloc.type = getTypeReference(0);
 		alloc.sourceStart = anonymousType.sourceStart;
 		alloc.sourceEnd = anonymousType.sourceEnd ;
-		anonymousType.allocation = alloc; 
 		this.lastCheckPoint = anonymousType.bodyStart = this.scanner.currentPosition;
 		this.currentElement = this.currentElement.add(anonymousType, 0);
 		this.lastIgnoredToken = -1;
@@ -774,10 +1027,134 @@
 	this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position
 	this.restartRecovery = true; // request to restart from here on
 }
+protected void consumeAnnotationAsModifier() {
+	// nothing to do
+}
+protected void consumeAnnotationName() {
+	// nothing to do
+}
+protected void consumeAnnotationTypeDeclaration() {
+	int length;
+	if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+		//there are length declarations
+		//dispatch according to the type of the declarations
+		dispatchDeclarationInto(length);
+	}
+
+	TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
+	
+	// mark initializers with local type mark if needed
+	markInitializersWithLocalType(typeDecl);
+
+	//convert constructor that do not have the type's name into methods
+	typeDecl.checkConstructors(this);
+	
+	//always add <clinit> (will be remove at code gen time if empty)
+	if (this.scanner.containsAssertKeyword) {
+		typeDecl.bits |= ASTNode.AddAssertionMASK;
+	}
+	typeDecl.addClinit();
+	typeDecl.bodyEnd = this.endStatementPosition;
+	if (length == 0 && !containsComment(typeDecl.bodyStart, typeDecl.bodyEnd)) {
+		typeDecl.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+	}
+	typeDecl.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition); 
+}
+protected void consumeAnnotationTypeDeclarationHeader() {
+	if (this.currentElement != null) {
+		this.restartRecovery = true; // used to avoid branching back into the regular automaton		
+	}
+}
+protected void consumeAnnotationTypeDeclarationHeaderName() {
+	// consumeAnnotationTypeDeclarationHeader ::= Modifiers '@' PushModifiers interface Identifier
+	// consumeAnnotationTypeDeclarationHeader ::= '@' PushModifiers interface Identifier
+	TypeDeclaration annotationTypeDeclaration = new TypeDeclaration(this.compilationUnit.compilationResult);
+	if (this.nestedMethod[this.nestedType] == 0) {
+		if (this.nestedType != 0) {
+			annotationTypeDeclaration.bits |= ASTNode.IsMemberTypeMASK;
+		}
+	} else {
+		// Record that the block has a declaration for local types
+		annotationTypeDeclaration.bits |= ASTNode.IsLocalTypeMASK;
+		markEnclosingMemberWithLocalType();
+		blockReal();
+	}
+
+	//highlight the name of the type
+	long pos = this.identifierPositionStack[this.identifierPtr];
+	annotationTypeDeclaration.sourceEnd = (int) pos;
+	annotationTypeDeclaration.sourceStart = (int) (pos >>> 32);
+	annotationTypeDeclaration.name = this.identifierStack[this.identifierPtr--];
+	this.identifierLengthPtr--;
+
+	//compute the declaration source too
+	// 'interface' push two int positions: the beginning of the class token and its end.
+	// we want to keep the beginning position but get rid of the end position
+	// it is only used for the ClassLiteralAccess positions.
+	this.intPtr--; // remove the start position of the interface token
+	this.intPtr--; // remove the end position of the interface token
+
+	annotationTypeDeclaration.modifiersSourceStart = this.intStack[this.intPtr--];
+	annotationTypeDeclaration.modifiers = this.intStack[this.intPtr--] | AccAnnotation | AccInterface;
+	if (annotationTypeDeclaration.modifiersSourceStart >= 0) {
+		annotationTypeDeclaration.declarationSourceStart = annotationTypeDeclaration.modifiersSourceStart;
+		this.intPtr--; // remove the position of the '@' token as we have modifiers
+	} else {
+		int atPosition = this.intStack[this.intPtr--];
+		// remove the position of the '@' token as we don't have modifiers
+		annotationTypeDeclaration.declarationSourceStart = atPosition;
+	}
+	// consume annotations
+	int length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			annotationTypeDeclaration.annotations = new Annotation[length], 
+			0, 
+			length); 
+	}
+	annotationTypeDeclaration.bodyStart = annotationTypeDeclaration.sourceEnd + 1;
+
+	// javadoc
+	annotationTypeDeclaration.javadoc = this.javadoc;
+	this.javadoc = null;	
+	pushOnAstStack(annotationTypeDeclaration);
+	if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+			this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+		this.problemReporter().invalidUsageOfAnnotationDeclarations(annotationTypeDeclaration);
+	}	
+	
+	// recovery
+	if (this.currentElement != null){ 
+		this.lastCheckPoint = annotationTypeDeclaration.bodyStart;
+		this.currentElement = this.currentElement.add(annotationTypeDeclaration, 0);
+		this.lastIgnoredToken = -1;
+	}
+}
+protected void consumeAnnotationTypeMemberDeclaration() {
+	// AnnotationTypeMemberDeclaration ::= AnnotationTypeMemberDeclarationHeader AnnotationTypeMemberHeaderExtendedDims DefaultValueopt ';'
+	AnnotationMethodDeclaration annotationTypeMemberDeclaration = (AnnotationMethodDeclaration) this.astStack[this.astPtr];
+	annotationTypeMemberDeclaration.modifiers |= AccSemicolonBody;
+	// store the this.endPosition (position just before the '}') in case there is
+	// a trailing comment behind the end of the method
+	int declarationEndPosition = flushCommentsDefinedPriorTo(this.endStatementPosition);
+	annotationTypeMemberDeclaration.bodyStart = this.endStatementPosition;
+	annotationTypeMemberDeclaration.bodyEnd = declarationEndPosition;
+	annotationTypeMemberDeclaration.declarationSourceEnd = declarationEndPosition;
+}
+protected void consumeAnnotationTypeMemberDeclarations() {
+	// AnnotationTypeMemberDeclarations ::= AnnotationTypeMemberDeclarations AnnotationTypeMemberDeclaration
+	concatNodeLists();
+}
 protected void consumeArgumentList() {
 	// ArgumentList ::= ArgumentList ',' Expression
 	concatExpressionLists();
 }
+protected void consumeArguments() {
+	// Arguments ::= '(' ArgumentListopt ')' 
+	// nothing to do, the expression stack is already updated
+}
 protected void consumeArrayAccess(boolean unspecifiedReference) {
 	// ArrayAccess ::= Name '[' Expression ']' ==> true
 	// ArrayAccess ::= PrimaryNoNewArray '[' Expression ']' ==> false
@@ -802,33 +1179,6 @@
 	}
 	exp.sourceEnd = this.endPosition;
 }
-protected void consumeArrayCreationExpressionWithoutInitializer() {
-	// ArrayCreationWithoutArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs
-	// ArrayCreationWithoutArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs
-
-	int length;
-	ArrayAllocationExpression aae = new ArrayAllocationExpression();
-	aae.type = getTypeReference(0);
-	length = (this.expressionLengthStack[this.expressionLengthPtr--]);
-	this.expressionPtr -= length ;
-	System.arraycopy(
-		this.expressionStack,
-		this.expressionPtr+1,
-		aae.dimensions = new Expression[length],
-		0,
-		length);
-	aae.sourceStart = this.intStack[this.intPtr--];
-	if (aae.initializer == null) {
-		aae.sourceEnd = this.endPosition;
-	} else {
-		aae.sourceEnd = aae.initializer.sourceEnd ;
-	}
-	pushOnExpressionStack(aae);
-}
-
-protected void consumeArrayCreationHeader() {
-	// nothing to do
-}
 protected void consumeArrayCreationExpressionWithInitializer() {
 	// ArrayCreationWithArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializer
 	// ArrayCreationWithArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializer
@@ -855,19 +1205,46 @@
 	}
 	pushOnExpressionStack(aae);
 }
+protected void consumeArrayCreationExpressionWithoutInitializer() {
+	// ArrayCreationWithoutArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs
+	// ArrayCreationWithoutArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs
+
+	int length;
+	ArrayAllocationExpression aae = new ArrayAllocationExpression();
+	aae.type = getTypeReference(0);
+	length = (this.expressionLengthStack[this.expressionLengthPtr--]);
+	this.expressionPtr -= length ;
+	System.arraycopy(
+		this.expressionStack,
+		this.expressionPtr+1,
+		aae.dimensions = new Expression[length],
+		0,
+		length);
+	aae.sourceStart = this.intStack[this.intPtr--];
+	if (aae.initializer == null) {
+		aae.sourceEnd = this.endPosition;
+	} else {
+		aae.sourceEnd = aae.initializer.sourceEnd ;
+	}
+	pushOnExpressionStack(aae);
+}
+protected void consumeArrayCreationHeader() {
+	// nothing to do
+}
 protected void consumeArrayInitializer() {
 	// ArrayInitializer ::= '{' VariableInitializers '}'
 	// ArrayInitializer ::= '{' VariableInitializers , '}'
 
 	arrayInitializer(this.expressionLengthStack[this.expressionLengthPtr--]);
 }
-
+protected void consumeArrayTypeWithTypeArgumentsName() {
+	this.intStack[this.intPtr] += this.identifierLengthStack[this.identifierLengthPtr];
+}
 protected void consumeAssertStatement() {
 	// AssertStatement ::= 'assert' Expression ':' Expression ';'
 	this.expressionLengthPtr-=2;
 	pushOnAstStack(new AssertStatement(this.expressionStack[this.expressionPtr--], this.expressionStack[this.expressionPtr--], this.intStack[this.intPtr--]));
 }
-
 protected void consumeAssignment() {
 	// Assignment ::= LeftHandSide AssignmentOperator AssignmentExpression
 	//optimize the push/pop
@@ -979,6 +1356,133 @@
 						op);
 			}
 			break;
+		case LESS :
+			this.intPtr--;
+			this.expressionStack[this.expressionPtr] = 
+				new BinaryExpression(
+					expr1, 
+					expr2, 
+					op);
+			break;
+		default :
+			this.expressionStack[this.expressionPtr] = 
+				new BinaryExpression(
+					expr1, 
+					expr2, 
+					op);		
+	}
+}
+/**
+ * @param op binary operator
+ */
+protected void consumeBinaryExpressionWithName(int op) {
+	pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+	this.expressionPtr--;
+	this.expressionLengthPtr--;
+	/*
+	if (op == OR_OR) {
+		this.expressionStack[this.expressionPtr] = 
+			new OR_OR_Expression(
+				this.expressionStack[this.expressionPtr + 1], 
+				this.expressionStack[this.expressionPtr], 
+				op); 
+	} else {
+		if (op == AND_AND) {
+			this.expressionStack[this.expressionPtr] = 
+				new AND_AND_Expression(
+					this.expressionStack[this.expressionPtr + 1], 
+					this.expressionStack[this.expressionPtr], 
+					op);
+		} else {
+			// look for "string1" + "string2"
+			if ((op == PLUS) && this.optimizeStringLiterals) {
+				Expression expr1, expr2;
+				expr1 = this.expressionStack[this.expressionPtr + 1];
+				expr2 = this.expressionStack[this.expressionPtr];
+				if (expr1 instanceof StringLiteral) {
+					if (expr2 instanceof CharLiteral) { // string+char
+						this.expressionStack[this.expressionPtr] = 
+							((StringLiteral) expr1).extendWith((CharLiteral) expr2); 
+					} else if (expr2 instanceof StringLiteral) { //string+string
+						this.expressionStack[this.expressionPtr] = 
+							((StringLiteral) expr1).extendWith((StringLiteral) expr2); 
+					} else {
+						this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
+					}
+				} else {
+					this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
+				}
+			} else {
+				this.expressionStack[this.expressionPtr] = 
+					new BinaryExpression(
+						this.expressionStack[this.expressionPtr + 1], 
+						this.expressionStack[this.expressionPtr], 
+						op);
+			}
+		}
+	}
+	*/
+	Expression expr1 = this.expressionStack[this.expressionPtr + 1];
+	Expression expr2 = this.expressionStack[this.expressionPtr];
+	switch(op) {
+		case OR_OR :
+			this.expressionStack[this.expressionPtr] = 
+				new OR_OR_Expression(
+					expr1, 
+					expr2, 
+					op); 
+			break;
+		case AND_AND :
+			this.expressionStack[this.expressionPtr] = 
+				new AND_AND_Expression(
+					expr1, 
+					expr2, 
+					op);
+			break;
+		case PLUS :
+			// look for "string1" + "string2"
+			if (this.optimizeStringLiterals) {
+				if (expr1 instanceof StringLiteral) {
+					if (expr2 instanceof CharLiteral) { // string+char
+						this.expressionStack[this.expressionPtr] = 
+							((StringLiteral) expr1).extendWith((CharLiteral) expr2); 
+					} else if (expr2 instanceof StringLiteral) { //string+string
+						this.expressionStack[this.expressionPtr] = 
+							((StringLiteral) expr1).extendWith((StringLiteral) expr2); 
+					} else {
+						this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
+					}
+				} else {
+					this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
+				}
+			} else if (expr1 instanceof StringLiteral) {
+				if (expr2 instanceof StringLiteral) {
+					// string + string
+					this.expressionStack[this.expressionPtr] = 
+						((StringLiteral) expr1).extendsWith((StringLiteral) expr2); 
+				} else {
+					this.expressionStack[this.expressionPtr] = 
+						new BinaryExpression(
+							expr1, 
+							expr2, 
+							op);
+				}
+			} else {
+				this.expressionStack[this.expressionPtr] = 
+					new BinaryExpression(
+						expr1, 
+						expr2, 
+						op);
+			}
+			break;
+		case LESS :
+			this.intPtr--;
+			this.expressionStack[this.expressionPtr] = 
+				new BinaryExpression(
+					expr1, 
+					expr2, 
+					op);
+			break;
 		default :
 			this.expressionStack[this.expressionPtr] = 
 				new BinaryExpression(
@@ -1026,21 +1530,6 @@
 	Expression expression = this.expressionStack[this.expressionPtr--];
 	pushOnAstStack(new CaseStatement(expression, expression.sourceEnd, this.intStack[this.intPtr--]));
 }
-protected void consumeCastExpression() {
-	// CastExpression ::= PushLPAREN PrimitiveType Dimsopt PushRPAREN InsideCastExpression UnaryExpression
-	// CastExpression ::= PushLPAREN Name Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus
-
-	//this.intStack : posOfLeftParen dim posOfRightParen
-
-	//optimize the push/pop
-
-	Expression exp, cast, castType;
-	int end = this.intStack[this.intPtr--];
-	this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr], castType = getTypeReference(this.intStack[this.intPtr--]));
-	castType.sourceEnd = end - 1;
-	castType.sourceStart = (cast.sourceStart = this.intStack[this.intPtr--]) + 1;
-	cast.sourceEnd = exp.sourceEnd;
-}
 protected void consumeCastExpressionLL1() {
 	//CastExpression ::= '(' Expression ')' InsideCastExpressionLL1 UnaryExpressionNotPlusMinus
 	// Expression is used in order to make the grammar LL1
@@ -1057,6 +1546,123 @@
 	updateSourcePosition(cast);
 	cast.sourceEnd=exp.sourceEnd;
 }
+protected void consumeCastExpressionWithGenericsArray() {
+	// CastExpression ::= PushLPAREN Name TypeArguments Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus
+
+	Expression exp, cast, castType;
+	int end = this.intStack[this.intPtr--];
+
+	int dim = this.intStack[this.intPtr--];
+	pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+	
+	this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr], castType = getTypeReference(dim));
+	intPtr--;
+	castType.sourceEnd = end - 1;
+	castType.sourceStart = (cast.sourceStart = this.intStack[this.intPtr--]) + 1;
+	cast.sourceEnd = exp.sourceEnd;
+}
+protected void consumeCastExpressionWithNameArray() {
+	// CastExpression ::= PushLPAREN Name Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus
+
+	Expression exp, cast, castType;
+	int end = this.intStack[this.intPtr--];
+	
+	// handle type arguments
+	pushOnGenericsLengthStack(0);
+	pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+	
+	this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr], castType = getTypeReference(this.intStack[this.intPtr--]));
+	castType.sourceEnd = end - 1;
+	castType.sourceStart = (cast.sourceStart = this.intStack[this.intPtr--]) + 1;
+	cast.sourceEnd = exp.sourceEnd;
+}
+protected void consumeCastExpressionWithPrimitiveType() {
+	// CastExpression ::= PushLPAREN PrimitiveType Dimsopt PushRPAREN InsideCastExpression UnaryExpression
+
+	//this.intStack : posOfLeftParen dim posOfRightParen
+
+	//optimize the push/pop
+
+	Expression exp, cast, castType;
+	int end = this.intStack[this.intPtr--];
+	this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr], castType = getTypeReference(this.intStack[this.intPtr--]));
+	castType.sourceEnd = end - 1;
+	castType.sourceStart = (cast.sourceStart = this.intStack[this.intPtr--]) + 1;
+	cast.sourceEnd = exp.sourceEnd;
+}
+protected ParameterizedQualifiedTypeReference computeQualifiedGenericsFromRightSide(TypeReference rightSide, int dim) {
+	int nameSize = this.identifierLengthStack[this.identifierLengthPtr];
+	int tokensSize = nameSize;
+	if (rightSide instanceof ParameterizedSingleTypeReference) {
+		tokensSize ++;
+	} else if (rightSide instanceof SingleTypeReference) {
+		tokensSize ++;
+	} else if (rightSide instanceof ParameterizedQualifiedTypeReference) {
+		tokensSize += ((QualifiedTypeReference) rightSide).tokens.length;
+	} else if (rightSide instanceof QualifiedTypeReference) {
+		tokensSize += ((QualifiedTypeReference) rightSide).tokens.length;
+	}
+	TypeReference[][] typeArguments = new TypeReference[tokensSize][];
+	char[][] tokens = new char[tokensSize][];
+	long[] positions = new long[tokensSize];
+	if (rightSide instanceof ParameterizedSingleTypeReference) {
+		ParameterizedSingleTypeReference singleParameterizedTypeReference = (ParameterizedSingleTypeReference) rightSide;
+		tokens[nameSize] = singleParameterizedTypeReference.token;
+		positions[nameSize] = (((long) singleParameterizedTypeReference.sourceStart) << 32) + singleParameterizedTypeReference.sourceEnd;
+		typeArguments[nameSize] = singleParameterizedTypeReference.typeArguments;
+	} else if (rightSide instanceof SingleTypeReference) {
+		SingleTypeReference singleTypeReference = (SingleTypeReference) rightSide;
+		tokens[nameSize] = singleTypeReference.token;
+		positions[nameSize] = (((long) singleTypeReference.sourceStart) << 32) + singleTypeReference.sourceEnd;
+	} else if (rightSide instanceof ParameterizedQualifiedTypeReference) {
+		ParameterizedQualifiedTypeReference parameterizedTypeReference = (ParameterizedQualifiedTypeReference) rightSide;
+		TypeReference[][] rightSideTypeArguments = parameterizedTypeReference.typeArguments;
+		System.arraycopy(rightSideTypeArguments, 0, typeArguments, nameSize, rightSideTypeArguments.length);
+		char[][] rightSideTokens = parameterizedTypeReference.tokens;
+		System.arraycopy(rightSideTokens, 0, tokens, nameSize, rightSideTokens.length);
+		long[] rightSidePositions = parameterizedTypeReference.sourcePositions;
+		System.arraycopy(rightSidePositions, 0, positions, nameSize, rightSidePositions.length);
+	} else if (rightSide instanceof QualifiedTypeReference) {
+		QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) rightSide;
+		char[][] rightSideTokens = qualifiedTypeReference.tokens;
+		System.arraycopy(rightSideTokens, 0, tokens, nameSize, rightSideTokens.length);
+		long[] rightSidePositions = qualifiedTypeReference.sourcePositions;
+		System.arraycopy(rightSidePositions, 0, positions, nameSize, rightSidePositions.length);
+	}
+
+	int currentTypeArgumentsLength = this.genericsLengthStack[this.genericsLengthPtr--];
+	TypeReference[] currentTypeArguments = new TypeReference[currentTypeArgumentsLength];
+	this.genericsPtr -= currentTypeArgumentsLength;
+	System.arraycopy(this.genericsStack, this.genericsPtr + 1, currentTypeArguments, 0, currentTypeArgumentsLength);
+	
+	if (nameSize == 1) {
+		tokens[0] = this.identifierStack[this.identifierPtr];
+		positions[0] = this.identifierPositionStack[this.identifierPtr--];
+		typeArguments[0] = currentTypeArguments;
+	} else {
+		this.identifierPtr -= nameSize;
+		System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, nameSize);
+		System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, nameSize);
+		typeArguments[nameSize - 1] = currentTypeArguments;
+	}
+	this.identifierLengthPtr--;
+	return new ParameterizedQualifiedTypeReference(tokens, typeArguments, dim, positions);
+}
+protected void consumeCastExpressionWithQualifiedGenericsArray() {
+	// CastExpression ::= PushLPAREN Name OnlyTypeArguments '.' ClassOrInterfaceType Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus
+	Expression exp, cast, castType;
+	int end = this.intStack[this.intPtr--];
+
+	int dim = this.intStack[this.intPtr--];
+	TypeReference rightSide = getTypeReference(0);
+	
+	ParameterizedQualifiedTypeReference qualifiedParameterizedTypeReference = computeQualifiedGenericsFromRightSide(rightSide, dim);
+	intPtr--;
+	this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr], castType = qualifiedParameterizedTypeReference);
+	castType.sourceEnd = end - 1;
+	castType.sourceStart = (cast.sourceStart = this.intStack[this.intPtr--]) + 1;
+	cast.sourceEnd = exp.sourceEnd;
+}
 protected void consumeCatches() {
 	// Catches ::= Catches CatchClause
 	optimizedConcatNodeLists();
@@ -1123,7 +1729,7 @@
 protected void consumeClassBodyopt() {
 	// ClassBodyopt ::= $empty
 	pushOnAstStack(null);
-	this.endPosition = this.scanner.startPosition - 1;
+	this.endPosition = this.rParenPos;
 }
 protected void consumeClassDeclaration() {
 	// ClassDeclaration ::= ClassHeader ClassBody
@@ -1144,19 +1750,22 @@
 	boolean hasConstructor = typeDecl.checkConstructors(this);
 	
 	//add the default constructor when needed (interface don't have it)
-	if (!hasConstructor && !typeDecl.isInterface()) {
-		boolean insideFieldInitializer = false;
-		if (this.diet) {
-			for (int i = this.nestedType; i > 0; i--){
-				if (this.variablesCounter[i] > 0) {
-					insideFieldInitializer = true;
-					break;
+	if (!hasConstructor) {
+		switch(typeDecl.kind()) {
+			case IGenericType.CLASS_DECL :
+			case IGenericType.ENUM_DECL :
+				boolean insideFieldInitializer = false;
+				if (this.diet) {
+					for (int i = this.nestedType; i > 0; i--){
+						if (this.variablesCounter[i] > 0) {
+							insideFieldInitializer = true;
+							break;
+						}
+					}
 				}
-			}
+				typeDecl.createDefaultConstructor(!this.diet || insideFieldInitializer, true);
 		}
-		typeDecl.createsInternalConstructor(!this.diet || insideFieldInitializer, true);
 	}
-
 	//always add <clinit> (will be remove at code gen time if empty)
 	if (this.scanner.containsAssertKeyword) {
 		typeDecl.bits |= ASTNode.AddAssertionMASK;
@@ -1184,10 +1793,12 @@
 }
 protected void consumeClassHeaderExtends() {
 	// ClassHeaderExtends ::= 'extends' ClassType
+	//superclass
+	TypeReference superClass = getTypeReference(0);
 	// There is a class declaration on the top of stack
 	TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
-	//superclass
-	typeDecl.superclass = getTypeReference(0);
+	typeDecl.superclass = superClass;
+	superClass.bits |= ASTNode.IsSuperType;
 	typeDecl.bodyStart = typeDecl.superclass.sourceEnd + 1;
 	// recovery
 	if (this.currentElement != null){
@@ -1207,6 +1818,9 @@
 		typeDecl.superInterfaces = new TypeReference[length], 
 		0, 
 		length); 
+	for (int i = 0, max = typeDecl.superInterfaces.length; i < max; i++) {
+		typeDecl.superInterfaces[i].bits |= ASTNode.IsSuperType;
+	}
 	typeDecl.bodyStart = typeDecl.superInterfaces[length-1].sourceEnd + 1;
 	this.listLength = 0; // reset after having read super-interfaces
 	// recovery
@@ -1214,8 +1828,8 @@
 		this.lastCheckPoint = typeDecl.bodyStart;
 	}
 }
-protected void consumeClassHeaderName() {
-	// ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
+protected void consumeClassHeaderName1() {
+	// ClassHeaderName1 ::= Modifiersopt 'class' 'Identifier'
 	TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
 	if (this.nestedMethod[this.nestedType] == 0) {
 		if (this.nestedType != 0) {
@@ -1247,6 +1861,16 @@
 	if (typeDecl.modifiersSourceStart >= 0) {
 		typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
 	}
+	// consume annotations
+	int length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			typeDecl.annotations = new Annotation[length], 
+			0, 
+			length); 
+	}
 	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
 	pushOnAstStack(typeDecl);
 
@@ -1261,6 +1885,24 @@
 	typeDecl.javadoc = this.javadoc;
 	this.javadoc = null;
 }
+protected void consumeTypeHeaderNameWithTypeParameters() {
+	// ClassHeaderName ::= ClassHeaderName1 TypeParameters
+	// InterfaceHeaderName ::= InterfaceHeaderName1 TypeParameters
+	TypeDeclaration typeDecl = (TypeDeclaration)this.astStack[this.astPtr];
+
+	// consume type parameters
+	int length = this.genericsLengthStack[this.genericsLengthPtr--];
+	this.genericsPtr -= length;
+	System.arraycopy(this.genericsStack, this.genericsPtr + 1, typeDecl.typeParameters = new TypeParameter[length], 0, length);
+
+	typeDecl.bodyStart = typeDecl.typeParameters[length-1].declarationSourceEnd + 1;
+	
+	this.listTypeParameterLength = 0;
+	
+	if (this.currentElement != null) { // is recovering
+		this.lastCheckPoint = typeDecl.bodyStart;
+	}
+}
 protected void consumeClassInstanceCreationExpression() {
 	// ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
 	classInstanceCreation(false);
@@ -1272,8 +1914,7 @@
 protected void consumeClassInstanceCreationExpressionQualified() {
 	// ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
 	// ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
-
-	classInstanceCreation(true); //  <-- push the Qualifed....
+	classInstanceCreation(true);
 
 	this.expressionLengthPtr--;
 	QualifiedAllocationExpression qae = 
@@ -1282,10 +1923,138 @@
 	this.expressionStack[this.expressionPtr] = qae;
 	qae.sourceStart = qae.enclosingInstance.sourceStart;
 }
+protected void consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() {
+	// ClassInstanceCreationExpression ::= Primary '.' 'new' TypeArguments SimpleName '(' ArgumentListopt ')' ClassBodyopt
+	// ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' TypeArguments SimpleName '(' ArgumentListopt ')' ClassBodyopt
+
+	QualifiedAllocationExpression alloc;
+	int length;
+	if (((length = this.astLengthStack[this.astLengthPtr--]) == 1) && (this.astStack[this.astPtr] == null)) {
+		//NO ClassBody
+		this.astPtr--;
+		alloc = new QualifiedAllocationExpression();
+		alloc.sourceEnd = this.endPosition; //the position has been stored explicitly
+
+		if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+			this.expressionPtr -= length;
+			System.arraycopy(
+				this.expressionStack, 
+				this.expressionPtr + 1, 
+				alloc.arguments = new Expression[length], 
+				0, 
+				length); 
+		}
+		alloc.type = getTypeReference(0);
+
+		length = this.genericsLengthStack[this.genericsLengthPtr--];
+		this.genericsPtr -= length;
+		System.arraycopy(this.genericsStack, this.genericsPtr + 1, alloc.typeArguments = new TypeReference[length], 0, length);
+		intPtr--;
+
+		//the default constructor with the correct number of argument
+		//will be created and added by the TC (see createsInternalConstructorWithBinding)
+		alloc.sourceStart = this.intStack[this.intPtr--];
+		pushOnExpressionStack(alloc);
+	} else {
+		dispatchDeclarationInto(length);
+		TypeDeclaration anonymousTypeDeclaration = (TypeDeclaration)this.astStack[this.astPtr];
+		anonymousTypeDeclaration.declarationSourceEnd = this.endStatementPosition;
+		anonymousTypeDeclaration.bodyEnd = this.endStatementPosition;
+		if (length == 0 && !containsComment(anonymousTypeDeclaration.bodyStart, anonymousTypeDeclaration.bodyEnd)) {
+			anonymousTypeDeclaration.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+		}
+		this.astPtr--;
+		this.astLengthPtr--;
+
+		QualifiedAllocationExpression allocationExpression = anonymousTypeDeclaration.allocation;
+		if (allocationExpression != null) {
+			allocationExpression.sourceEnd = this.endStatementPosition;
+			// handle type arguments
+			length = this.genericsLengthStack[this.genericsLengthPtr--];
+			this.genericsPtr -= length;
+			System.arraycopy(this.genericsStack, this.genericsPtr + 1, allocationExpression.typeArguments = new TypeReference[length], 0, length);
+			allocationExpression.sourceStart = intStack[intPtr--];
+		}
+		
+		// mark initializers with local type mark if needed
+		markInitializersWithLocalType(anonymousTypeDeclaration);
+	}
+
+	this.expressionLengthPtr--;
+	QualifiedAllocationExpression qae = 
+		(QualifiedAllocationExpression) this.expressionStack[this.expressionPtr--]; 
+	qae.enclosingInstance = this.expressionStack[this.expressionPtr];
+	this.expressionStack[this.expressionPtr] = qae;
+	qae.sourceStart = qae.enclosingInstance.sourceStart;
+}
+protected void consumeClassInstanceCreationExpressionWithTypeArguments() {
+	// ClassInstanceCreationExpression ::= 'new' TypeArguments ClassType '(' ArgumentListopt ')' ClassBodyopt
+	AllocationExpression alloc;
+	int length;
+	if (((length = this.astLengthStack[this.astLengthPtr--]) == 1)
+		&& (this.astStack[this.astPtr] == null)) {
+		//NO ClassBody
+		this.astPtr--;
+		alloc = new AllocationExpression();
+		alloc.sourceEnd = this.endPosition; //the position has been stored explicitly
+
+		if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+			this.expressionPtr -= length;
+			System.arraycopy(
+				this.expressionStack, 
+				this.expressionPtr + 1, 
+				alloc.arguments = new Expression[length], 
+				0, 
+				length); 
+		}
+		alloc.type = getTypeReference(0);
+
+		length = this.genericsLengthStack[this.genericsLengthPtr--];
+		this.genericsPtr -= length;
+		System.arraycopy(this.genericsStack, this.genericsPtr + 1, alloc.typeArguments = new TypeReference[length], 0, length);
+		intPtr--;
+		
+		//the default constructor with the correct number of argument
+		//will be created and added by the TC (see createsInternalConstructorWithBinding)
+		alloc.sourceStart = this.intStack[this.intPtr--];
+		pushOnExpressionStack(alloc);
+	} else {
+		dispatchDeclarationInto(length);
+		TypeDeclaration anonymousTypeDeclaration = (TypeDeclaration)this.astStack[this.astPtr];
+		anonymousTypeDeclaration.declarationSourceEnd = this.endStatementPosition;
+		anonymousTypeDeclaration.bodyEnd = this.endStatementPosition;
+		if (length == 0 && !containsComment(anonymousTypeDeclaration.bodyStart, anonymousTypeDeclaration.bodyEnd)) {
+			anonymousTypeDeclaration.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+		}
+		this.astPtr--;
+		this.astLengthPtr--;
+
+		QualifiedAllocationExpression allocationExpression = anonymousTypeDeclaration.allocation;
+		if (allocationExpression != null) {
+			allocationExpression.sourceEnd = this.endStatementPosition;
+			// handle type arguments
+			length = this.genericsLengthStack[this.genericsLengthPtr--];
+			this.genericsPtr -= length;
+			System.arraycopy(this.genericsStack, this.genericsPtr + 1, allocationExpression.typeArguments = new TypeReference[length], 0, length);
+			allocationExpression.sourceStart = intStack[intPtr--];
+		}
+		
+		// mark initializers with local type mark if needed
+		markInitializersWithLocalType(anonymousTypeDeclaration);
+	}
+}
+protected void consumeClassOrInterface() {
+	this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr] += this.identifierLengthStack[this.identifierLengthPtr];
+	pushOnGenericsLengthStack(0); // handle type arguments
+}
+protected void consumeClassOrInterfaceName() {
+	pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+	pushOnGenericsLengthStack(0); // handle type arguments
+}
 protected void consumeClassTypeElt() {
 	// ClassTypeElt ::= ClassType
 	pushOnAstStack(getTypeReference(0));
-	/* if incomplete thrown exception list, listLength counter will not have been reset,
+	/* if incomplete thrown exception list, this.listLength counter will not have been reset,
 		indicating that some items are available on the stack */
 	this.listLength++; 	
 }
@@ -1294,13 +2063,13 @@
 	optimizedConcatNodeLists();
 }
 protected void consumeCompilationUnit() {
-	// CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt
+	// CompilationUnit ::= EnterCompilationUnit InternalCompilationUnit
 	// do nothing by default
 }
 protected void consumeConditionalExpression(int op) {
 	// ConditionalExpression ::= ConditionalOrExpression '?' Expression ':' ConditionalExpression
 	//optimize the push/pop
-
+	this.intPtr -= 2;//consume position of the question mark
 	this.expressionPtr -= 2;
 	this.expressionLengthPtr -= 2;
 	this.expressionStack[this.expressionPtr] =
@@ -1309,6 +2078,21 @@
 			this.expressionStack[this.expressionPtr + 1],
 			this.expressionStack[this.expressionPtr + 2]);
 }
+/**
+ * @param op
+ */
+protected void consumeConditionalExpressionWithName(int op) {
+	// ConditionalExpression ::= Name '?' Expression ':' ConditionalExpression
+	this.intPtr -= 2;//consume position of the question mark
+	pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+	this.expressionPtr -= 2;
+	this.expressionLengthPtr -= 2;
+	this.expressionStack[this.expressionPtr] =
+		new ConditionalExpression(
+			this.expressionStack[this.expressionPtr + 2],
+			this.expressionStack[this.expressionPtr],
+			this.expressionStack[this.expressionPtr + 1]);
+}
 protected void consumeConstructorBlockStatements() {
 	// ConstructorBody ::= NestedMethod '{' ExplicitConstructorInvocation BlockStatements '}'
 	concatNodeLists(); // explictly add the first statement into the list of statements 
@@ -1322,11 +2106,11 @@
 	// ConstructorDeclaration ::= ConstructorHeader ConstructorBody
 
 	/*
-	astStack : MethodDeclaration statements
-	identifierStack : name
+	this.astStack : MethodDeclaration statements
+	this.identifierStack : name
 	 ==>
-	astStack : MethodDeclaration
-	identifierStack :
+	this.astStack : MethodDeclaration
+	this.identifierStack :
 	*/
 
 	//must provide a default constructor call when needed
@@ -1396,23 +2180,11 @@
 	}
 
 	//watch for } that could be given as a unicode ! ( u007D is '}' )
-	// store the endPosition (position just before the '}') in case there is
+	// store the this.endPosition (position just before the '}') in case there is
 	// a trailing comment behind the end of the method
 	cd.bodyEnd = this.endPosition;
 	cd.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition); 
 }
-
-protected void consumeInvalidConstructorDeclaration() {
-	// ConstructorDeclaration ::= ConstructorHeader ';'
-	// now we know that the top of stack is a constructorDeclaration
-	ConstructorDeclaration cd = (ConstructorDeclaration) this.astStack[this.astPtr];
-
-	cd.bodyEnd = this.endPosition; // position just before the trailing semi-colon
-	cd.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition); 
-	// report the problem and continue the parsing - narrowing the problem onto the method
-	
-	cd.modifiers |= AccSemicolonBody; // remember semi-colon body
-}
 protected void consumeConstructorHeader() {
 	// ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
 
@@ -1456,6 +2228,16 @@
 	//modifiers
 	cd.declarationSourceStart = this.intStack[this.intPtr--];
 	cd.modifiers = this.intStack[this.intPtr--];
+	// consume annotations
+	int length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			cd.annotations = new Annotation[length], 
+			0, 
+			length); 
+	}	
 	// javadoc
 	cd.javadoc = this.javadoc;
 	this.javadoc = null;
@@ -1465,7 +2247,64 @@
 	pushOnAstStack(cd);
 	cd.sourceEnd = this.lParenPos;
 	cd.bodyStart = this.lParenPos+1;
-	this.listLength = 0; // initialize listLength before reading parameters/throws
+	this.listLength = 0; // initialize this.listLength before reading parameters/throws
+
+	// recovery
+	if (this.currentElement != null){
+		this.lastCheckPoint = cd.bodyStart;
+		if ((this.currentElement instanceof RecoveredType && this.lastIgnoredToken != TokenNameDOT)
+			|| cd.modifiers != 0){
+			this.currentElement = this.currentElement.add(cd, 0);
+			this.lastIgnoredToken = -1;
+		}
+	}	
+}
+protected void consumeConstructorHeaderNameWithTypeParameters() {
+
+	/* recovering - might be an empty message send */
+	if (this.currentElement != null){
+		if (this.lastIgnoredToken == TokenNamenew){ // was an allocation expression
+			this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position				
+			this.restartRecovery = true;
+			return;
+		}
+	}
+	
+	// ConstructorHeaderName ::=  Modifiersopt TypeParameters 'Identifier' '('
+	ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationUnit.compilationResult);
+
+	//name -- this is not really revelant but we do .....
+	cd.selector = this.identifierStack[this.identifierPtr];
+	long selectorSource = this.identifierPositionStack[this.identifierPtr--];
+	this.identifierLengthPtr--;
+
+	// consume type parameters
+	int length = this.genericsLengthStack[this.genericsLengthPtr--];
+	this.genericsPtr -= length;
+	System.arraycopy(this.genericsStack, this.genericsPtr + 1, cd.typeParameters = new TypeParameter[length], 0, length);
+	
+	//modifiers
+	cd.declarationSourceStart = this.intStack[this.intPtr--];
+	cd.modifiers = this.intStack[this.intPtr--];
+	// consume annotations
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			cd.annotations = new Annotation[length], 
+			0, 
+			length); 
+	}
+	// javadoc
+	cd.javadoc = this.javadoc;
+	this.javadoc = null;
+
+	//highlight starts at the selector starts
+	cd.sourceStart = (int) (selectorSource >>> 32);
+	pushOnAstStack(cd);
+	cd.sourceEnd = this.lParenPos;
+	cd.bodyStart = this.lParenPos+1;
+	this.listLength = 0; // initialize this.listLength before reading parameters/throws
 
 	// recovery
 	if (this.currentElement != null){
@@ -1487,6 +2326,7 @@
 	pushOnIntStack(
 		this.modifiersSourceStart >= 0 ? this.modifiersSourceStart : this.scanner.startPosition); 
 	resetModifiers();
+	pushOnExpressionStackLengthStack(0); // no annotation
 }
 protected void consumeDiet() {
 	// Diet ::= $empty
@@ -1513,10 +2353,18 @@
 	// DimWithOrWithOutExprs ::= DimWithOrWithOutExprs DimWithOrWithOutExpr
 	concatExpressionLists();
 }
+protected void consumeEmptyAnnotationTypeMemberDeclarationsopt() {
+	// AnnotationTypeMemberDeclarationsopt ::= $empty
+	pushOnAstLengthStack(0);
+}
 protected void consumeEmptyArgumentListopt() {
 	// ArgumentListopt ::= $empty
 	pushOnExpressionStackLengthStack(0);
 }
+protected void consumeEmptyArguments() {
+	// Argumentsopt ::= $empty
+	pushOnExpressionStackLengthStack(0);
+}
 protected void consumeEmptyArrayInitializer() {
 	// ArrayInitializer ::= '{' ,opt '}'
 	arrayInitializer(0);
@@ -1543,10 +2391,21 @@
 	problemReporter().superfluousSemicolon(this.endPosition+1, this.endStatementPosition);
 	flushCommentsDefinedPriorTo(this.endStatementPosition);
 }
+protected void consumeEmptyMethodHeaderDefaultValue() {
+	// DefaultValueopt ::= $empty
+	AbstractMethodDeclaration method = (AbstractMethodDeclaration)this.astStack[this.astPtr];
+	if(method.isAnnotationMethod()) { //'method' can be a MethodDeclaration when recovery is started
+		pushOnExpressionStackLengthStack(0);
+	}
+}
 protected void consumeEmptyDimsopt() {
 	// Dimsopt ::= $empty
 	pushOnIntStack(0);
 }
+protected void consumeEmptyEnumDeclarations() {
+	// EnumBodyDeclarationsopt ::= $empty
+	pushOnAstLengthStack(0);
+}
 protected void consumeEmptyExpression() {
 	// Expressionopt ::= $empty
 	pushOnExpressionStackLengthStack(0);
@@ -1559,10 +2418,6 @@
 	// ForUpdateopt ::= $empty
 	pushOnExpressionStackLengthStack(0);
 }
-protected void consumeEmptyImportDeclarationsopt() {
-	// ImportDeclarationsopt ::= $empty
-	pushOnAstLengthStack(0);
-}
 protected void consumeEmptyInterfaceMemberDeclaration() {
 	// InterfaceMemberDeclaration ::= ';'
 	pushOnAstLengthStack(0);
@@ -1571,6 +2426,19 @@
 	// InterfaceMemberDeclarationsopt ::= $empty
 	pushOnAstLengthStack(0);
 }
+protected void consumeEmptyInternalCompilationUnit() {
+	// InternalCompilationUnit ::= $empty
+	// nothing to do by default
+}
+protected void consumeEmptyMemberValuePairsopt() {
+	// MemberValuePairsopt ::= $empty
+	pushOnAstLengthStack(0);
+}
+protected void consumeEmptyMemberValueArrayInitializer() {
+	// MemberValueArrayInitializer ::= '{' ',' '}'
+	// MemberValueArrayInitializer ::= '{' '}'
+	arrayInitializer(0);
+}
 protected void consumeEmptyStatement() {
 	// EmptyStatement ::= ';'
 	if (this.scanner.source[this.endStatementPosition] == ';') {
@@ -1590,17 +2458,90 @@
 	problemReporter().superfluousSemicolon(this.endPosition+1, this.endStatementPosition);
 	flushCommentsDefinedPriorTo(this.endStatementPosition);
 }
-protected void consumeEmptyTypeDeclarationsopt() {
-	// TypeDeclarationsopt ::= $empty
-	pushOnAstLengthStack(0); 
+protected void consumeEnhancedForStatementHeader(boolean hasModifiers){
+	// EnhancedForStatementHeader ::= 'for' '(' Type PushModifiers Identifier Dimsopt ':' Expression ')'
+	// EnhancedForStatementHeader ::= 'for' '(' Modifiers Type PushRealModifiers Identifier Dimsopt ':' Expression ')'
+	TypeReference type;
+
+	char[] identifierName = this.identifierStack[this.identifierPtr];
+	long namePosition = this.identifierPositionStack[this.identifierPtr];
+	
+	LocalDeclaration localDeclaration = createLocalDeclaration(identifierName, (int) (namePosition >>> 32), (int) namePosition);
+	localDeclaration.declarationSourceEnd = localDeclaration.declarationEnd;
+	
+	int extraDims = this.intStack[this.intPtr--];
+	this.identifierPtr--;
+	this.identifierLengthPtr--;
+	// remove fake modifiers/modifiers start
+	int declarationSourceStart = 0;
+	int modifiersValue  = 0;
+	if (hasModifiers) {
+		declarationSourceStart = this.intStack[this.intPtr--];
+		modifiersValue = this.intStack[this.intPtr--];
+	} else {
+		this.intPtr-=2;
+	}
+
+	//updates are on the expression stack
+	this.expressionLengthPtr--;
+	Expression collection = this.expressionStack[this.expressionPtr--];
+	
+	type = getTypeReference(this.intStack[this.intPtr--] + extraDims); // type dimension
+
+	// consume annotations
+	int length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--])!= 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			localDeclaration.annotations = new Annotation[length], 
+			0, 
+			length); 
+	}
+	if (hasModifiers) {
+		localDeclaration.declarationSourceStart = declarationSourceStart;
+		localDeclaration.modifiers = modifiersValue;
+	} else {
+		localDeclaration.declarationSourceStart = type.sourceStart;
+	}
+	localDeclaration.type = type;
+
+	ForeachStatement iteratorForStatement =
+		new ForeachStatement(
+			localDeclaration,
+			collection,
+			this.intStack[this.intPtr--]); 
+	pushOnAstStack(iteratorForStatement);
+	
+	if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+			this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+		this.problemReporter().invalidUsageOfForeachStatements(localDeclaration, collection);
+	}
+}
+protected void consumeEnhancedForStatement() {
+	// EnhancedForStatement ::= EnhancedForStatementHeader Statement
+	// EnhancedForStatementNoShortIf ::= EnhancedForStatementHeader StatementNoShortIf
+
+	//statements
+	this.astLengthPtr--;
+	Statement statement = (Statement) this.astStack[this.astPtr--];
+
+	// foreach statement is on the ast stack
+	ForeachStatement foreachStatement = (ForeachStatement) this.astStack[this.astPtr];
+	foreachStatement.action = statement;
+	// remember useful empty statement
+	if (statement instanceof EmptyStatement) statement.bits |= ASTNode.IsUsefulEmptyStatementMASK;
+	
+	foreachStatement.sourceEnd = this.endStatementPosition;
 }
 protected void consumeEnterAnonymousClassBody() {
 	// EnterAnonymousClassBody ::= $empty
-	QualifiedAllocationExpression alloc;
+	TypeReference typeReference = getTypeReference(0);
+
 	TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult); 
 	anonymousType.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
 	anonymousType.bits |= ASTNode.AnonymousAndLocalMask;
-	alloc = anonymousType.allocation = new QualifiedAllocationExpression(anonymousType); 
+	QualifiedAllocationExpression alloc = new QualifiedAllocationExpression(anonymousType); 
 	markEnclosingMemberWithLocalType();
 	pushOnAstStack(anonymousType);
 
@@ -1615,7 +2556,49 @@
 			0, 
 			argumentLength); 
 	}
-	alloc.type = getTypeReference(0);
+	alloc.type = typeReference;
+
+	anonymousType.sourceEnd = alloc.sourceEnd;
+	//position at the type while it impacts the anonymous declaration
+	anonymousType.sourceStart = anonymousType.declarationSourceStart = alloc.type.sourceStart;
+	alloc.sourceStart = this.intStack[this.intPtr--];
+	pushOnExpressionStack(alloc);
+
+	anonymousType.bodyStart = this.scanner.currentPosition;	
+	this.listLength = 0; // will be updated when reading super-interfaces
+	// recovery
+	if (this.currentElement != null){ 
+		this.lastCheckPoint = anonymousType.bodyStart;		
+		this.currentElement = this.currentElement.add(anonymousType, 0);
+		this.currentToken = 0; // opening brace already taken into account
+		this.lastIgnoredToken = -1;
+	}	
+}
+protected void consumeEnterAnonymousClassBodySimpleName() {
+	// EnterAnonymousClassBody ::= $empty
+	pushOnGenericsLengthStack(0);
+	pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+	TypeReference typeReference = getTypeReference(0);
+
+	TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult); 
+	anonymousType.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
+	anonymousType.bits |= ASTNode.AnonymousAndLocalMask;
+	QualifiedAllocationExpression alloc = new QualifiedAllocationExpression(anonymousType); 
+	markEnclosingMemberWithLocalType();
+	pushOnAstStack(anonymousType);
+
+	alloc.sourceEnd = this.rParenPos; //the position has been stored explicitly
+	int argumentLength;
+	if ((argumentLength = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		this.expressionPtr -= argumentLength;
+		System.arraycopy(
+			this.expressionStack, 
+			this.expressionPtr + 1, 
+			alloc.arguments = new Expression[argumentLength], 
+			0, 
+			argumentLength); 
+	}
+	alloc.type = typeReference;
 
 	anonymousType.sourceEnd = alloc.sourceEnd;
 	//position at the type while it impacts the anonymous declaration
@@ -1667,6 +2650,16 @@
 		if (isLocalDeclaration) {
 			declaration.declarationSourceStart = this.intStack[this.intPtr--];
 			declaration.modifiers = this.intStack[this.intPtr--];
+			// consume annotations
+			int length;
+			if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+				System.arraycopy(
+					this.expressionStack, 
+					(this.expressionPtr -= length) + 1, 
+					declaration.annotations = new Annotation[length], 
+					0, 
+					length); 
+			}	
 			type = getTypeReference(typeDim = this.intStack[this.intPtr--]); // type dimension
 			if (declaration.declarationSourceStart == -1) {
 				// this is true if there is no modifiers for the local variable declaration
@@ -1678,7 +2671,16 @@
 			pushOnAstStack(type);
 			declaration.declarationSourceStart = this.intStack[this.intPtr--];
 			declaration.modifiers = this.intStack[this.intPtr--];
-			
+			// consume annotations
+			int length;
+			if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+				System.arraycopy(
+					this.expressionStack, 
+					(this.expressionPtr -= length) + 1, 
+					declaration.annotations = new Annotation[length], 
+					0, 
+					length); 
+			}			
 			// Store javadoc only on first declaration as it is the same for all ones
 			FieldDeclaration fieldDeclaration = (FieldDeclaration) declaration;
 			fieldDeclaration.javadoc = this.javadoc;
@@ -1697,7 +2699,7 @@
 		declaration.type = type;
 	} else {
 		int dimension = typeDim + extendedDimension;
-		//on the identifierLengthStack there is the information about the type....
+		//on the this.identifierLengthStack there is the information about the type....
 		int baseType;
 		if ((baseType = this.identifierLengthStack[this.identifierLengthPtr + 1]) < 0) {
 			//it was a baseType
@@ -1736,6 +2738,275 @@
 		this.lastIgnoredToken = -1;
 	}
 }
+protected void consumeEnumBodyNoConstants() {
+	// nothing to do
+	// The 0 on the astLengthStack has been pushed by EnumBodyDeclarationsopt
+}
+protected void consumeEnumBodyWithConstants() {
+	// merge the constants values with the class body
+	concatNodeLists();
+}
+protected void consumeEnumConstantHeaderName() {
+	if (this.currentElement != null) {
+		if (!(this.currentElement instanceof RecoveredType
+					|| (this.currentElement instanceof RecoveredField && ((RecoveredField)currentElement).fieldDeclaration.type == null))
+				|| (this.lastIgnoredToken == TokenNameDOT)) {
+			this.lastCheckPoint = this.scanner.startPosition;
+			this.restartRecovery = true;
+			return;
+		}
+	}
+   long namePosition = this.identifierPositionStack[this.identifierPtr];
+   char[] constantName = this.identifierStack[this.identifierPtr--];
+   final int sourceEnd = (int) namePosition;
+   FieldDeclaration enumConstant = createFieldDeclaration(constantName, (int) (namePosition >>> 32), sourceEnd);
+   this.identifierLengthPtr--;
+   enumConstant.modifiersSourceStart = this.intStack[this.intPtr--];
+   enumConstant.modifiers = this.intStack[this.intPtr--];
+   enumConstant.declarationSourceStart = enumConstant.modifiersSourceStart;
+   // consume annotations
+   int length;
+   if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+      System.arraycopy(
+         this.expressionStack, 
+         (this.expressionPtr -= length) + 1, 
+         enumConstant.annotations = new Annotation[length], 
+         0, 
+         length); 
+   }
+   pushOnAstStack(enumConstant);
+	if (this.currentElement != null){
+		this.lastCheckPoint = enumConstant.sourceEnd + 1;
+		this.currentElement = this.currentElement.add(enumConstant, 0);		
+	}
+	// javadoc
+	enumConstant.javadoc = this.javadoc;
+	this.javadoc = null;
+}
+protected void consumeEnumConstantHeader() {
+   FieldDeclaration enumConstant = (FieldDeclaration) this.astStack[this.astPtr];
+   boolean foundOpeningBrace = this.currentToken == TokenNameLBRACE;
+   if (foundOpeningBrace){
+      // qualified allocation expression
+      TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult);
+      anonymousType.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
+      anonymousType.bits |= ASTNode.AnonymousAndLocalMask;
+      final int start = this.scanner.startPosition;
+      anonymousType.declarationSourceStart = start;
+      anonymousType.sourceStart = start;
+      anonymousType.sourceEnd = start; // closing parenthesis
+      anonymousType.modifiers = 0;
+      anonymousType.bodyStart = this.scanner.currentPosition;
+      markEnclosingMemberWithLocalType();
+      pushOnAstStack(anonymousType);
+      QualifiedAllocationExpression allocationExpression = new QualifiedAllocationExpression(anonymousType);
+      allocationExpression.enumConstant = enumConstant;
+      
+      // fill arguments if needed
+      int length;
+      if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+         this.expressionPtr -= length;
+         System.arraycopy(
+               this.expressionStack, 
+               this.expressionPtr + 1, 
+               allocationExpression.arguments = new Expression[length], 
+               0, 
+               length); 
+      }
+      enumConstant.initialization = allocationExpression;
+   } else {
+      AllocationExpression allocationExpression = new AllocationExpression();
+      allocationExpression.enumConstant = enumConstant;
+      // fill arguments if needed
+      int length;
+      if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+         this.expressionPtr -= length;
+         System.arraycopy(
+               this.expressionStack, 
+               this.expressionPtr + 1, 
+               allocationExpression.arguments = new Expression[length], 
+               0, 
+               length); 
+      }
+      enumConstant.initialization = allocationExpression;
+   }
+   
+   // recovery
+   if (this.currentElement != null) {
+	  if(foundOpeningBrace) {
+	  	TypeDeclaration anonymousType = (TypeDeclaration) this.astStack[this.astPtr];
+	  	this.currentElement = this.currentElement.add(anonymousType, 0);
+      	this.lastCheckPoint = anonymousType.bodyStart;
+        this.lastIgnoredToken = -1;
+        this.currentToken = 0; // opening brace already taken into account
+	  } else {
+	  	  if(this.currentToken == TokenNameSEMICOLON) {
+		  	RecoveredType currentType = this.currentRecoveryType();
+			if(currentType != null) {
+				currentType.insideEnumConstantPart = false;
+			}
+		  }
+	      if (!(this.currentElement instanceof RecoveredType)
+	            && (this.currentToken == TokenNameDOT)){
+	         this.lastCheckPoint = enumConstant.sourceStart;
+	         this.restartRecovery = true;
+	         return;
+	      }
+		  this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position
+	      this.lastIgnoredToken = -1;
+	      this.restartRecovery = true;
+	  }
+   }
+}
+protected void consumeEnumConstantNoClassBody() {
+	// set declarationEnd and declarationSourceEnd
+	final FieldDeclaration fieldDeclaration = (FieldDeclaration) this.astStack[this.astPtr];
+	int declarationEnd = fieldDeclaration.sourceEnd;
+	if (declarationEnd > rParenPos) {
+		fieldDeclaration.declarationEnd = declarationEnd;
+		fieldDeclaration.declarationSourceEnd = flushCommentsDefinedPriorTo(declarationEnd);
+	} else {
+		fieldDeclaration.declarationEnd = rParenPos;
+		fieldDeclaration.declarationSourceEnd = flushCommentsDefinedPriorTo(rParenPos);
+	}
+}
+protected void consumeEnumConstants() {
+	concatNodeLists();
+}
+protected void consumeEnumConstantWithClassBody() {
+   dispatchDeclarationInto(this.astLengthStack[this.astLengthPtr--]);
+   TypeDeclaration anonymousType = (TypeDeclaration) this.astStack[this.astPtr--]; // pop type
+   this.astLengthPtr--;
+   anonymousType.bodyEnd = this.endPosition;
+   anonymousType.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
+   final FieldDeclaration fieldDeclaration = ((FieldDeclaration) this.astStack[this.astPtr]);
+   fieldDeclaration.declarationEnd = this.endStatementPosition;
+   fieldDeclaration.declarationSourceEnd = anonymousType.declarationSourceEnd;
+}
+protected void consumeEnumDeclaration() {
+	// EnumDeclaration ::= EnumHeader ClassHeaderImplementsopt EnumBody
+	int length;
+	if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+		//there are length declarations
+		//dispatch according to the type of the declarations
+		dispatchDeclarationIntoEnumDeclaration(length);
+	}
+
+	TypeDeclaration enumDeclaration = (TypeDeclaration) this.astStack[this.astPtr];
+
+	// mark initializers with local type mark if needed
+	markInitializersWithLocalType(enumDeclaration);
+
+	//convert constructor that do not have the type's name into methods
+	boolean hasConstructor = enumDeclaration.checkConstructors(this);
+	
+	//add the default constructor when needed
+	if (!hasConstructor) {
+		boolean insideFieldInitializer = false;
+		if (this.diet) {
+			for (int i = this.nestedType; i > 0; i--){
+				if (this.variablesCounter[i] > 0) {
+					insideFieldInitializer = true;
+					break;
+				}
+			}
+		}
+		enumDeclaration.createDefaultConstructor(!this.diet || insideFieldInitializer, true);
+	}
+
+	//always add <clinit> (will be remove at code gen time if empty)
+	if (this.scanner.containsAssertKeyword) {
+		enumDeclaration.bits |= ASTNode.AddAssertionMASK;
+	}
+	enumDeclaration.addClinit();
+	enumDeclaration.bodyEnd = this.endStatementPosition;
+	if (length == 0 && !containsComment(enumDeclaration.bodyStart, enumDeclaration.bodyEnd)) {
+		enumDeclaration.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+	}
+
+	enumDeclaration.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition); 
+}
+protected void consumeEnumDeclarations() {
+	// Do nothing by default
+}
+protected void consumeEnumHeader() {
+	TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];	
+	if (this.currentToken == TokenNameLBRACE) { 
+		typeDecl.bodyStart = this.scanner.currentPosition;
+	}
+
+	if (this.currentElement != null) {
+		this.restartRecovery = true; // used to avoid branching back into the regular automaton		
+	}
+	
+	// flush the comments related to the enum header
+	this.scanner.commentPtr = -1;
+}
+protected void consumeEnumHeaderName() {
+	// EnumHeaderName ::= Modifiersopt 'enum' Identifier
+	TypeDeclaration enumDeclaration = new TypeDeclaration(this.compilationUnit.compilationResult);
+	if (this.nestedMethod[this.nestedType] == 0) {
+		if (this.nestedType != 0) {
+			enumDeclaration.bits |= ASTNode.IsMemberTypeMASK;
+		}		
+	} else {
+		// Record that the block has a declaration for local types
+//		markEnclosingMemberWithLocalType();
+		blockReal();
+	}
+	//highlight the name of the type
+	long pos = this.identifierPositionStack[this.identifierPtr];
+	enumDeclaration.sourceEnd = (int) pos;
+	enumDeclaration.sourceStart = (int) (pos >>> 32);
+	enumDeclaration.name = this.identifierStack[this.identifierPtr--];
+	this.identifierLengthPtr--;
+
+	//compute the declaration source too
+	// 'class' and 'interface' push two int positions: the beginning of the class token and its end.
+	// we want to keep the beginning position but get rid of the end position
+	// it is only used for the ClassLiteralAccess positions.
+	enumDeclaration.declarationSourceStart = this.intStack[this.intPtr--]; 
+	this.intPtr--; // remove the end position of the class token
+
+	enumDeclaration.modifiersSourceStart = this.intStack[this.intPtr--];
+	enumDeclaration.modifiers = this.intStack[this.intPtr--] | AccEnum;
+	if (enumDeclaration.modifiersSourceStart >= 0) {
+		enumDeclaration.declarationSourceStart = enumDeclaration.modifiersSourceStart;
+	}
+	// consume annotations
+	int length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			enumDeclaration.annotations = new Annotation[length], 
+			0, 
+			length); 
+	}
+//	if (this.currentToken == TokenNameLBRACE) { 
+//		enumDeclaration.bodyStart = this.scanner.currentPosition;
+//	}
+	enumDeclaration.bodyStart = enumDeclaration.sourceEnd + 1;
+	pushOnAstStack(enumDeclaration);
+
+	this.listLength = 0; // will be updated when reading super-interfaces
+	
+	if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+			this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+		//TODO this code will be never run while 'enum' is an identifier in 1.3 scanner 
+		this.problemReporter().invalidUsageOfEnumDeclarations(enumDeclaration);
+	}
+	
+	// recovery
+	if (this.currentElement != null){ 
+		this.lastCheckPoint = enumDeclaration.bodyStart;
+		this.currentElement = this.currentElement.add(enumDeclaration, 0);
+		this.lastIgnoredToken = -1;
+	}
+	// javadoc
+	enumDeclaration.javadoc = this.javadoc;
+	this.javadoc = null;
+}
 protected void consumeEqualityExpression(int op) {
 	// EqualityExpression ::= EqualityExpression '==' RelationalExpression
 	// EqualityExpression ::= EqualityExpression '!=' RelationalExpression
@@ -1750,6 +3021,21 @@
 			this.expressionStack[this.expressionPtr + 1],
 			op);
 }
+/*
+ * @param op
+ */
+protected void consumeEqualityExpressionWithName(int op) {
+	// EqualityExpression ::= Name '==' RelationalExpression
+	// EqualityExpression ::= Name '!=' RelationalExpression
+	pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+	this.expressionPtr--;
+	this.expressionLengthPtr--;
+	this.expressionStack[this.expressionPtr] =
+		new EqualExpression(
+			this.expressionStack[this.expressionPtr + 1],
+			this.expressionStack[this.expressionPtr],
+			op);
+}
 protected void consumeExitTryBlock() {
 	//ExitTryBlock ::= $empty
 	if(this.currentElement != null) {
@@ -1775,7 +3061,11 @@
 	
 	AbstractVariableDeclaration variableDecl = (AbstractVariableDeclaration) this.astStack[this.astPtr];
 	variableDecl.declarationSourceEnd = variableDecl.declarationEnd;
-	
+	if(this.currentElement != null && this.currentElement instanceof RecoveredField) {
+		if(this.endStatementPosition > variableDecl.sourceEnd) {
+			this.currentElement.updateSourceEndIfNecessary(this.endStatementPosition);
+		}
+	}
 	this.recoveryExitFromVariable();
 }
 protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
@@ -1813,6 +3103,47 @@
 	pushOnAstStack(ecc);
 	ecc.sourceEnd = this.endPosition;
 }
+protected void consumeExplicitConstructorInvocationWithTypeArguments(int flag, int recFlag) {
+
+	/* flag allows to distinguish 3 cases :
+	(0) :   
+	ExplicitConstructorInvocation ::= TypeArguments 'this' '(' ArgumentListopt ')' ';'
+	ExplicitConstructorInvocation ::= TypeArguments 'super' '(' ArgumentListopt ')' ';'
+	(1) :
+	ExplicitConstructorInvocation ::= Primary '.' TypeArguments 'super' '(' ArgumentListopt ')' ';'
+	ExplicitConstructorInvocation ::= Primary '.' TypeArguments 'this' '(' ArgumentListopt ')' ';'
+	(2) :
+	ExplicitConstructorInvocation ::= Name '.' TypeArguments 'super' '(' ArgumentListopt ')' ';'
+	ExplicitConstructorInvocation ::= Name '.' TypeArguments 'this' '(' ArgumentListopt ')' ';'
+	*/
+	int startPosition = this.intStack[this.intPtr--];
+	ExplicitConstructorCall ecc = new ExplicitConstructorCall(recFlag);
+	int length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		this.expressionPtr -= length;
+		System.arraycopy(this.expressionStack, this.expressionPtr + 1, ecc.arguments = new Expression[length], 0, length);
+	}
+	length = this.genericsLengthStack[this.genericsLengthPtr--];
+	this.genericsPtr -= length;
+	System.arraycopy(this.genericsStack, this.genericsPtr + 1, ecc.typeArguments = new TypeReference[length], 0, length);
+	ecc.typeArgumentsSourceStart = this.intStack[intPtr--];
+
+	switch (flag) {
+		case 0 :
+			ecc.sourceStart = startPosition;
+			break;
+		case 1 :
+			this.expressionLengthPtr--;
+			ecc.sourceStart = (ecc.qualification = this.expressionStack[this.expressionPtr--]).sourceStart;
+			break;
+		case 2 :
+			ecc.sourceStart = (ecc.qualification = getUnspecifiedReferenceOptimized()).sourceStart;
+			break;
+	}
+	
+	pushOnAstStack(ecc);
+	ecc.sourceEnd = this.endPosition;
+}
 protected void consumeExpressionStatement() {
 	// ExpressionStatement ::= StatementExpression ';'
 	this.expressionLengthPtr--;
@@ -1846,15 +3177,15 @@
 	// FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
 
 	/*
-	astStack : 
-	expressionStack: Expression Expression ...... Expression
-	identifierStack : type  identifier identifier ...... identifier
-	intStack : typeDim      dim        dim               dim
+	this.astStack : 
+	this.expressionStack: Expression Expression ...... Expression
+	this.identifierStack : type  identifier identifier ...... identifier
+	this.intStack : typeDim      dim        dim               dim
 	 ==>
-	astStack : FieldDeclaration FieldDeclaration ...... FieldDeclaration
-	expressionStack :
-	identifierStack : 
-	intStack : 
+	this.astStack : FieldDeclaration FieldDeclaration ...... FieldDeclaration
+	this.expressionStack :
+	this.identifierStack : 
+	this.intStack : 
 	  
 	*/
 	int variableDeclaratorsCounter = this.astLengthStack[this.astLengthPtr];
@@ -1873,7 +3204,7 @@
 			fieldDeclaration.declarationSourceEnd = endPos;
 		}
 	}
-	// update the astStack, astPtr and astLengthStack
+	// update the this.astStack, this.astPtr and this.astLengthStack
 	int startIndex = this.astPtr - this.variablesCounter[this.nestedType] + 1;
 	System.arraycopy(
 		this.astStack, 
@@ -1904,23 +3235,37 @@
 	// ForInit ::= StatementExpressionList
 	pushOnAstLengthStack(-1);
 }
-protected void consumeFormalParameter() {
+protected void consumeFormalParameter(boolean isVarArgs) {
 	// FormalParameter ::= Type VariableDeclaratorId ==> false
 	// FormalParameter ::= Modifiers Type VariableDeclaratorId ==> true
 	/*
-	astStack : 
-	identifierStack : type identifier
-	intStack : dim dim
+	this.astStack : 
+	this.identifierStack : type identifier
+	this.intStack : dim dim
 	 ==>
-	astStack : Argument
-	identifierStack :  
-	intStack :  
+	this.astStack : Argument
+	this.identifierStack :   
+	this.intStack :  
 	*/
 
 	this.identifierLengthPtr--;
 	char[] identifierName = this.identifierStack[this.identifierPtr];
 	long namePositions = this.identifierPositionStack[this.identifierPtr--];
-	TypeReference type = getTypeReference(this.intStack[this.intPtr--] + this.intStack[this.intPtr--]);
+	int extendedDimensions = this.intStack[this.intPtr--];
+	int endOfEllipsis = 0;
+	if (isVarArgs) {
+		endOfEllipsis = this.intStack[this.intPtr--];
+	}
+	int firstDimensions = this.intStack[this.intPtr--];
+	final int typeDimensions = firstDimensions + extendedDimensions;
+	TypeReference type = getTypeReference(typeDimensions);
+	if (isVarArgs) {
+		type = type.copyDims(typeDimensions + 1);
+		if (extendedDimensions == 0) {
+			type.sourceEnd = endOfEllipsis;
+		}
+		type.bits |= ASTNode.IsVarArgs; // set isVarArgs
+	}
 	int modifierPositions = this.intStack[this.intPtr--];
 	this.intPtr--;
 	Argument arg = 
@@ -1930,11 +3275,30 @@
 			type, 
 			this.intStack[this.intPtr + 1] & ~AccDeprecated); // modifiers
 	arg.declarationSourceStart = modifierPositions;
+	// consume annotations
+	int length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			arg.annotations = new Annotation[length], 
+			0, 
+			length); 
+	}
 	pushOnAstStack(arg);
 
-	/* if incomplete method header, listLength counter will not have been reset,
+	/* if incomplete method header, this.listLength counter will not have been reset,
 		indicating that some arguments are available on the stack */
 	this.listLength++; 	
+	
+	if(isVarArgs) {
+		if (options.sourceLevel < ClassFileConstants.JDK1_5 &&
+				this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+				this.problemReporter().invalidUsageOfVarargs(arg);
+		} else if (extendedDimensions > 0) {
+			this.problemReporter().illegalExtendedDimensions(arg);
+		}
+	}
 }
 protected void consumeFormalParameterList() {
 	// FormalParameterList ::= FormalParameterList ',' FormalParameter
@@ -1944,30 +3308,48 @@
 	// FormalParameterListopt ::= $empty
 	pushOnAstLengthStack(0);
 }
+protected void consumeGenericType() {
+	// nothing to do
+	// Will be consume by a getTypeRefence call
+}
+protected void consumeGenericTypeArrayType() {
+	// nothing to do
+	// Will be consume by a getTypeRefence call
+}
+protected void consumeGenericTypeNameArrayType() {
+	pushOnGenericsLengthStack(0); // handle type arguments
+}
+protected void consumeImportDeclaration() {
+	// SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName ';'
+	ImportReference impt = (ImportReference) this.astStack[this.astPtr];
+	// flush annotations defined prior to import statements
+	impt.declarationEnd = this.endStatementPosition;
+	impt.declarationSourceEnd = 
+		this.flushCommentsDefinedPriorTo(impt.declarationSourceEnd); 
+
+	// recovery
+	if (this.currentElement != null) {
+		this.lastCheckPoint = impt.declarationSourceEnd + 1;
+		this.currentElement = this.currentElement.add(impt, 0);
+		this.lastIgnoredToken = -1;
+		this.restartRecovery = true; 
+		// used to avoid branching back into the regular automaton
+	}
+}
 protected void consumeImportDeclarations() {
 	// ImportDeclarations ::= ImportDeclarations ImportDeclaration 
 	optimizedConcatNodeLists();
 }
-protected void consumeImportDeclarationsopt() {
-	// ImportDeclarationsopt ::= ImportDeclarations
-	int length;
-	if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
-		this.astPtr -= length;
-		System.arraycopy(
-			this.astStack,
-			this.astPtr + 1,
-			this.compilationUnit.imports = new ImportReference[length],
-			0,
-			length);
-	}
-}
 protected void consumeInsideCastExpression() {
 	// InsideCastExpression ::= $empty
 }
 protected void consumeInsideCastExpressionLL1() {
 	// InsideCastExpressionLL1 ::= $empty
+	pushOnExpressionStack(getUnspecifiedReferenceOptimized());
 }
-
+protected void consumeInsideCastExpressionWithQualifiedGenerics() {
+	// InsideCastExpressionWithQualifiedGenerics ::= $empty
+}
 protected void consumeInstanceOfExpression(int op) {
 	// RelationalExpression ::= RelationalExpression 'instanceof' ReferenceType
 	//optimize the push/pop
@@ -1985,6 +3367,28 @@
 	}
 	//the scanner is on the next token already....
 }
+/**
+ * @param op
+ */
+protected void consumeInstanceOfExpressionWithName(int op) {
+	// RelationalExpression_NotName ::= Name instanceof ReferenceType
+	//optimize the push/pop
+
+	//by construction, no base type may be used in getTypeReference
+	TypeReference reference = getTypeReference(this.intStack[this.intPtr--]);
+	pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+	Expression exp;
+	this.expressionStack[this.expressionPtr] = exp =
+		new InstanceOfExpression(
+			this.expressionStack[this.expressionPtr],
+			reference,
+			op);
+	if (exp.sourceEnd == 0) {
+		//array on base type....
+		exp.sourceEnd = this.scanner.startPosition - 1;
+	}
+	//the scanner is on the next token already....
+}
 protected void consumeInterfaceDeclaration() {
 	// see consumeClassDeclaration in case of changes: duplicated code
 	// InterfaceDeclaration ::= InterfaceHeader InterfaceBody
@@ -2039,6 +3443,9 @@
 		typeDecl.superInterfaces = new TypeReference[length], 
 		0, 
 		length); 
+	for (int i = 0, max = typeDecl.superInterfaces.length; i < max; i++) {
+		typeDecl.superInterfaces[i].bits |= ASTNode.IsSuperType;
+	}
 	typeDecl.bodyStart = typeDecl.superInterfaces[length-1].sourceEnd + 1;		
 	this.listLength = 0; // reset after having read super-interfaces		
 	// recovery
@@ -2046,7 +3453,7 @@
 		this.lastCheckPoint = typeDecl.bodyStart;
 	}
 }
-protected void consumeInterfaceHeaderName() {
+protected void consumeInterfaceHeaderName1() {
 	// InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
 	TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
 
@@ -2075,10 +3482,20 @@
 	typeDecl.declarationSourceStart = this.intStack[this.intPtr--];
 	this.intPtr--; // remove the end position of the class token
 	typeDecl.modifiersSourceStart = this.intStack[this.intPtr--];
-	typeDecl.modifiers = this.intStack[this.intPtr--];
+	typeDecl.modifiers = this.intStack[this.intPtr--] | AccInterface;
 	if (typeDecl.modifiersSourceStart >= 0) {
 		typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
 	}
+	// consume annotations
+	int length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			typeDecl.annotations = new Annotation[length], 
+			0, 
+			length); 
+	}
 	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
 	pushOnAstStack(typeDecl);
 	this.listLength = 0; // will be updated when reading super-interfaces
@@ -2103,7 +3520,7 @@
 protected void consumeInterfaceType() {
 	// InterfaceType ::= ClassOrInterfaceType
 	pushOnAstStack(getTypeReference(0));
-	/* if incomplete type header, listLength counter will not have been reset,
+	/* if incomplete type header, this.listLength counter will not have been reset,
 		indicating that some interfaces are available on the stack */
 	this.listLength++; 	
 }
@@ -2111,6 +3528,34 @@
 	// InterfaceTypeList ::= InterfaceTypeList ',' InterfaceType
 	optimizedConcatNodeLists();
 }
+protected void consumeInternalCompilationUnit() {
+	// InternalCompilationUnit ::= PackageDeclaration
+	// InternalCompilationUnit ::= PackageDeclaration ImportDeclarations ReduceImports
+	// InternalCompilationUnit ::= ImportDeclarations ReduceImports
+}
+protected void consumeInternalCompilationUnitWithTypes() {
+	// InternalCompilationUnit ::= PackageDeclaration ImportDeclarations ReduceImports TypeDeclarations
+	// InternalCompilationUnit ::= PackageDeclaration TypeDeclarations
+	// InternalCompilationUnit ::= TypeDeclarations
+	// InternalCompilationUnit ::= ImportDeclarations ReduceImports TypeDeclarations
+	// consume type declarations
+	int length;
+	if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+		this.astPtr -= length;
+		System.arraycopy(this.astStack, this.astPtr + 1, this.compilationUnit.types = new TypeDeclaration[length], 0, length);
+	}
+}
+protected void consumeInvalidConstructorDeclaration() {
+	// ConstructorDeclaration ::= ConstructorHeader ';'
+	// now we know that the top of stack is a constructorDeclaration
+	ConstructorDeclaration cd = (ConstructorDeclaration) this.astStack[this.astPtr];
+
+	cd.bodyEnd = this.endPosition; // position just before the trailing semi-colon
+	cd.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition); 
+	// report the problem and continue the parsing - narrowing the problem onto the method
+	
+	cd.modifiers |= AccSemicolonBody; // remember semi-colon body
+}
 protected void consumeLeftParen() {
 	// PushLPAREN ::= '('
 	pushOnIntStack(this.lParenPos);
@@ -2119,20 +3564,20 @@
 	// LocalVariableDeclaration ::= Modifiers Type VariableDeclarators ';'
 
 	/*
-	astStack : 
-	expressionStack: Expression Expression ...... Expression
-	identifierStack : type  identifier identifier ...... identifier
-	intStack : typeDim      dim        dim               dim
+	this.astStack : 
+	this.expressionStack: Expression Expression ...... Expression
+	this.identifierStack : type  identifier identifier ...... identifier
+	this.intStack : typeDim      dim        dim               dim
 	 ==>
-	astStack : FieldDeclaration FieldDeclaration ...... FieldDeclaration
-	expressionStack :
-	identifierStack : 
-	intStack : 
+	this.astStack : FieldDeclaration FieldDeclaration ...... FieldDeclaration
+	this.expressionStack :
+	this.identifierStack : 
+	this.intStack : 
 	  
 	*/
 	int variableDeclaratorsCounter = this.astLengthStack[this.astLengthPtr];
 
-	// update the astStack, astPtr and astLengthStack
+	// update the this.astStack, this.astPtr and this.astLengthStack
 	int startIndex = this.astPtr - this.variablesCounter[this.nestedType] + 1;
 	System.arraycopy(
 		this.astStack, 
@@ -2159,6 +3604,70 @@
 	}
 
 }
+protected void consumeMarkerAnnotation() {
+	// MarkerAnnotation ::= '@' Name
+	MarkerAnnotation markerAnnotation = null;
+	int length = this.identifierLengthStack[this.identifierLengthPtr--];
+	TypeReference typeReference;
+	if (length == 1) {
+		typeReference = new SingleTypeReference(
+				this.identifierStack[this.identifierPtr], 
+				this.identifierPositionStack[this.identifierPtr--]);
+	} else {
+		char[][] tokens = new char[length][];
+		this.identifierPtr -= length;
+		long[] positions = new long[length];
+		System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+		System.arraycopy(
+			this.identifierPositionStack, 
+			this.identifierPtr + 1, 
+			positions, 
+			0, 
+			length);
+		typeReference = new QualifiedTypeReference(tokens, positions);
+	}
+	markerAnnotation = new MarkerAnnotation(typeReference, this.intStack[this.intPtr--]);
+	int sourceStart = markerAnnotation.sourceStart;
+	if (this.modifiersSourceStart < 0) {
+		this.modifiersSourceStart = sourceStart;
+	} else if (this.modifiersSourceStart > sourceStart) {
+		this.modifiersSourceStart = sourceStart;
+	}
+	markerAnnotation.declarationSourceEnd = markerAnnotation.sourceEnd;
+	pushOnExpressionStack(markerAnnotation);
+	if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+			this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+		this.problemReporter().invalidUsageOfAnnotation(markerAnnotation);
+	}
+}
+protected void consumeMemberValueArrayInitializer() {
+	// MemberValueArrayInitializer ::= '{' MemberValues ',' '}'
+	// MemberValueArrayInitializer ::= '{' MemberValues '}'
+	arrayInitializer(this.expressionLengthStack[this.expressionLengthPtr--]);
+}
+protected void consumeMemberValueAsName() {
+	pushOnExpressionStack(getUnspecifiedReferenceOptimized());	
+}
+protected void consumeMemberValuePair() {
+	// MemberValuePair ::= SimpleName '=' MemberValue
+	char[] simpleName = this.identifierStack[this.identifierPtr];
+	long position = this.identifierPositionStack[this.identifierPtr--];
+	this.identifierLengthPtr--;
+	int end = (int) position;
+	int start = (int) (position >>> 32);
+	Expression value = this.expressionStack[this.expressionPtr--];
+	this.expressionLengthPtr--;
+	MemberValuePair memberValuePair = new MemberValuePair(simpleName, start, end, value);
+	pushOnAstStack(memberValuePair);
+}
+protected void consumeMemberValuePairs() {
+	// MemberValuePairs ::= MemberValuePairs ',' MemberValuePair
+	concatNodeLists();
+}
+protected void consumeMemberValues() {
+	// MemberValues ::= MemberValues ',' MemberValue
+	concatExpressionLists();
+}
 protected void consumeMethodBody() {
 	// MethodBody ::= NestedMethod '{' BlockStatementsopt '}' 
 	this.nestedMethod[this.nestedType] --;
@@ -2168,13 +3677,13 @@
 	// AbstractMethodDeclaration ::= MethodHeader ';'
 
 	/*
-	astStack : modifiers arguments throws statements
-	identifierStack : type name
-	intStack : dim dim dim
+	this.astStack : modifiers arguments throws statements
+	this.identifierStack : type name
+	this.intStack : dim dim dim
 	 ==>
-	astStack : MethodDeclaration
-	identifierStack :
-	intStack : 
+	this.astStack : MethodDeclaration
+	this.identifierStack :
+	this.intStack : 
 	*/
 
 	int length;
@@ -2215,13 +3724,17 @@
 			}
 		}
 	}
-	// store the endPosition (position just before the '}') in case there is
+	// store the this.endPosition (position just before the '}') in case there is
 	// a trailing comment behind the end of the method
 	md.bodyEnd = this.endPosition;
 	md.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
 }
 protected void consumeMethodHeader() {
 	// MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
+	// AnnotationMethodHeader ::= AnnotationMethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims AnnotationMethodHeaderDefaultValueopt
+	// RecoveryMethodHeader ::= RecoveryMethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims AnnotationMethodHeaderDefaultValueopt
+	// RecoveryMethodHeader ::= RecoveryMethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims MethodHeaderThrowsClause
+	
 	// retrieve end position of method declarator
 	AbstractMethodDeclaration method = (AbstractMethodDeclaration)this.astStack[this.astPtr];
 
@@ -2230,7 +3743,13 @@
 	}
 	// recovery
 	if (this.currentElement != null){
-		if (this.currentToken == TokenNameSEMICOLON){
+//		if(method.isAnnotationMethod()) {
+//			method.modifiers |= AccSemicolonBody;
+//			method.declarationSourceEnd = this.scanner.currentPosition-1;
+//			method.bodyEnd = this.scanner.currentPosition-1;
+//			this.currentElement = this.currentElement.parent;
+//		} else 
+		if (this.currentToken == TokenNameSEMICOLON /*&& !method.isAnnotationMethod()*/){
 			method.modifiers |= AccSemicolonBody;			
 			method.declarationSourceEnd = this.scanner.currentPosition-1;
 			method.bodyEnd = this.scanner.currentPosition-1;
@@ -2241,11 +3760,36 @@
 		this.restartRecovery = true; // used to avoid branching back into the regular automaton
 	}		
 }
+protected void consumeMethodHeaderDefaultValue() {
+	// MethodHeaderDefaultValue ::= DefaultValue
+	MethodDeclaration md = (MethodDeclaration) this.astStack[this.astPtr];
+
+	
+	int length = this.expressionLengthStack[this.expressionLengthPtr--];
+	if (length == 1) {
+		intPtr--; // we get rid of the position of the default keyword
+		intPtr--; // we get rid of the position of the default keyword
+		if(md.isAnnotationMethod()) {
+			((AnnotationMethodDeclaration)md).defaultValue = this.expressionStack[this.expressionPtr];
+			md.modifiers |=  AccAnnotationDefault;
+		}
+		this.expressionPtr--;
+	}
+
+	if(this.currentElement != null) {
+		if(md.isAnnotationMethod()) {
+			this.currentElement.updateSourceEndIfNecessary(((AnnotationMethodDeclaration)md).defaultValue.sourceEnd);
+		}
+	}
+}
 protected void consumeMethodHeaderExtendedDims() {
 	// MethodHeaderExtendedDims ::= Dimsopt
 	// now we update the returnType of the method
 	MethodDeclaration md = (MethodDeclaration) this.astStack[this.astPtr];
 	int extendedDims = this.intStack[this.intPtr--];
+	if(md.isAnnotationMethod()) {
+		((AnnotationMethodDeclaration)md).extendedDimensions = extendedDims;
+	}
 	if (extendedDims != 0) {
 		TypeReference returnType = md.returnType;
 		md.sourceEnd = this.endPosition;
@@ -2271,9 +3815,16 @@
 		}		
 	}
 }
-protected void consumeMethodHeaderName() {
+protected void consumeMethodHeaderName(boolean isAnnotationMethod) {
 	// MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
-	MethodDeclaration md = new MethodDeclaration(this.compilationUnit.compilationResult);
+	// AnnotationMethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+	// RecoveryMethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+	MethodDeclaration md = null;
+	if(isAnnotationMethod) {
+		md = new AnnotationMethodDeclaration(this.compilationUnit.compilationResult);
+	} else {
+		md = new MethodDeclaration(this.compilationUnit.compilationResult);
+	}
 
 	//name
 	md.selector = this.identifierStack[this.identifierPtr];
@@ -2284,6 +3835,16 @@
 	//modifiers
 	md.declarationSourceStart = this.intStack[this.intPtr--];
 	md.modifiers = this.intStack[this.intPtr--];
+	// consume annotations
+	int length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			md.annotations = new Annotation[length], 
+			0, 
+			length); 
+	}
 	// javadoc
 	md.javadoc = this.javadoc;
 	this.javadoc = null;
@@ -2293,7 +3854,7 @@
 	pushOnAstStack(md);
 	md.sourceEnd = this.lParenPos;
 	md.bodyStart = this.lParenPos+1;
-	this.listLength = 0; // initialize listLength before reading parameters/throws
+	this.listLength = 0; // initialize this.listLength before reading parameters/throws
 	
 	// recovery
 	if (this.currentElement != null){
@@ -2310,7 +3871,68 @@
 		}
 	}		
 }
-protected void consumeMethodHeaderParameters() {
+protected void consumeMethodHeaderNameWithTypeParameters(boolean isAnnotationMethod) {
+	// MethodHeaderName ::= Modifiersopt TypeParameters Type 'Identifier' '('
+	// AnnotationMethodHeaderName ::= Modifiersopt TypeParameters Type 'Identifier' '('
+	// RecoveryMethodHeaderName ::= Modifiersopt TypeParameters Type 'Identifier' '('
+	MethodDeclaration md = null;
+	if(isAnnotationMethod) {
+		md = new AnnotationMethodDeclaration(this.compilationUnit.compilationResult);
+	} else {
+		md = new MethodDeclaration(this.compilationUnit.compilationResult);
+	}
+
+	//name
+	md.selector = this.identifierStack[this.identifierPtr];
+	long selectorSource = this.identifierPositionStack[this.identifierPtr--];
+	this.identifierLengthPtr--;
+	//type
+	md.returnType = getTypeReference(this.intStack[this.intPtr--]);
+	
+	// consume type parameters
+	int length = this.genericsLengthStack[this.genericsLengthPtr--];
+	this.genericsPtr -= length;
+	System.arraycopy(this.genericsStack, this.genericsPtr + 1, md.typeParameters = new TypeParameter[length], 0, length);
+	
+	//modifiers
+	md.declarationSourceStart = this.intStack[this.intPtr--];
+	md.modifiers = this.intStack[this.intPtr--];
+	// consume annotations
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			md.annotations = new Annotation[length], 
+			0, 
+			length); 
+	}	
+	// javadoc
+	md.javadoc = this.javadoc;
+	this.javadoc = null;
+
+	//highlight starts at selector start
+	md.sourceStart = (int) (selectorSource >>> 32);
+	pushOnAstStack(md);
+	md.sourceEnd = this.lParenPos;
+	md.bodyStart = this.lParenPos+1;
+	this.listLength = 0; // initialize this.listLength before reading parameters/throws
+	
+	// recovery
+	if (this.currentElement != null){
+		if (this.currentElement instanceof RecoveredType 
+			//|| md.modifiers != 0
+			|| (this.scanner.getLineNumber(md.returnType.sourceStart)
+					== this.scanner.getLineNumber(md.sourceStart))){
+			this.lastCheckPoint = md.bodyStart;
+			this.currentElement = this.currentElement.add(md, 0);
+			this.lastIgnoredToken = -1;
+		} else {
+			this.lastCheckPoint = md.sourceStart;
+			this.restartRecovery = true;
+		}
+	}		
+}
+protected void consumeMethodHeaderRightParen() {
 	// MethodHeaderParameters ::= FormalParameterListopt ')'
 	int length = this.astLengthStack[this.astLengthPtr--];
 	this.astPtr -= length;
@@ -2326,7 +3948,7 @@
 			length); 
 	}
 	md.bodyStart = this.rParenPos+1;
-	this.listLength = 0; // reset listLength after having read all parameters
+	this.listLength = 0; // reset this.listLength after having read all parameters
 	// recovery
 	if (this.currentElement != null){
 		this.lastCheckPoint = md.bodyStart;
@@ -2356,11 +3978,11 @@
 		length);
 	md.sourceEnd = md.thrownExceptions[length-1].sourceEnd;
 	md.bodyStart = md.thrownExceptions[length-1].sourceEnd + 1;
-	this.listLength = 0; // reset listLength after having read all thrown exceptions	
+	this.listLength = 0; // reset this.listLength after having read all thrown exceptions	
 	// recovery
 	if (this.currentElement != null){
 		this.lastCheckPoint = md.bodyStart;
-	}		
+	}
 }
 protected void consumeMethodInvocationName() {
 	// MethodInvocation ::= Name '(' ArgumentListopt ')'
@@ -2382,6 +4004,28 @@
 	}
 	pushOnExpressionStack(m);
 }
+protected void consumeMethodInvocationNameWithTypeArguments() {
+	// MethodInvocation ::= Name '.' TypeArguments 'Identifier' '(' ArgumentListopt ')'
+
+	// when the name is only an identifier...we have a message send to "this" (implicit)
+
+	MessageSend m = newMessageSendWithTypeArguments();
+	m.sourceEnd = this.rParenPos;
+	m.sourceStart = 
+		(int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32); 
+	m.selector = this.identifierStack[this.identifierPtr--];
+	this.identifierLengthPtr--;
+
+	// handle type arguments
+	int length = this.genericsLengthStack[this.genericsLengthPtr--];
+	this.genericsPtr -= length;
+	System.arraycopy(this.genericsStack, this.genericsPtr + 1, m.typeArguments = new TypeReference[length], 0, length);
+	intPtr--;
+	
+	m.receiver = getUnspecifiedReference();
+	m.sourceStart = m.receiver.sourceStart;		
+	pushOnExpressionStack(m);
+}
 protected void consumeMethodInvocationPrimary() {
 	//optimize the push/pop
 	//MethodInvocation ::= Primary '.' 'Identifier' '(' ArgumentListopt ')'
@@ -2396,6 +4040,27 @@
 	m.sourceEnd = this.rParenPos;
 	this.expressionStack[this.expressionPtr] = m;
 }
+protected void consumeMethodInvocationPrimaryWithTypeArguments() {
+	//optimize the push/pop
+	//MethodInvocation ::= Primary '.' TypeArguments 'Identifier' '(' ArgumentListopt ')'
+
+	MessageSend m = newMessageSendWithTypeArguments();
+	m.sourceStart = 
+		(int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32); 
+	m.selector = this.identifierStack[this.identifierPtr--];
+	this.identifierLengthPtr--;
+	
+	// handle type arguments
+	int length = this.genericsLengthStack[this.genericsLengthPtr--];
+	this.genericsPtr -= length;
+	System.arraycopy(this.genericsStack, this.genericsPtr + 1, m.typeArguments = new TypeReference[length], 0, length);
+	intPtr--;
+
+	m.receiver = this.expressionStack[this.expressionPtr];
+	m.sourceStart = m.receiver.sourceStart;
+	m.sourceEnd = this.rParenPos;
+	this.expressionStack[this.expressionPtr] = m;
+}
 protected void consumeMethodInvocationSuper() {
 	// MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
 
@@ -2408,6 +4073,25 @@
 	m.receiver = new SuperReference(m.sourceStart, this.endPosition);
 	pushOnExpressionStack(m);
 }
+protected void consumeMethodInvocationSuperWithTypeArguments() {
+	// MethodInvocation ::= 'super' '.' TypeArguments 'Identifier' '(' ArgumentListopt ')'
+
+	MessageSend m = newMessageSendWithTypeArguments();
+	m.sourceStart = this.intStack[this.intPtr--];
+	m.sourceEnd = this.rParenPos;
+	m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr];
+	m.selector = this.identifierStack[this.identifierPtr--];
+	this.identifierLengthPtr--;
+	
+	// handle type arguments
+	int length = this.genericsLengthStack[this.genericsLengthPtr--];
+	this.genericsPtr -= length;
+	System.arraycopy(this.genericsStack, this.genericsPtr + 1, m.typeArguments = new TypeReference[length], 0, length);
+	intPtr--;
+
+	m.receiver = new SuperReference(m.sourceStart, this.endPosition);
+	pushOnExpressionStack(m);
+}
 protected void consumeModifiers() {
 	int savedModifiersSourceStart = this.modifiersSourceStart;	
 	checkComment(); // might update modifiers with AccDeprecated
@@ -2418,6 +4102,13 @@
 	pushOnIntStack(this.modifiersSourceStart);
 	resetModifiers();
 }
+protected void consumeModifiers2() {
+	this.expressionLengthStack[this.expressionLengthPtr - 1] += this.expressionLengthStack[this.expressionLengthPtr--];
+}
+protected void consumeNameArrayType() {
+	pushOnGenericsLengthStack(0); // handle type arguments
+	pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+}
 protected void consumeNestedMethod() {
 	// NestedMethod ::= $empty
 	jumpOverMethodBody();
@@ -2442,6 +4133,50 @@
 	this.nestedMethod[this.nestedType] = 0;
 	this.variablesCounter[this.nestedType] = 0;
 }
+protected void consumeNormalAnnotation() {
+	// NormalAnnotation ::= '@' Name '(' MemberValuePairsopt ')'
+	NormalAnnotation normalAnnotation = null;
+	int length = this.identifierLengthStack[this.identifierLengthPtr--];
+	TypeReference typeReference;
+	if (length == 1) {
+		typeReference = new SingleTypeReference(
+				this.identifierStack[this.identifierPtr], 
+				this.identifierPositionStack[this.identifierPtr--]);
+	} else {
+		char[][] tokens = new char[length][];
+		this.identifierPtr -= length;
+		long[] positions = new long[length];
+		System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+		System.arraycopy(
+			this.identifierPositionStack, 
+			this.identifierPtr + 1, 
+			positions, 
+			0, 
+			length);
+		typeReference = new QualifiedTypeReference(tokens, positions);
+	}
+	normalAnnotation = new NormalAnnotation(typeReference, this.intStack[this.intPtr--]);
+	if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.astStack, 
+			(this.astPtr -= length) + 1, 
+			normalAnnotation.memberValuePairs = new MemberValuePair[length], 
+			0, 
+			length); 
+	}
+	int sourceStart = normalAnnotation.sourceStart;
+	if (this.modifiersSourceStart < 0) {
+		this.modifiersSourceStart = sourceStart;
+	} else if (this.modifiersSourceStart > sourceStart) {
+		this.modifiersSourceStart = sourceStart;
+	}
+	normalAnnotation.declarationSourceEnd = this.rParenPos;
+	pushOnExpressionStack(normalAnnotation);
+	if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+			this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+		this.problemReporter().invalidUsageOfAnnotation(normalAnnotation);
+	}
+}
 protected void consumeOneDimLoop() {
 	// OneDimLoop ::= '[' ']'
 	this.dimensions++;
@@ -2450,6 +4185,19 @@
 	// OnlySynchronized ::= 'synchronized'
 	pushOnIntStack(this.synchronizedBlockSourceStart);
 	resetModifiers();
+	this.expressionLengthPtr--;
+}
+protected void consumeOnlyTypeArguments() {
+	if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+			this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+		int length = this.genericsLengthStack[this.genericsLengthPtr];
+		this.problemReporter().invalidUsageOfTypeArguments(
+			(TypeReference)this.genericsStack[this.genericsPtr - length + 1],
+			(TypeReference)this.genericsStack[this.genericsPtr]);
+	}
+}
+protected void consumeOnlyTypeArgumentsForCastExpression() {
+	// OnlyTypeArgumentsForCastExpression ::= OnlyTypeArguments
 }
 protected void consumeOpenBlock() {
 	// OpenBlock ::= $empty
@@ -2491,9 +4239,10 @@
 		this.identifierPtr--, 
 		positions, 
 		0, 
-		length); 
-	this.compilationUnit.currentPackage = 
-		impt = new ImportReference(tokens, positions, true, AccDefault); 
+		length);
+	
+	impt = new ImportReference(tokens, positions, true, AccDefault);
+	this.compilationUnit.currentPackage = impt; 
 
 	if (this.currentToken == TokenNameSEMICOLON){
 		impt.declarationSourceEnd = this.scanner.currentPosition - 1;
@@ -2501,7 +4250,7 @@
 		impt.declarationSourceEnd = impt.sourceEnd;
 	}
 	impt.declarationEnd = impt.declarationSourceEnd;
-	//endPosition is just before the ;
+	//this.endPosition is just before the ;
 	impt.declarationSourceStart = this.intStack[this.intPtr--];
 
 	// recovery
@@ -2510,6 +4259,57 @@
 		this.restartRecovery = true; // used to avoid branching back into the regular automaton		
 	}	
 }
+protected void consumePackageDeclarationNameWithModifiers() {
+	// PackageDeclarationName ::= Modifiers 'package' Name
+	/* build an ImportRef build from the last name 
+	stored in the identifier stack. */
+
+	ImportReference impt;
+	int length;
+	char[][] tokens = 
+		new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][]; 
+	this.identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(this.identifierStack, ++this.identifierPtr, tokens, 0, length);
+	System.arraycopy(
+		this.identifierPositionStack, 
+		this.identifierPtr--, 
+		positions, 
+		0, 
+		length);
+	
+	int packageModifiersSourceStart = this.intStack[this.intPtr--]; // we don't need the modifiers start
+	int packageModifiers = this.intStack[this.intPtr--];
+
+	impt = new ImportReference(tokens, positions, true, packageModifiers);
+	this.compilationUnit.currentPackage = impt; 
+	// consume annotations
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			impt.annotations = new Annotation[length], 
+			0, 
+			length);
+		impt.declarationSourceStart = packageModifiersSourceStart;
+		intPtr--; // we don't need the position of the 'package keyword
+	} else {
+		impt.declarationSourceStart = this.intStack[this.intPtr--];
+	}
+		
+	if (this.currentToken == TokenNameSEMICOLON){
+		impt.declarationSourceEnd = this.scanner.currentPosition - 1;
+	} else {
+		impt.declarationSourceEnd = impt.sourceEnd;
+	}
+	impt.declarationEnd = impt.declarationSourceEnd;
+
+	// recovery
+	if (this.currentElement != null){
+		this.lastCheckPoint = impt.declarationSourceEnd+1;
+		this.restartRecovery = true; // used to avoid branching back into the regular automaton		
+	}	
+}
 protected void consumePostfixExpression() {
 	// PostfixExpression ::= Name
 	pushOnExpressionStack(getUnspecifiedReferenceOptimized());
@@ -2523,54 +4323,108 @@
 	parenthesizedExpression.bits |= (numberOfParenthesis + 1) << ASTNode.ParenthesizedSHIFT;
 }
 protected void consumePrimaryNoNewArrayArrayType() {
-	// PrimaryNoNewArray ::= ArrayType '.' 'class'
-	this.intPtr--;
+	// PrimaryNoNewArray ::= Name Dims '.' 'class'
+	this.intPtr--; // remove the class start position
+
+	pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+	pushOnGenericsLengthStack(0);
+
 	pushOnExpressionStack(
-		new ClassLiteralAccess(this.intStack[this.intPtr--],
-		getTypeReference(this.intStack[this.intPtr--])));
+		new ClassLiteralAccess(this.intStack[this.intPtr--], getTypeReference(this.intStack[this.intPtr--])));
 }
 protected void consumePrimaryNoNewArrayName() {
 	// PrimaryNoNewArray ::= Name '.' 'class'
-	this.intPtr--;
+	this.intPtr--; // remove the class start position
+
+	// handle type arguments
+	pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+	pushOnGenericsLengthStack(0);
+	TypeReference typeReference = getTypeReference(0);
+	
 	pushOnExpressionStack(
-		new ClassLiteralAccess(this.intStack[this.intPtr--],
-		getTypeReference(0)));
+		new ClassLiteralAccess(this.intStack[this.intPtr--], typeReference));
 }
 protected void consumePrimaryNoNewArrayNameSuper() {
 	// PrimaryNoNewArray ::= Name '.' 'super'
+	// handle type arguments
+	pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+	pushOnGenericsLengthStack(0);
+	TypeReference typeReference = getTypeReference(0);
+
 	pushOnExpressionStack(
 		new QualifiedSuperReference(
-			getTypeReference(0),
+			typeReference,
 			this.intStack[this.intPtr--],
 			this.endPosition));
 }
 protected void consumePrimaryNoNewArrayNameThis() {
 	// PrimaryNoNewArray ::= Name '.' 'this'
+	// handle type arguments
+	pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+	pushOnGenericsLengthStack(0); // handle type arguments
+
+	TypeReference typeReference = getTypeReference(0);
+	
 	pushOnExpressionStack(
 		new QualifiedThisReference(
-			getTypeReference(0),
+			typeReference,
 			this.intStack[this.intPtr--],
 			this.endPosition));
 }
+protected void consumePrimaryNoNewArrayPrimitiveArrayType() {
+	// PrimaryNoNewArray ::= PrimitiveType Dims '.' 'class'
+	this.intPtr--; // remove the class start position
+	pushOnExpressionStack(
+		new ClassLiteralAccess(this.intStack[this.intPtr--], getTypeReference(this.intStack[this.intPtr--])));
+}
 protected void consumePrimaryNoNewArrayPrimitiveType() {
 	// PrimaryNoNewArray ::= PrimitiveType '.' 'class'
-	this.intPtr--;
+	this.intPtr--; // remove the class start position
 	pushOnExpressionStack(
-		new ClassLiteralAccess(this.intStack[this.intPtr--],
-		getTypeReference(0)));
+		new ClassLiteralAccess(this.intStack[this.intPtr--], getTypeReference(0)));
 }
 protected void consumePrimaryNoNewArrayThis() {
 	// PrimaryNoNewArray ::= 'this'
 	pushOnExpressionStack(new ThisReference(this.intStack[this.intPtr--], this.endPosition));
 }
+protected void consumePrimaryNoNewArrayWithName() {
+	// PrimaryNoNewArray ::=  PushLPAREN Expression PushRPAREN 
+	pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+	final Expression parenthesizedExpression = this.expressionStack[this.expressionPtr];
+	updateSourcePosition(parenthesizedExpression);
+	int numberOfParenthesis = (parenthesizedExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+	parenthesizedExpression.bits &= ~ASTNode.ParenthesizedMASK;
+	parenthesizedExpression.bits |= (numberOfParenthesis + 1) << ASTNode.ParenthesizedSHIFT;
+}
+protected void consumePrimitiveArrayType() {
+	// nothing to do
+	// Will be consume by a getTypeRefence call
+}
 protected void consumePrimitiveType() {
 	// Type ::= PrimitiveType
 	pushOnIntStack(0);
 }
+protected void consumePushLeftBrace() {
+	pushOnIntStack(this.endPosition); // modifiers
+}
+protected void consumePushRealModifiers() {
+	checkComment(); // might update modifiers with AccDeprecated
+	pushOnIntStack(this.modifiers); // modifiers
+	pushOnIntStack(this.modifiersSourceStart);
+	resetModifiers();
+}
 protected void consumePushModifiers() {
 	pushOnIntStack(this.modifiers); // modifiers
 	pushOnIntStack(this.modifiersSourceStart);
 	resetModifiers();
+	pushOnExpressionStackLengthStack(0);
+}
+protected void consumePushModifiersForHeader() {
+	checkComment(); // might update modifiers with AccDeprecated
+	pushOnIntStack(this.modifiers); // modifiers
+	pushOnIntStack(this.modifiersSourceStart);
+	resetModifiers();
+	pushOnExpressionStackLengthStack(0);
 }
 protected void consumePushPosition() {
 	// for source managment purpose
@@ -2584,9 +4438,56 @@
 
 	this.identifierLengthStack[--this.identifierLengthPtr]++;
 }
+protected void consumeRecoveryMethodHeaderName() {
+	// this method is call only inside recovery
+	boolean isAnnotationMethod = false;
+	if(this.currentElement instanceof RecoveredType) {
+		isAnnotationMethod = (((RecoveredType)this.currentElement).typeDeclaration.modifiers & AccAnnotation) != 0;
+	} else {
+		RecoveredType recoveredType = this.currentElement.enclosingType();
+		if(recoveredType != null) {
+			isAnnotationMethod = (recoveredType.typeDeclaration.modifiers & AccAnnotation) != 0;
+		}
+	}
+	this.consumeMethodHeaderName(isAnnotationMethod);
+}
+protected void consumeRecoveryMethodHeaderNameWithTypeParameters() {
+	// this method is call only inside recovery
+	boolean isAnnotationMethod = false;
+	if(this.currentElement instanceof RecoveredType) {
+		isAnnotationMethod = (((RecoveredType)this.currentElement).typeDeclaration.modifiers & AccAnnotation) != 0;
+	} else {
+		RecoveredType recoveredType = this.currentElement.enclosingType();
+		if(recoveredType != null) {
+			isAnnotationMethod = (recoveredType.typeDeclaration.modifiers & AccAnnotation) != 0;
+		}
+	}
+	this.consumeMethodHeaderNameWithTypeParameters(isAnnotationMethod);
+}
+protected void consumeReduceImports() {
+	// Consume imports
+	int length;
+	if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+		this.astPtr -= length;
+		System.arraycopy(
+			this.astStack,
+			this.astPtr + 1,
+			this.compilationUnit.imports = new ImportReference[length],
+			0,
+			length);
+	}
+}
 protected void consumeReferenceType() {
-	// ReferenceType ::= ClassOrInterfaceType
-	pushOnIntStack(0);
+	pushOnIntStack(0); // handle array type
+}
+protected void consumeReferenceType1() {
+	pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--]));	
+}
+protected void consumeReferenceType2() {
+	pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--]));	
+}
+protected void consumeReferenceType3() {
+	pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--]));	
 }
 protected void consumeRestoreDiet() {
 	// RestoreDiet ::= $empty
@@ -2598,895 +4499,1629 @@
 }
 // This method is part of an automatic generation : do NOT edit-modify  
 protected void consumeRule(int act) {
-	switch ( act ) {
-	case 26 : // System.out.println("Type ::= PrimitiveType");  //$NON-NLS-1$
-		consumePrimitiveType();  
-		break ;
-		
-	case 40 : // System.out.println("ReferenceType ::= ClassOrInterfaceType");  //$NON-NLS-1$
-		consumeReferenceType();   
-		break ;
-		
-	case 49 : // System.out.println("QualifiedName ::= Name DOT SimpleName");  //$NON-NLS-1$
-		consumeQualifiedName();  
-		break ;
-		
-	case 50 : // System.out.println("CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt...");  //$NON-NLS-1$
-		consumeCompilationUnit();  
-		break ;
-		
-	case 51 : // System.out.println("EnterCompilationUnit ::=");  //$NON-NLS-1$
-		consumeEnterCompilationUnit();  
-		break ;
-		
-	case 64 : // System.out.println("CatchHeader ::= catch LPAREN FormalParameter RPAREN LBRACE");  //$NON-NLS-1$
-		consumeCatchHeader();  
-		break ;
-		
-	case 66 : // System.out.println("ImportDeclarations ::= ImportDeclarations ImportDeclaration");  //$NON-NLS-1$
-		consumeImportDeclarations();  
-		break ;
-		
-	case 68 : // System.out.println("TypeDeclarations ::= TypeDeclarations TypeDeclaration");  //$NON-NLS-1$
-		consumeTypeDeclarations();  
-		break ;
-		
-	case 69 : // System.out.println("PackageDeclaration ::= PackageDeclarationName SEMICOLON");  //$NON-NLS-1$
-		consumePackageDeclaration();  
-		break ;
-		
-	case 70 : // System.out.println("PackageDeclarationName ::= package Name");  //$NON-NLS-1$
-		consumePackageDeclarationName();  
-		break ;
-		
-	case 73 : // System.out.println("SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName...");  //$NON-NLS-1$
-		consumeSingleTypeImportDeclaration();  
-		break ;
-		
-	case 74 : // System.out.println("SingleTypeImportDeclarationName ::= import Name");  //$NON-NLS-1$
-		consumeSingleTypeImportDeclarationName();  
-		break ;
-		
-	case 75 : // System.out.println("TypeImportOnDemandDeclaration ::= TypeImportOnDemandDeclarationName");  //$NON-NLS-1$
-		consumeTypeImportOnDemandDeclaration();  
-		break ;
-		
-	case 76 : // System.out.println("TypeImportOnDemandDeclarationName ::= import Name DOT MULTIPLY");  //$NON-NLS-1$
-		consumeTypeImportOnDemandDeclarationName();  
-		break ;
-		
-	case 79 : // System.out.println("TypeDeclaration ::= SEMICOLON");  //$NON-NLS-1$
-		consumeEmptyTypeDeclaration();  
-		break ;
-		
-	case 93 : // System.out.println("ClassDeclaration ::= ClassHeader ClassBody");  //$NON-NLS-1$
-		consumeClassDeclaration();  
-		break ;
-		
-	case 94 : // System.out.println("ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt...");  //$NON-NLS-1$
-		consumeClassHeader();  
-		break ;
-		
-	case 95 : // System.out.println("ClassHeaderName ::= Modifiersopt class Identifier");  //$NON-NLS-1$
-		consumeClassHeaderName();  
-		break ;
-		
-	case 96 : // System.out.println("ClassHeaderExtends ::= extends ClassType");  //$NON-NLS-1$
-		consumeClassHeaderExtends();  
-		break ;
-		
-	case 97 : // System.out.println("ClassHeaderImplements ::= implements InterfaceTypeList");  //$NON-NLS-1$
-		consumeClassHeaderImplements();  
-		break ;
-		
-	case 99 : // System.out.println("InterfaceTypeList ::= InterfaceTypeList COMMA InterfaceType");  //$NON-NLS-1$
-		consumeInterfaceTypeList();  
-		break ;
-		
-	case 100 : // System.out.println("InterfaceType ::= ClassOrInterfaceType");  //$NON-NLS-1$
-		consumeInterfaceType();  
-		break ;
-		
-	case 103 : // System.out.println("ClassBodyDeclarations ::= ClassBodyDeclarations ClassBodyDeclaration");  //$NON-NLS-1$
-		consumeClassBodyDeclarations();  
-		break ;
-		
-	case 107 : // System.out.println("ClassBodyDeclaration ::= Diet NestedMethod Block");  //$NON-NLS-1$
-		consumeClassBodyDeclaration();  
-		break ;
-		
-	case 108 : // System.out.println("Diet ::=");  //$NON-NLS-1$
-		consumeDiet();  
-		break ;
+  switch ( act ) {
+    case 29 : if (DEBUG) { System.out.println("Type ::= PrimitiveType"); }  //$NON-NLS-1$
+		    consumePrimitiveType();  
+			break;
+ 
+    case 43 : if (DEBUG) { System.out.println("ReferenceType ::= ClassOrInterfaceType"); }  //$NON-NLS-1$
+		    consumeReferenceType();   
+			break;
+ 
+    case 47 : if (DEBUG) { System.out.println("ClassOrInterface ::= Name"); }  //$NON-NLS-1$
+		    consumeClassOrInterfaceName();   
+			break;
+ 
+    case 48 : if (DEBUG) { System.out.println("ClassOrInterface ::= GenericType DOT Name"); }  //$NON-NLS-1$
+		    consumeClassOrInterface();   
+			break;
+ 
+    case 49 : if (DEBUG) { System.out.println("GenericType ::= ClassOrInterface TypeArguments"); }  //$NON-NLS-1$
+		    consumeGenericType();   
+			break;
+ 
+    case 50 : if (DEBUG) { System.out.println("ArrayTypeWithTypeArgumentsName ::= GenericType DOT Name"); }  //$NON-NLS-1$
+		    consumeArrayTypeWithTypeArgumentsName();   
+			break;
+ 
+    case 51 : if (DEBUG) { System.out.println("ArrayType ::= PrimitiveType Dims"); }  //$NON-NLS-1$
+		    consumePrimitiveArrayType();   
+			break;
+ 
+    case 52 : if (DEBUG) { System.out.println("ArrayType ::= Name Dims"); }  //$NON-NLS-1$
+		    consumeNameArrayType();   
+			break;
+ 
+    case 53 : if (DEBUG) { System.out.println("ArrayType ::= ArrayTypeWithTypeArgumentsName Dims"); }  //$NON-NLS-1$
+		    consumeGenericTypeNameArrayType();   
+			break;
+ 
+    case 54 : if (DEBUG) { System.out.println("ArrayType ::= GenericType Dims"); }  //$NON-NLS-1$
+		    consumeGenericTypeArrayType();   
+			break;
+ 
+    case 59 : if (DEBUG) { System.out.println("QualifiedName ::= Name DOT SimpleName"); }  //$NON-NLS-1$
+		    consumeQualifiedName();  
+			break;
+ 
+    case 60 : if (DEBUG) { System.out.println("CompilationUnit ::= EnterCompilationUnit..."); }  //$NON-NLS-1$
+		    consumeCompilationUnit();  
+			break;
+ 
+    case 61 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= PackageDeclaration"); }  //$NON-NLS-1$
+		    consumeInternalCompilationUnit();  
+			break;
+ 
+    case 62 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= PackageDeclaration..."); }  //$NON-NLS-1$
+		    consumeInternalCompilationUnit();  
+			break;
+ 
+    case 63 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= PackageDeclaration..."); }  //$NON-NLS-1$
+		    consumeInternalCompilationUnitWithTypes();  
+			break;
+ 
+    case 64 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= PackageDeclaration..."); }  //$NON-NLS-1$
+		    consumeInternalCompilationUnitWithTypes();  
+			break;
+ 
+    case 65 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= ImportDeclarations..."); }  //$NON-NLS-1$
+		    consumeInternalCompilationUnit();  
+			break;
+ 
+    case 66 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= TypeDeclarations"); }  //$NON-NLS-1$
+		    consumeInternalCompilationUnitWithTypes();  
+			break;
+ 
+    case 67 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= ImportDeclarations..."); }  //$NON-NLS-1$
+		    consumeInternalCompilationUnitWithTypes();  
+			break;
+ 
+    case 68 : if (DEBUG) { System.out.println("InternalCompilationUnit ::="); }  //$NON-NLS-1$
+		    consumeEmptyInternalCompilationUnit();  
+			break;
+ 
+    case 69 : if (DEBUG) { System.out.println("ReduceImports ::="); }  //$NON-NLS-1$
+		    consumeReduceImports();  
+			break;
+ 
+    case 70 : if (DEBUG) { System.out.println("EnterCompilationUnit ::="); }  //$NON-NLS-1$
+		    consumeEnterCompilationUnit();  
+			break;
+ 
+    case 86 : if (DEBUG) { System.out.println("CatchHeader ::= catch LPAREN FormalParameter RPAREN..."); }  //$NON-NLS-1$
+		    consumeCatchHeader();  
+			break;
+ 
+    case 88 : if (DEBUG) { System.out.println("ImportDeclarations ::= ImportDeclarations..."); }  //$NON-NLS-1$
+		    consumeImportDeclarations();  
+			break;
+ 
+    case 90 : if (DEBUG) { System.out.println("TypeDeclarations ::= TypeDeclarations TypeDeclaration"); }  //$NON-NLS-1$
+		    consumeTypeDeclarations();  
+			break;
+ 
+    case 91 : if (DEBUG) { System.out.println("PackageDeclaration ::= PackageDeclarationName SEMICOLON"); }  //$NON-NLS-1$
+		     consumePackageDeclaration();  
+			break;
+ 
+    case 92 : if (DEBUG) { System.out.println("PackageDeclarationName ::= Modifiers package..."); }  //$NON-NLS-1$
+		     consumePackageDeclarationNameWithModifiers();  
+			break;
+ 
+    case 93 : if (DEBUG) { System.out.println("PackageDeclarationName ::= package Name"); }  //$NON-NLS-1$
+		     consumePackageDeclarationName();  
+			break;
+ 
+    case 98 : if (DEBUG) { System.out.println("SingleTypeImportDeclaration ::=..."); }  //$NON-NLS-1$
+		    consumeImportDeclaration();  
+			break;
+ 
+    case 99 : if (DEBUG) { System.out.println("SingleTypeImportDeclarationName ::= import Name"); }  //$NON-NLS-1$
+		    consumeSingleTypeImportDeclarationName();  
+			break;
+ 
+    case 100 : if (DEBUG) { System.out.println("TypeImportOnDemandDeclaration ::=..."); }  //$NON-NLS-1$
+		    consumeImportDeclaration();  
+			break;
+ 
+    case 101 : if (DEBUG) { System.out.println("TypeImportOnDemandDeclarationName ::= import Name DOT..."); }  //$NON-NLS-1$
+		    consumeTypeImportOnDemandDeclarationName();  
+			break;
+ 
+     case 104 : if (DEBUG) { System.out.println("TypeDeclaration ::= SEMICOLON"); }  //$NON-NLS-1$
+		    consumeEmptyTypeDeclaration();  
+			break;
+ 
+    case 108 : if (DEBUG) { System.out.println("Modifiers ::= Modifiers Modifier"); }  //$NON-NLS-1$
+		    consumeModifiers2();  
+			break;
+ 
+    case 120 : if (DEBUG) { System.out.println("Modifier ::= Annotation"); }  //$NON-NLS-1$
+		    consumeAnnotationAsModifier();  
+			break;
+ 
+    case 121 : if (DEBUG) { System.out.println("ClassDeclaration ::= ClassHeader ClassBody"); }  //$NON-NLS-1$
+		    consumeClassDeclaration();  
+			break;
+ 
+    case 122 : if (DEBUG) { System.out.println("ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt..."); }  //$NON-NLS-1$
+		    consumeClassHeader();  
+			break;
+ 
+    case 123 : if (DEBUG) { System.out.println("ClassHeaderName ::= ClassHeaderName1 TypeParameters"); }  //$NON-NLS-1$
+		    consumeTypeHeaderNameWithTypeParameters();  
+			break;
+ 
+    case 125 : if (DEBUG) { System.out.println("ClassHeaderName1 ::= Modifiersopt class Identifier"); }  //$NON-NLS-1$
+		    consumeClassHeaderName1();  
+			break;
+ 
+    case 126 : if (DEBUG) { System.out.println("ClassHeaderExtends ::= extends ClassType"); }  //$NON-NLS-1$
+		    consumeClassHeaderExtends();  
+			break;
+ 
+    case 127 : if (DEBUG) { System.out.println("ClassHeaderImplements ::= implements InterfaceTypeList"); }  //$NON-NLS-1$
+		    consumeClassHeaderImplements();  
+			break;
+ 
+    case 129 : if (DEBUG) { System.out.println("InterfaceTypeList ::= InterfaceTypeList COMMA..."); }  //$NON-NLS-1$
+		    consumeInterfaceTypeList();  
+			break;
+ 
+    case 130 : if (DEBUG) { System.out.println("InterfaceType ::= ClassOrInterfaceType"); }  //$NON-NLS-1$
+		    consumeInterfaceType();  
+			break;
+ 
+    case 133 : if (DEBUG) { System.out.println("ClassBodyDeclarations ::= ClassBodyDeclarations..."); }  //$NON-NLS-1$
+		    consumeClassBodyDeclarations();  
+			break;
+ 
+    case 137 : if (DEBUG) { System.out.println("ClassBodyDeclaration ::= Diet NestedMethod Block"); }  //$NON-NLS-1$
+		    consumeClassBodyDeclaration();  
+			break;
+ 
+    case 138 : if (DEBUG) { System.out.println("Diet ::="); }  //$NON-NLS-1$
+		    consumeDiet();  
+			break;
 
-	case 109 : // System.out.println("Initializer ::= Diet NestedMethod Block");  //$NON-NLS-1$
-		consumeClassBodyDeclaration();  
-		break ;
-		
-	case 116 : // System.out.println("ClassMemberDeclaration ::= SEMICOLON");  //$NON-NLS-1$
-		consumeEmptyClassMemberDeclaration();  
-		break ;
+    case 139 : if (DEBUG) { System.out.println("Initializer ::= Diet NestedMethod Block"); }  //$NON-NLS-1$
+		    consumeClassBodyDeclaration();  
+			break;
+ 
+    case 146 : if (DEBUG) { System.out.println("ClassMemberDeclaration ::= SEMICOLON"); }  //$NON-NLS-1$
+		    consumeEmptyClassMemberDeclaration();  
+			break;
 
-	case 117 : // System.out.println("FieldDeclaration ::= Modifiersopt Type VariableDeclarators SEMICOLON");  //$NON-NLS-1$
-		consumeFieldDeclaration();  
-		break ;
-		
-	case 119 : // System.out.println("VariableDeclarators ::= VariableDeclarators COMMA VariableDeclarator");  //$NON-NLS-1$
-		consumeVariableDeclarators();  
-		break ;
-		
-	case 122 : // System.out.println("EnterVariable ::=");  //$NON-NLS-1$
-		consumeEnterVariable();  
-		break ;
-		
-	case 123 : // System.out.println("ExitVariableWithInitialization ::=");  //$NON-NLS-1$
-		consumeExitVariableWithInitialization();  
-		break ;
-		
-	case 124 : // System.out.println("ExitVariableWithoutInitialization ::=");  //$NON-NLS-1$
-		consumeExitVariableWithoutInitialization();  
-		break ;
-		
-	case 125 : // System.out.println("ForceNoDiet ::=");  //$NON-NLS-1$
-		consumeForceNoDiet();  
-		break ;
-		
-	case 126 : // System.out.println("RestoreDiet ::=");  //$NON-NLS-1$
-		consumeRestoreDiet();  
-		break ;
-		
-	case 131 : // System.out.println("MethodDeclaration ::= MethodHeader MethodBody");  //$NON-NLS-1$
-		// set to true to consume a method with a body
-		consumeMethodDeclaration(true);   
-		break ;
-		
-	case 132 : // System.out.println("AbstractMethodDeclaration ::= MethodHeader SEMICOLON");  //$NON-NLS-1$
-		// set to false to consume a method without body
-		consumeMethodDeclaration(false);  
-		break ;
-		
-	case 133 : // System.out.println("MethodHeader ::= MethodHeaderName MethodHeaderParameters...");  //$NON-NLS-1$
-		consumeMethodHeader();  
-		break ;
-		
-	case 134 : // System.out.println("MethodHeaderName ::= Modifiersopt Type Identifier LPAREN");  //$NON-NLS-1$
-		consumeMethodHeaderName();  
-		break ;
-		
-	case 135 : // System.out.println("MethodHeaderParameters ::= FormalParameterListopt RPAREN");  //$NON-NLS-1$
-		consumeMethodHeaderParameters();  
-		break ;
-		
-	case 136 : // System.out.println("MethodHeaderExtendedDims ::= Dimsopt");  //$NON-NLS-1$
-		consumeMethodHeaderExtendedDims();  
-		break ;
-		
-	case 137 : // System.out.println("MethodHeaderThrowsClause ::= throws ClassTypeList");  //$NON-NLS-1$
-		consumeMethodHeaderThrowsClause();  
-		break ;
-		
-	case 138 : // System.out.println("ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters");  //$NON-NLS-1$
-		consumeConstructorHeader();  
-		break ;
-		
-	case 139 : // System.out.println("ConstructorHeaderName ::= Modifiersopt Identifier LPAREN");  //$NON-NLS-1$
-		consumeConstructorHeaderName();  
-		break ;
-		
-	case 141 : // System.out.println("FormalParameterList ::= FormalParameterList COMMA FormalParameter");  //$NON-NLS-1$
-		consumeFormalParameterList();  
-		break ;
-		
-	case 142 : // System.out.println("FormalParameter ::= Modifiersopt Type VariableDeclaratorId");  //$NON-NLS-1$
-		// the boolean is used to know if the modifiers should be reset
-		consumeFormalParameter();  
-		break ;
-		
-	case 144 : // System.out.println("ClassTypeList ::= ClassTypeList COMMA ClassTypeElt");  //$NON-NLS-1$
-		consumeClassTypeList();  
-		break ;
-		
-	case 145 : // System.out.println("ClassTypeElt ::= ClassType");  //$NON-NLS-1$
-		consumeClassTypeElt();  
-		break ;
-		
-	case 146 : // System.out.println("MethodBody ::= NestedMethod LBRACE BlockStatementsopt RBRACE");  //$NON-NLS-1$
-		consumeMethodBody();  
-		break ;
-		
-	case 147 : // System.out.println("NestedMethod ::=");  //$NON-NLS-1$
-		consumeNestedMethod();  
-		break ;
-		
-	case 148 : // System.out.println("StaticInitializer ::= StaticOnly Block");  //$NON-NLS-1$
-		consumeStaticInitializer();  
-		break ;
+    case 149 : if (DEBUG) { System.out.println("FieldDeclaration ::= Modifiersopt Type..."); }  //$NON-NLS-1$
+		    consumeFieldDeclaration();  
+			break;
+ 
+    case 151 : if (DEBUG) { System.out.println("VariableDeclarators ::= VariableDeclarators COMMA..."); }  //$NON-NLS-1$
+		    consumeVariableDeclarators();  
+			break;
+ 
+    case 154 : if (DEBUG) { System.out.println("EnterVariable ::="); }  //$NON-NLS-1$
+		    consumeEnterVariable();  
+			break;
+ 
+    case 155 : if (DEBUG) { System.out.println("ExitVariableWithInitialization ::="); }  //$NON-NLS-1$
+		    consumeExitVariableWithInitialization();  
+			break;
+ 
+    case 156 : if (DEBUG) { System.out.println("ExitVariableWithoutInitialization ::="); }  //$NON-NLS-1$
+		    consumeExitVariableWithoutInitialization();  
+			break;
+ 
+    case 157 : if (DEBUG) { System.out.println("ForceNoDiet ::="); }  //$NON-NLS-1$
+		    consumeForceNoDiet();  
+			break;
+ 
+    case 158 : if (DEBUG) { System.out.println("RestoreDiet ::="); }  //$NON-NLS-1$
+		    consumeRestoreDiet();  
+			break;
+ 
+    case 163 : if (DEBUG) { System.out.println("MethodDeclaration ::= MethodHeader MethodBody"); }  //$NON-NLS-1$
+		    // set to true to consume a method with a body
+  consumeMethodDeclaration(true);   
+			break;
+ 
+    case 164 : if (DEBUG) { System.out.println("AbstractMethodDeclaration ::= MethodHeader SEMICOLON"); }  //$NON-NLS-1$
+		    // set to false to consume a method without body
+  consumeMethodDeclaration(false);  
+			break;
+ 
+    case 165 : if (DEBUG) { System.out.println("MethodHeader ::= MethodHeaderName FormalParameterListopt"); }  //$NON-NLS-1$
+		    consumeMethodHeader();  
+			break;
+ 
+    case 166 : if (DEBUG) { System.out.println("MethodHeaderName ::= Modifiersopt TypeParameters Type..."); }  //$NON-NLS-1$
+		    consumeMethodHeaderNameWithTypeParameters(false);  
+			break;
+ 
+    case 167 : if (DEBUG) { System.out.println("MethodHeaderName ::= Modifiersopt Type Identifier LPAREN"); }  //$NON-NLS-1$
+		    consumeMethodHeaderName(false);  
+			break;
+ 
+    case 168 : if (DEBUG) { System.out.println("MethodHeaderRightParen ::= RPAREN"); }  //$NON-NLS-1$
+		    consumeMethodHeaderRightParen();  
+			break;
+ 
+    case 169 : if (DEBUG) { System.out.println("MethodHeaderExtendedDims ::= Dimsopt"); }  //$NON-NLS-1$
+		    consumeMethodHeaderExtendedDims();  
+			break;
+ 
+    case 170 : if (DEBUG) { System.out.println("MethodHeaderThrowsClause ::= throws ClassTypeList"); }  //$NON-NLS-1$
+		    consumeMethodHeaderThrowsClause();  
+			break;
+ 
+    case 171 : if (DEBUG) { System.out.println("ConstructorHeader ::= ConstructorHeaderName..."); }  //$NON-NLS-1$
+		    consumeConstructorHeader();  
+			break;
+ 
+    case 172 : if (DEBUG) { System.out.println("ConstructorHeaderName ::= Modifiersopt TypeParameters..."); }  //$NON-NLS-1$
+		    consumeConstructorHeaderNameWithTypeParameters();  
+			break;
+ 
+    case 173 : if (DEBUG) { System.out.println("ConstructorHeaderName ::= Modifiersopt Identifier LPAREN"); }  //$NON-NLS-1$
+		    consumeConstructorHeaderName();  
+			break;
+ 
+    case 175 : if (DEBUG) { System.out.println("FormalParameterList ::= FormalParameterList COMMA..."); }  //$NON-NLS-1$
+		    consumeFormalParameterList();  
+			break;
+ 
+    case 176 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type..."); }  //$NON-NLS-1$
+		    consumeFormalParameter(false);  
+			break;
+ 
+    case 177 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type ELLIPSIS..."); }  //$NON-NLS-1$
+		    consumeFormalParameter(true);  
+			break;
+ 
+    case 179 : if (DEBUG) { System.out.println("ClassTypeList ::= ClassTypeList COMMA ClassTypeElt"); }  //$NON-NLS-1$
+		    consumeClassTypeList();  
+			break;
+ 
+    case 180 : if (DEBUG) { System.out.println("ClassTypeElt ::= ClassType"); }  //$NON-NLS-1$
+		    consumeClassTypeElt();  
+			break;
+ 
+    case 181 : if (DEBUG) { System.out.println("MethodBody ::= NestedMethod LBRACE BlockStatementsopt..."); }  //$NON-NLS-1$
+		    consumeMethodBody();  
+			break;
+ 
+    case 182 : if (DEBUG) { System.out.println("NestedMethod ::="); }  //$NON-NLS-1$
+		    consumeNestedMethod();  
+			break;
+ 
+    case 183 : if (DEBUG) { System.out.println("StaticInitializer ::= StaticOnly Block"); }  //$NON-NLS-1$
+		    consumeStaticInitializer();  
+			break;
 
-	case 149 : // System.out.println("StaticOnly ::= static");  //$NON-NLS-1$
-		consumeStaticOnly();  
-		break ;
-		
-	case 150 : // System.out.println("ConstructorDeclaration ::= ConstructorHeader MethodBody");  //$NON-NLS-1$
-		consumeConstructorDeclaration() ;  
-		break ;
-		
-	case 151 : // System.out.println("ConstructorDeclaration ::= ConstructorHeader SEMICOLON");  //$NON-NLS-1$
-		consumeInvalidConstructorDeclaration() ;  
-		break ;
-		
-	case 152 : // System.out.println("ExplicitConstructorInvocation ::= this LPAREN ArgumentListopt RPAREN");  //$NON-NLS-1$
-		consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.This);  
-		break ;
-		
-	case 153 : // System.out.println("ExplicitConstructorInvocation ::= super LPAREN ArgumentListopt...");  //$NON-NLS-1$
-		consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.Super);  
-		break ;
-		
-	case 154 : // System.out.println("ExplicitConstructorInvocation ::= Primary DOT super LPAREN...");  //$NON-NLS-1$
-		consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.Super);  
-		break ;
-		
-	case 155 : // System.out.println("ExplicitConstructorInvocation ::= Name DOT super LPAREN...");  //$NON-NLS-1$
-		consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.Super);  
-		break ;
-		
-	case 156 : // System.out.println("ExplicitConstructorInvocation ::= Primary DOT this LPAREN...");  //$NON-NLS-1$
-		consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.This);  
-		break ;
-		
-	case 157 : // System.out.println("ExplicitConstructorInvocation ::= Name DOT this LPAREN...");  //$NON-NLS-1$
-		consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.This);  
-		break ;
-		
-	case 158 : // System.out.println("InterfaceDeclaration ::= InterfaceHeader InterfaceBody");  //$NON-NLS-1$
-		consumeInterfaceDeclaration();  
-		break ;
-		
-	case 159 : // System.out.println("InterfaceHeader ::= InterfaceHeaderName InterfaceHeaderExtendsopt");  //$NON-NLS-1$
-		consumeInterfaceHeader();  
-		break ;
-		
-	case 160 : // System.out.println("InterfaceHeaderName ::= Modifiersopt interface Identifier");  //$NON-NLS-1$
-		consumeInterfaceHeaderName();  
-		break ;
-		
-	case 162 : // System.out.println("InterfaceHeaderExtends ::= extends InterfaceTypeList");  //$NON-NLS-1$
-		consumeInterfaceHeaderExtends();  
-		break ;
-		
-	case 165 : // System.out.println("InterfaceMemberDeclarations ::= InterfaceMemberDeclarations...");  //$NON-NLS-1$
-		consumeInterfaceMemberDeclarations();  
-		break ;
-		
-	case 166 : // System.out.println("InterfaceMemberDeclaration ::= SEMICOLON");  //$NON-NLS-1$
-		consumeEmptyInterfaceMemberDeclaration();  
-		break ;
-		
-	case 169 : // System.out.println("InterfaceMemberDeclaration ::= InvalidMethodDeclaration");  //$NON-NLS-1$
-		ignoreMethodBody();  
-		break ;
-		
-	case 170 : // System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader MethodBody");  //$NON-NLS-1$
-		ignoreInvalidConstructorDeclaration(true);   
-		break ;
-		
-	case 171 : // System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader SEMICOLON");  //$NON-NLS-1$
-		ignoreInvalidConstructorDeclaration(false);   
-		break ;
-		
-	case 177 : // System.out.println("ArrayInitializer ::= LBRACE ,opt RBRACE");  //$NON-NLS-1$
-		consumeEmptyArrayInitializer();  
-		break ;
-		
-	case 178 : // System.out.println("ArrayInitializer ::= LBRACE VariableInitializers RBRACE");  //$NON-NLS-1$
-		consumeArrayInitializer();  
-		break ;
-		
-	case 179 : // System.out.println("ArrayInitializer ::= LBRACE VariableInitializers COMMA RBRACE");  //$NON-NLS-1$
-		consumeArrayInitializer();  
-		break ;
-		
-	case 181 : // System.out.println("VariableInitializers ::= VariableInitializers COMMA...");  //$NON-NLS-1$
-		consumeVariableInitializers();  
-		break ;
-		
-	case 182 : // System.out.println("Block ::= OpenBlock LBRACE BlockStatementsopt RBRACE");  //$NON-NLS-1$
-		consumeBlock();  
-		break ;
-		
-	case 183 : // System.out.println("OpenBlock ::=");  //$NON-NLS-1$
-		consumeOpenBlock() ;  
-		break ;
-		
-	case 185 : // System.out.println("BlockStatements ::= BlockStatements BlockStatement");  //$NON-NLS-1$
-		consumeBlockStatements() ;  
-		break ;
-		
-	case 189 : // System.out.println("BlockStatement ::= InvalidInterfaceDeclaration");  //$NON-NLS-1$
-		ignoreInterfaceDeclaration();  
-		break ;
-		
-	case 190 : // System.out.println("LocalVariableDeclarationStatement ::= LocalVariableDeclaration...");  //$NON-NLS-1$
-		consumeLocalVariableDeclarationStatement();  
-		break ;
-		
-	case 191 : // System.out.println("LocalVariableDeclaration ::= Type PushModifiers VariableDeclarators");  //$NON-NLS-1$
-		consumeLocalVariableDeclaration();  
-		break ;
-		
-	case 192 : // System.out.println("LocalVariableDeclaration ::= Modifiers Type PushModifiers...");  //$NON-NLS-1$
-		consumeLocalVariableDeclaration();  
-		break ;
-		
-	case 193 : // System.out.println("PushModifiers ::=");  //$NON-NLS-1$
-		consumePushModifiers();  
-		break ;
-		
-	case 217 : // System.out.println("EmptyStatement ::= SEMICOLON");  //$NON-NLS-1$
-		consumeEmptyStatement();  
-		break ;
-		
-	case 218 : // System.out.println("LabeledStatement ::= Identifier COLON Statement");  //$NON-NLS-1$
-		consumeStatementLabel() ;  
-		break ;
-		
-	case 219 : // System.out.println("LabeledStatementNoShortIf ::= Identifier COLON StatementNoShortIf");  //$NON-NLS-1$
-		consumeStatementLabel() ;  
-		break ;
-		
-	case 220 : // System.out.println("ExpressionStatement ::= StatementExpression SEMICOLON");  //$NON-NLS-1$
-		consumeExpressionStatement();  
-		break ;
-		
-	case 229 : // System.out.println("IfThenStatement ::= if LPAREN Expression RPAREN Statement");  //$NON-NLS-1$
-		consumeStatementIfNoElse();  
-		break ;
-		
-	case 230 : // System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN...");  //$NON-NLS-1$
-		consumeStatementIfWithElse();  
-		break ;
-		
-	case 231 : // System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression RPAREN...");  //$NON-NLS-1$
-		consumeStatementIfWithElse();  
-		break ;
-		
-	case 232 : // System.out.println("SwitchStatement ::= switch LPAREN Expression RPAREN OpenBlock...");  //$NON-NLS-1$
-		consumeStatementSwitch() ;  
-		break ;
-		
-	case 233 : // System.out.println("SwitchBlock ::= LBRACE RBRACE");  //$NON-NLS-1$
-		consumeEmptySwitchBlock() ;  
-		break ;
-		
-	case 236 : // System.out.println("SwitchBlock ::= LBRACE SwitchBlockStatements SwitchLabels RBRACE");  //$NON-NLS-1$
-		consumeSwitchBlock() ;  
-		break ;
-		
-	case 238 : // System.out.println("SwitchBlockStatements ::= SwitchBlockStatements SwitchBlockStatement");  //$NON-NLS-1$
-		consumeSwitchBlockStatements() ;  
-		break ;
-		
-	case 239 : // System.out.println("SwitchBlockStatement ::= SwitchLabels BlockStatements");  //$NON-NLS-1$
-		consumeSwitchBlockStatement() ;  
-		break ;
-		
-	case 241 : // System.out.println("SwitchLabels ::= SwitchLabels SwitchLabel");  //$NON-NLS-1$
-		consumeSwitchLabels() ;  
-		break ;
-		
-	case 242 : // System.out.println("SwitchLabel ::= case ConstantExpression COLON");  //$NON-NLS-1$
-		consumeCaseLabel();  
-		break ;
-		
-	case 243 : // System.out.println("SwitchLabel ::= default COLON");  //$NON-NLS-1$
-		consumeDefaultLabel();  
-		break ;
-		
-	case 244 : // System.out.println("WhileStatement ::= while LPAREN Expression RPAREN Statement");  //$NON-NLS-1$
-		consumeStatementWhile() ;  
-		break ;
-		
-	case 245 : // System.out.println("WhileStatementNoShortIf ::= while LPAREN Expression RPAREN...");  //$NON-NLS-1$
-		consumeStatementWhile() ;  
-		break ;
-		
-	case 246 : // System.out.println("DoStatement ::= do Statement while LPAREN Expression RPAREN...");  //$NON-NLS-1$
-		consumeStatementDo() ;  
-		break ;
-		
-	case 247 : // System.out.println("ForStatement ::= for LPAREN ForInitopt SEMICOLON Expressionopt...");  //$NON-NLS-1$
-		consumeStatementFor() ;  
-		break ;
-		
-	case 248 : // System.out.println("ForStatementNoShortIf ::= for LPAREN ForInitopt SEMICOLON...");  //$NON-NLS-1$
-		consumeStatementFor() ;  
-		break ;
-		
-	case 249 : // System.out.println("ForInit ::= StatementExpressionList");  //$NON-NLS-1$
-		consumeForInit() ;  
-		break ;
-		
-	case 253 : // System.out.println("StatementExpressionList ::= StatementExpressionList COMMA...");  //$NON-NLS-1$
-		consumeStatementExpressionList() ;  
-		break ;
-		
-	case 254 : // System.out.println("AssertStatement ::= assert Expression SEMICOLON");  //$NON-NLS-1$
-		consumeSimpleAssertStatement() ;  
-		break ;
-		
-	case 255 : // System.out.println("AssertStatement ::= assert Expression COLON Expression SEMICOLON");  //$NON-NLS-1$
-		consumeAssertStatement() ;  
-		break ;
-		
-	case 256 : // System.out.println("BreakStatement ::= break SEMICOLON");  //$NON-NLS-1$
-		consumeStatementBreak() ;  
-		break ;
-		
-	case 257 : // System.out.println("BreakStatement ::= break Identifier SEMICOLON");  //$NON-NLS-1$
-		consumeStatementBreakWithLabel() ;  
-		break ;
-		
-	case 258 : // System.out.println("ContinueStatement ::= continue SEMICOLON");  //$NON-NLS-1$
-		consumeStatementContinue() ;  
-		break ;
-		
-	case 259 : // System.out.println("ContinueStatement ::= continue Identifier SEMICOLON");  //$NON-NLS-1$
-		consumeStatementContinueWithLabel() ;  
-		break ;
-		
-	case 260 : // System.out.println("ReturnStatement ::= return Expressionopt SEMICOLON");  //$NON-NLS-1$
-		consumeStatementReturn() ;  
-		break ;
-		
-	case 261 : // System.out.println("ThrowStatement ::= throw Expression SEMICOLON");  //$NON-NLS-1$
-		consumeStatementThrow();
-		
-		break ;
-		
-	case 262 : // System.out.println("SynchronizedStatement ::= OnlySynchronized LPAREN Expression RPAREN");  //$NON-NLS-1$
-		consumeStatementSynchronized();  
-		break ;
-		
-	case 263 : // System.out.println("OnlySynchronized ::= synchronized");  //$NON-NLS-1$
-		consumeOnlySynchronized();  
-		break ;
-		
-	case 264 : // System.out.println("TryStatement ::= try TryBlock Catches");  //$NON-NLS-1$
-		consumeStatementTry(false);  
-		break ;
-		
-	case 265 : // System.out.println("TryStatement ::= try TryBlock Catchesopt Finally");  //$NON-NLS-1$
-		consumeStatementTry(true);  
-		break ;
-		
-	case 267 : // System.out.println("ExitTryBlock ::=");  //$NON-NLS-1$
-		consumeExitTryBlock();  
-		break ;
-		
-	case 269 : // System.out.println("Catches ::= Catches CatchClause");  //$NON-NLS-1$
-		consumeCatches();  
-		break ;
-		
-	case 270 : // System.out.println("CatchClause ::= catch LPAREN FormalParameter RPAREN Block");  //$NON-NLS-1$
-		consumeStatementCatch() ;  
-		break ;
-		
-	case 272 : // System.out.println("PushLPAREN ::= LPAREN");  //$NON-NLS-1$
-		consumeLeftParen();  
-		break ;
-		
-	case 273 : // System.out.println("PushRPAREN ::= RPAREN");  //$NON-NLS-1$
-		consumeRightParen();  
-		break ;
-		
-	case 278 : // System.out.println("PrimaryNoNewArray ::= this");  //$NON-NLS-1$
-		consumePrimaryNoNewArrayThis();  
-		break ;
-		
-	case 279 : // System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression PushRPAREN");  //$NON-NLS-1$
-		consumePrimaryNoNewArray();  
-		break ;
-		
-	case 282 : // System.out.println("PrimaryNoNewArray ::= Name DOT this");  //$NON-NLS-1$
-		consumePrimaryNoNewArrayNameThis();  
-		break ;
-		
-	case 283 : // System.out.println("PrimaryNoNewArray ::= Name DOT super");  //$NON-NLS-1$
-		consumePrimaryNoNewArrayNameSuper();  
-		break ;
-		
-	case 284 : // System.out.println("PrimaryNoNewArray ::= Name DOT class");  //$NON-NLS-1$
-		consumePrimaryNoNewArrayName();  
-		break ;
-		
-	case 285 : // System.out.println("PrimaryNoNewArray ::= ArrayType DOT class");  //$NON-NLS-1$
-		consumePrimaryNoNewArrayArrayType();  
-		break ;
-		
-	case 286 : // System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class");  //$NON-NLS-1$
-		consumePrimaryNoNewArrayPrimitiveType();  
-		break ;
-		
-	case 289 : // System.out.println("AllocationHeader ::= new ClassType LPAREN ArgumentListopt RPAREN");  //$NON-NLS-1$
-		consumeAllocationHeader();  
-		break ;
-		
-	case 290 : // System.out.println("ClassInstanceCreationExpression ::= new ClassType LPAREN...");  //$NON-NLS-1$
-		consumeClassInstanceCreationExpression();  
-		break ;
-		
-	case 291 : // System.out.println("ClassInstanceCreationExpression ::= Primary DOT new SimpleName...");  //$NON-NLS-1$
-		consumeClassInstanceCreationExpressionQualified() ;  
-		break ;
-		
-	case 292 : // System.out.println("ClassInstanceCreationExpression ::=...");  //$NON-NLS-1$
-		consumeClassInstanceCreationExpressionQualified() ;  
-		break ;
-		
-	case 293 : // System.out.println("ClassInstanceCreationExpressionName ::= Name DOT");  //$NON-NLS-1$
-		consumeClassInstanceCreationExpressionName() ;  
-		break ;
-		
-	case 294 : // System.out.println("ClassBodyopt ::=");  //$NON-NLS-1$
-		consumeClassBodyopt();  
-		break ;
-		
-	case 296 : // System.out.println("EnterAnonymousClassBody ::=");  //$NON-NLS-1$
-		consumeEnterAnonymousClassBody();  
-		break ;
-		
-	case 298 : // System.out.println("ArgumentList ::= ArgumentList COMMA Expression");  //$NON-NLS-1$
-		consumeArgumentList();  
-		break ;
-		
-	case 299 : // System.out.println("ArrayCreationHeader ::= new PrimitiveType DimWithOrWithOutExprs");  //$NON-NLS-1$
-		consumeArrayCreationHeader();  
-		break ;
-		
-	case 300 : // System.out.println("ArrayCreationHeader ::= new ClassOrInterfaceType...");  //$NON-NLS-1$
-		consumeArrayCreationHeader();  
-		break ;
-		
-	case 301 : // System.out.println("ArrayCreationWithoutArrayInitializer ::= new PrimitiveType...");  //$NON-NLS-1$
-		consumeArrayCreationExpressionWithoutInitializer();  
-		break ;
-		
-	case 302 : // System.out.println("ArrayCreationWithArrayInitializer ::= new PrimitiveType...");  //$NON-NLS-1$
-		consumeArrayCreationExpressionWithInitializer();  
-		break ;
-		
-	case 303 : // System.out.println("ArrayCreationWithoutArrayInitializer ::= new ClassOrInterfaceType...");  //$NON-NLS-1$
-		consumeArrayCreationExpressionWithoutInitializer();  
-		break ;
-		
-	case 304 : // System.out.println("ArrayCreationWithArrayInitializer ::= new ClassOrInterfaceType...");  //$NON-NLS-1$
-		consumeArrayCreationExpressionWithInitializer();  
-		break ;
-		
-	case 306 : // System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs DimWithOrWithOutExpr");  //$NON-NLS-1$
-		consumeDimWithOrWithOutExprs();  
-		break ;
-		
-	case 308 : // System.out.println("DimWithOrWithOutExpr ::= LBRACKET RBRACKET");  //$NON-NLS-1$
-		consumeDimWithOrWithOutExpr();  
-		break ;
-		
-	case 309 : // System.out.println("Dims ::= DimsLoop");  //$NON-NLS-1$
-		consumeDims();  
-		break ;
-		
-	case 312 : // System.out.println("OneDimLoop ::= LBRACKET RBRACKET");  //$NON-NLS-1$
-		consumeOneDimLoop();  
-		break ;
-		
-	case 313 : // System.out.println("FieldAccess ::= Primary DOT Identifier");  //$NON-NLS-1$
-		consumeFieldAccess(false);  
-		break ;
-		
-	case 314 : // System.out.println("FieldAccess ::= super DOT Identifier");  //$NON-NLS-1$
-		consumeFieldAccess(true);  
-		break ;
-		
-	case 315 : // System.out.println("MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN");  //$NON-NLS-1$
-		consumeMethodInvocationName();  
-		break ;
-		
-	case 316 : // System.out.println("MethodInvocation ::= Primary DOT Identifier LPAREN ArgumentListopt");  //$NON-NLS-1$
-		consumeMethodInvocationPrimary();  
-		break ;
-		
-	case 317 : // System.out.println("MethodInvocation ::= super DOT Identifier LPAREN ArgumentListopt...");  //$NON-NLS-1$
-		consumeMethodInvocationSuper();  
-		break ;
-		
-	case 318 : // System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET");  //$NON-NLS-1$
-		consumeArrayAccess(true);  
-		break ;
-		
-	case 319 : // System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression RBRACKET");  //$NON-NLS-1$
-		consumeArrayAccess(false);  
-		break ;
-		
-	case 320 : // System.out.println("ArrayAccess ::= ArrayCreationWithArrayInitializer LBRACKET...");  //$NON-NLS-1$
-		consumeArrayAccess(false);  
-		break ;
-		
-	case 322 : // System.out.println("PostfixExpression ::= Name");  //$NON-NLS-1$
-		consumePostfixExpression();  
-		break ;
-		
-	case 325 : // System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS");  //$NON-NLS-1$
-		consumeUnaryExpression(OperatorIds.PLUS,true);  
-		break ;
-		
-	case 326 : // System.out.println("PostDecrementExpression ::= PostfixExpression MINUS_MINUS");  //$NON-NLS-1$
-		consumeUnaryExpression(OperatorIds.MINUS,true);  
-		break ;
-		
-	case 327 : // System.out.println("PushPosition ::=");  //$NON-NLS-1$
-		consumePushPosition();  
-		break ;
-		
-	case 330 : // System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression");  //$NON-NLS-1$
-		consumeUnaryExpression(OperatorIds.PLUS);  
-		break ;
-		
-	case 331 : // System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression");  //$NON-NLS-1$
-		consumeUnaryExpression(OperatorIds.MINUS);  
-		break ;
-		
-	case 333 : // System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition UnaryExpression");  //$NON-NLS-1$
-		consumeUnaryExpression(OperatorIds.PLUS,false);  
-		break ;
-		
-	case 334 : // System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition UnaryExpression");  //$NON-NLS-1$
-		consumeUnaryExpression(OperatorIds.MINUS,false);  
-		break ;
-		
-	case 336 : // System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition UnaryExpression");  //$NON-NLS-1$
-		consumeUnaryExpression(OperatorIds.TWIDDLE);  
-		break ;
-		
-	case 337 : // System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition UnaryExpression");  //$NON-NLS-1$
-		consumeUnaryExpression(OperatorIds.NOT);  
-		break ;
-		
-	case 339 : // System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt PushRPAREN...");  //$NON-NLS-1$
-		consumeCastExpression();  
-		break ;
-		
-	case 340 : // System.out.println("CastExpression ::= PushLPAREN Name Dims PushRPAREN...");  //$NON-NLS-1$
-		consumeCastExpression();  
-		break ;
-		
-	case 341 : // System.out.println("CastExpression ::= PushLPAREN Expression PushRPAREN...");  //$NON-NLS-1$
-		consumeCastExpressionLL1();  
-		break ;
-		
-	case 342 : // System.out.println("InsideCastExpression ::=");  //$NON-NLS-1$
-		consumeInsideCastExpression();  
-		break ;
-		
-	case 343 : // System.out.println("InsideCastExpressionLL1 ::=");  //$NON-NLS-1$
-		consumeInsideCastExpressionLL1();  
-		break ;
-		
-	case 345 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression MULTIPLY...");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.MULTIPLY);  
-		break ;
-		
-	case 346 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression DIVIDE...");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.DIVIDE);  
-		break ;
-		
-	case 347 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression REMAINDER...");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.REMAINDER);  
-		break ;
-		
-	case 349 : // System.out.println("AdditiveExpression ::= AdditiveExpression PLUS...");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.PLUS);  
-		break ;
-		
-	case 350 : // System.out.println("AdditiveExpression ::= AdditiveExpression MINUS...");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.MINUS);  
-		break ;
-		
-	case 352 : // System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT AdditiveExpression");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.LEFT_SHIFT);  
-		break ;
-		
-	case 353 : // System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT AdditiveExpression");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.RIGHT_SHIFT);  
-		break ;
-		
-	case 354 : // System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT...");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT);  
-		break ;
-		
-	case 356 : // System.out.println("RelationalExpression ::= RelationalExpression LESS ShiftExpression");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.LESS);  
-		break ;
-		
-	case 357 : // System.out.println("RelationalExpression ::= RelationalExpression GREATER...");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.GREATER);  
-		break ;
-		
-	case 358 : // System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL...");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.LESS_EQUAL);  
-		break ;
-		
-	case 359 : // System.out.println("RelationalExpression ::= RelationalExpression GREATER_EQUAL...");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.GREATER_EQUAL);  
-		break ;
-		
-	case 360 : // System.out.println("RelationalExpression ::= RelationalExpression instanceof...");  //$NON-NLS-1$
-		consumeInstanceOfExpression(OperatorIds.INSTANCEOF);  
-		break ;
-		
-	case 362 : // System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL...");  //$NON-NLS-1$
-		consumeEqualityExpression(OperatorIds.EQUAL_EQUAL);  
-		break ;
-		
-	case 363 : // System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL...");  //$NON-NLS-1$
-		consumeEqualityExpression(OperatorIds.NOT_EQUAL);  
-		break ;
-		
-	case 365 : // System.out.println("AndExpression ::= AndExpression AND EqualityExpression");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.AND);  
-		break ;
-		
-	case 367 : // System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR AndExpression");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.XOR);  
-		break ;
-		
-	case 369 : // System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR...");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.OR);  
-		break ;
-		
-	case 371 : // System.out.println("ConditionalAndExpression ::= ConditionalAndExpression AND_AND...");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.AND_AND);  
-		break ;
-		
-	case 373 : // System.out.println("ConditionalOrExpression ::= ConditionalOrExpression OR_OR...");  //$NON-NLS-1$
-		consumeBinaryExpression(OperatorIds.OR_OR);  
-		break ;
-		
-	case 375 : // System.out.println("ConditionalExpression ::= ConditionalOrExpression QUESTION...");  //$NON-NLS-1$
-		consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ;  
-		break ;
-		
-	case 378 : // System.out.println("Assignment ::= PostfixExpression AssignmentOperator...");  //$NON-NLS-1$
-		consumeAssignment();  
-		break ;
-		
-	case 380 : // System.out.println("Assignment ::= InvalidArrayInitializerAssignement");  //$NON-NLS-1$
-		ignoreExpressionAssignment(); 
-		break ;
-		
-	case 381 : // System.out.println("AssignmentOperator ::= EQUAL");  //$NON-NLS-1$
-		consumeAssignmentOperator(EQUAL);  
-		break ;
-		
-	case 382 : // System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL");  //$NON-NLS-1$
-		consumeAssignmentOperator(MULTIPLY);  
-		break ;
-		
-	case 383 : // System.out.println("AssignmentOperator ::= DIVIDE_EQUAL");  //$NON-NLS-1$
-		consumeAssignmentOperator(DIVIDE);  
-		break ;
-		
-	case 384 : // System.out.println("AssignmentOperator ::= REMAINDER_EQUAL");  //$NON-NLS-1$
-		consumeAssignmentOperator(REMAINDER);  
-		break ;
-		
-	case 385 : // System.out.println("AssignmentOperator ::= PLUS_EQUAL");  //$NON-NLS-1$
-		consumeAssignmentOperator(PLUS);  
-		break ;
-		
-	case 386 : // System.out.println("AssignmentOperator ::= MINUS_EQUAL");  //$NON-NLS-1$
-		consumeAssignmentOperator(MINUS);  
-		break ;
-		
-	case 387 : // System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL");  //$NON-NLS-1$
-		consumeAssignmentOperator(LEFT_SHIFT);  
-		break ;
-		
-	case 388 : // System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL");  //$NON-NLS-1$
-		consumeAssignmentOperator(RIGHT_SHIFT);  
-		break ;
-		
-	case 389 : // System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL");  //$NON-NLS-1$
-		consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT);  
-		break ;
-		
-	case 390 : // System.out.println("AssignmentOperator ::= AND_EQUAL");  //$NON-NLS-1$
-		consumeAssignmentOperator(AND);  
-		break ;
-		
-	case 391 : // System.out.println("AssignmentOperator ::= XOR_EQUAL");  //$NON-NLS-1$
-		consumeAssignmentOperator(XOR);  
-		break ;
-		
-	case 392 : // System.out.println("AssignmentOperator ::= OR_EQUAL");  //$NON-NLS-1$
-		consumeAssignmentOperator(OR);  
-		break ;
-		
-	case 399 : // System.out.println("Expressionopt ::=");  //$NON-NLS-1$
-		consumeEmptyExpression();  
-		break ;
-		
-	case 403 : // System.out.println("ImportDeclarationsopt ::=");  //$NON-NLS-1$
-		consumeEmptyImportDeclarationsopt();  
-		break ;
-		
-	case 404 : // System.out.println("ImportDeclarationsopt ::= ImportDeclarations");  //$NON-NLS-1$
-		consumeImportDeclarationsopt();  
-		break ;
-		
-	case 405 : // System.out.println("TypeDeclarationsopt ::=");  //$NON-NLS-1$
-		consumeEmptyTypeDeclarationsopt();  
-		break ;
-		
-	case 406 : // System.out.println("TypeDeclarationsopt ::= TypeDeclarations");  //$NON-NLS-1$
-		consumeTypeDeclarationsopt();  
-		break ;
-		
-	case 407 : // System.out.println("ClassBodyDeclarationsopt ::=");  //$NON-NLS-1$
-		consumeEmptyClassBodyDeclarationsopt();  
-		break ;
-		
-	case 408 : // System.out.println("ClassBodyDeclarationsopt ::= NestedType ClassBodyDeclarations");  //$NON-NLS-1$
-		consumeClassBodyDeclarationsopt();  
-		break ;
-		
-	case 409 : // System.out.println("Modifiersopt ::=");  //$NON-NLS-1$
-		consumeDefaultModifiers();  
-		break ;
-		
-	case 410 : // System.out.println("Modifiersopt ::= Modifiers");  //$NON-NLS-1$
-		consumeModifiers();  
-		break ;
-		
-	case 411 : // System.out.println("BlockStatementsopt ::=");  //$NON-NLS-1$
-		consumeEmptyBlockStatementsopt();  
-		break ;
-		
-	case 413 : // System.out.println("Dimsopt ::=");  //$NON-NLS-1$
-		consumeEmptyDimsopt();  
-		break ;
-		
-	case 415 : // System.out.println("ArgumentListopt ::=");  //$NON-NLS-1$
-		consumeEmptyArgumentListopt();  
-		break ;
-		
-	case 419 : // System.out.println("FormalParameterListopt ::=");  //$NON-NLS-1$
-		consumeFormalParameterListopt();  
-		break ;
-		
-	case 423 : // System.out.println("InterfaceMemberDeclarationsopt ::=");  //$NON-NLS-1$
-		consumeEmptyInterfaceMemberDeclarationsopt();  
-		break ;
-		
-	case 424 : // System.out.println("InterfaceMemberDeclarationsopt ::= NestedType...");  //$NON-NLS-1$
-		consumeInterfaceMemberDeclarationsopt();  
-		break ;
-		
-	case 425 : // System.out.println("NestedType ::=");  //$NON-NLS-1$
-		consumeNestedType();  
-		break ;
+    case 184 : if (DEBUG) { System.out.println("StaticOnly ::= static"); }  //$NON-NLS-1$
+		    consumeStaticOnly();  
+			break;
+ 
+    case 185 : if (DEBUG) { System.out.println("ConstructorDeclaration ::= ConstructorHeader MethodBody"); }  //$NON-NLS-1$
+		    consumeConstructorDeclaration() ;  
+			break;
+ 
+    case 186 : if (DEBUG) { System.out.println("ConstructorDeclaration ::= ConstructorHeader SEMICOLON"); }  //$NON-NLS-1$
+		    consumeInvalidConstructorDeclaration() ;  
+			break;
+ 
+    case 187 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= this LPAREN..."); }  //$NON-NLS-1$
+		    consumeExplicitConstructorInvocation(0, THIS_CALL);  
+			break;
+ 
+    case 188 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= OnlyTypeArguments this"); }  //$NON-NLS-1$
+		    consumeExplicitConstructorInvocationWithTypeArguments(0,THIS_CALL);  
+			break;
+ 
+    case 189 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= super LPAREN..."); }  //$NON-NLS-1$
+		    consumeExplicitConstructorInvocation(0,SUPER_CALL);  
+			break;
+ 
+    case 190 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= OnlyTypeArguments..."); }  //$NON-NLS-1$
+		    consumeExplicitConstructorInvocationWithTypeArguments(0,SUPER_CALL);  
+			break;
+ 
+    case 191 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT super..."); }  //$NON-NLS-1$
+		    consumeExplicitConstructorInvocation(1, SUPER_CALL);  
+			break;
+ 
+    case 192 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT..."); }  //$NON-NLS-1$
+		    consumeExplicitConstructorInvocationWithTypeArguments(1, SUPER_CALL);  
+			break;
+ 
+    case 193 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT super LPAREN"); }  //$NON-NLS-1$
+		    consumeExplicitConstructorInvocation(2, SUPER_CALL);  
+			break;
+ 
+    case 194 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT..."); }  //$NON-NLS-1$
+		    consumeExplicitConstructorInvocationWithTypeArguments(2, SUPER_CALL);  
+			break;
+ 
+    case 195 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT this..."); }  //$NON-NLS-1$
+		    consumeExplicitConstructorInvocation(1, THIS_CALL);  
+			break;
+ 
+    case 196 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT..."); }  //$NON-NLS-1$
+		    consumeExplicitConstructorInvocationWithTypeArguments(1, THIS_CALL);  
+			break;
+ 
+    case 197 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT this LPAREN"); }  //$NON-NLS-1$
+		    consumeExplicitConstructorInvocation(2, THIS_CALL);  
+			break;
+ 
+    case 198 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT..."); }  //$NON-NLS-1$
+		    consumeExplicitConstructorInvocationWithTypeArguments(2, THIS_CALL);  
+			break;
+ 
+    case 199 : if (DEBUG) { System.out.println("InterfaceDeclaration ::= InterfaceHeader InterfaceBody"); }  //$NON-NLS-1$
+		    consumeInterfaceDeclaration();  
+			break;
+ 
+    case 200 : if (DEBUG) { System.out.println("InterfaceHeader ::= InterfaceHeaderName..."); }  //$NON-NLS-1$
+		    consumeInterfaceHeader();  
+			break;
+ 
+    case 201 : if (DEBUG) { System.out.println("InterfaceHeaderName ::= InterfaceHeaderName1..."); }  //$NON-NLS-1$
+		    consumeTypeHeaderNameWithTypeParameters();  
+			break;
+ 
+    case 203 : if (DEBUG) { System.out.println("InterfaceHeaderName1 ::= Modifiersopt interface..."); }  //$NON-NLS-1$
+		    consumeInterfaceHeaderName1();  
+			break;
+ 
+    case 205 : if (DEBUG) { System.out.println("InterfaceHeaderExtends ::= extends InterfaceTypeList"); }  //$NON-NLS-1$
+		    consumeInterfaceHeaderExtends();  
+			break;
+ 
+    case 208 : if (DEBUG) { System.out.println("InterfaceMemberDeclarations ::=..."); }  //$NON-NLS-1$
+		    consumeInterfaceMemberDeclarations();  
+			break;
+ 
+    case 209 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= SEMICOLON"); }  //$NON-NLS-1$
+		    consumeEmptyInterfaceMemberDeclaration();  
+			break;
+ 
+    case 212 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= InvalidMethodDeclaration"); }  //$NON-NLS-1$
+		    ignoreMethodBody();  
+			break;
+ 
+    case 213 : if (DEBUG) { System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader..."); }  //$NON-NLS-1$
+		    ignoreInvalidConstructorDeclaration(true);   
+			break;
+ 
+    case 214 : if (DEBUG) { System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader..."); }  //$NON-NLS-1$
+		    ignoreInvalidConstructorDeclaration(false);   
+			break;
+ 
+    case 222 : if (DEBUG) { System.out.println("PushLeftBrace ::="); }  //$NON-NLS-1$
+		    consumePushLeftBrace();  
+			break;
+ 
+    case 223 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace ,opt RBRACE"); }  //$NON-NLS-1$
+		    consumeEmptyArrayInitializer();  
+			break;
+ 
+    case 224 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace..."); }  //$NON-NLS-1$
+		    consumeArrayInitializer();  
+			break;
+ 
+    case 225 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace..."); }  //$NON-NLS-1$
+		    consumeArrayInitializer();  
+			break;
+ 
+    case 227 : if (DEBUG) { System.out.println("VariableInitializers ::= VariableInitializers COMMA..."); }  //$NON-NLS-1$
+		    consumeVariableInitializers();  
+			break;
+ 
+    case 228 : if (DEBUG) { System.out.println("Block ::= OpenBlock LBRACE BlockStatementsopt RBRACE"); }  //$NON-NLS-1$
+		    consumeBlock();  
+			break;
+ 
+    case 229 : if (DEBUG) { System.out.println("OpenBlock ::="); }  //$NON-NLS-1$
+		    consumeOpenBlock() ;  
+			break;
+ 
+    case 231 : if (DEBUG) { System.out.println("BlockStatements ::= BlockStatements BlockStatement"); }  //$NON-NLS-1$
+		    consumeBlockStatements() ;  
+			break;
+ 
+    case 235 : if (DEBUG) { System.out.println("BlockStatement ::= InvalidInterfaceDeclaration"); }  //$NON-NLS-1$
+		    ignoreInterfaceDeclaration();  
+			break;
+ 
+    case 236 : if (DEBUG) { System.out.println("LocalVariableDeclarationStatement ::=..."); }  //$NON-NLS-1$
+		    consumeLocalVariableDeclarationStatement();  
+			break;
+ 
+    case 237 : if (DEBUG) { System.out.println("LocalVariableDeclaration ::= Type PushModifiers..."); }  //$NON-NLS-1$
+		    consumeLocalVariableDeclaration();  
+			break;
+ 
+    case 238 : if (DEBUG) { System.out.println("LocalVariableDeclaration ::= Modifiers Type..."); }  //$NON-NLS-1$
+		    consumeLocalVariableDeclaration();  
+			break;
+ 
+    case 239 : if (DEBUG) { System.out.println("PushModifiers ::="); }  //$NON-NLS-1$
+		    consumePushModifiers();  
+			break;
+ 
+    case 240 : if (DEBUG) { System.out.println("PushModifiersForHeader ::="); }  //$NON-NLS-1$
+		    consumePushModifiersForHeader();  
+			break;
+ 
+    case 241 : if (DEBUG) { System.out.println("PushRealModifiers ::="); }  //$NON-NLS-1$
+		    consumePushRealModifiers();  
+			break;
+ 
+    case 267 : if (DEBUG) { System.out.println("EmptyStatement ::= SEMICOLON"); }  //$NON-NLS-1$
+		    consumeEmptyStatement();  
+			break;
+ 
+    case 268 : if (DEBUG) { System.out.println("LabeledStatement ::= Identifier COLON Statement"); }  //$NON-NLS-1$
+		    consumeStatementLabel() ;  
+			break;
+ 
+    case 269 : if (DEBUG) { System.out.println("LabeledStatementNoShortIf ::= Identifier COLON..."); }  //$NON-NLS-1$
+		    consumeStatementLabel() ;  
+			break;
+ 
+     case 270 : if (DEBUG) { System.out.println("ExpressionStatement ::= StatementExpression SEMICOLON"); }  //$NON-NLS-1$
+		    consumeExpressionStatement();  
+			break;
+ 
+    case 279 : if (DEBUG) { System.out.println("IfThenStatement ::= if LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
+		    consumeStatementIfNoElse();  
+			break;
+ 
+    case 280 : if (DEBUG) { System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
+		    consumeStatementIfWithElse();  
+			break;
+ 
+    case 281 : if (DEBUG) { System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression..."); }  //$NON-NLS-1$
+		    consumeStatementIfWithElse();  
+			break;
+ 
+    case 282 : if (DEBUG) { System.out.println("SwitchStatement ::= switch LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
+		    consumeStatementSwitch() ;  
+			break;
+ 
+    case 283 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE RBRACE"); }  //$NON-NLS-1$
+		    consumeEmptySwitchBlock() ;  
+			break;
+ 
+    case 286 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE SwitchBlockStatements..."); }  //$NON-NLS-1$
+		    consumeSwitchBlock() ;  
+			break;
+ 
+    case 288 : if (DEBUG) { System.out.println("SwitchBlockStatements ::= SwitchBlockStatements..."); }  //$NON-NLS-1$
+		    consumeSwitchBlockStatements() ;  
+			break;
+ 
+    case 289 : if (DEBUG) { System.out.println("SwitchBlockStatement ::= SwitchLabels BlockStatements"); }  //$NON-NLS-1$
+		    consumeSwitchBlockStatement() ;  
+			break;
+ 
+    case 291 : if (DEBUG) { System.out.println("SwitchLabels ::= SwitchLabels SwitchLabel"); }  //$NON-NLS-1$
+		    consumeSwitchLabels() ;  
+			break;
+ 
+     case 292 : if (DEBUG) { System.out.println("SwitchLabel ::= case ConstantExpression COLON"); }  //$NON-NLS-1$
+		    consumeCaseLabel();  
+			break;
+ 
+     case 293 : if (DEBUG) { System.out.println("SwitchLabel ::= default COLON"); }  //$NON-NLS-1$
+		    consumeDefaultLabel();  
+			break;
+ 
+    case 294 : if (DEBUG) { System.out.println("WhileStatement ::= while LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
+		    consumeStatementWhile() ;  
+			break;
+ 
+    case 295 : if (DEBUG) { System.out.println("WhileStatementNoShortIf ::= while LPAREN Expression..."); }  //$NON-NLS-1$
+		    consumeStatementWhile() ;  
+			break;
+ 
+    case 296 : if (DEBUG) { System.out.println("DoStatement ::= do Statement while LPAREN Expression..."); }  //$NON-NLS-1$
+		    consumeStatementDo() ;  
+			break;
+ 
+    case 297 : if (DEBUG) { System.out.println("ForStatement ::= for LPAREN ForInitopt SEMICOLON..."); }  //$NON-NLS-1$
+		    consumeStatementFor() ;  
+			break;
+ 
+    case 298 : if (DEBUG) { System.out.println("ForStatementNoShortIf ::= for LPAREN ForInitopt..."); }  //$NON-NLS-1$
+		    consumeStatementFor() ;  
+			break;
+ 
+    case 299 : if (DEBUG) { System.out.println("ForInit ::= StatementExpressionList"); }  //$NON-NLS-1$
+		    consumeForInit() ;  
+			break;
+ 
+    case 303 : if (DEBUG) { System.out.println("StatementExpressionList ::= StatementExpressionList..."); }  //$NON-NLS-1$
+		    consumeStatementExpressionList() ;  
+			break;
+ 
+    case 304 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression SEMICOLON"); }  //$NON-NLS-1$
+		    consumeSimpleAssertStatement() ;  
+			break;
+ 
+    case 305 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression COLON Expression"); }  //$NON-NLS-1$
+		    consumeAssertStatement() ;  
+			break;
+ 
+    case 306 : if (DEBUG) { System.out.println("BreakStatement ::= break SEMICOLON"); }  //$NON-NLS-1$
+		    consumeStatementBreak() ;  
+			break;
+ 
+    case 307 : if (DEBUG) { System.out.println("BreakStatement ::= break Identifier SEMICOLON"); }  //$NON-NLS-1$
+		    consumeStatementBreakWithLabel() ;  
+			break;
+ 
+    case 308 : if (DEBUG) { System.out.println("ContinueStatement ::= continue SEMICOLON"); }  //$NON-NLS-1$
+		    consumeStatementContinue() ;  
+			break;
+ 
+    case 309 : if (DEBUG) { System.out.println("ContinueStatement ::= continue Identifier SEMICOLON"); }  //$NON-NLS-1$
+		    consumeStatementContinueWithLabel() ;  
+			break;
+ 
+    case 310 : if (DEBUG) { System.out.println("ReturnStatement ::= return Expressionopt SEMICOLON"); }  //$NON-NLS-1$
+		    consumeStatementReturn() ;  
+			break;
+ 
+    case 311 : if (DEBUG) { System.out.println("ThrowStatement ::= throw Expression SEMICOLON"); }  //$NON-NLS-1$
+		    consumeStatementThrow();  
+			break;
+ 
+    case 312 : if (DEBUG) { System.out.println("SynchronizedStatement ::= OnlySynchronized LPAREN..."); }  //$NON-NLS-1$
+		    consumeStatementSynchronized();  
+			break;
+ 
+    case 313 : if (DEBUG) { System.out.println("OnlySynchronized ::= synchronized"); }  //$NON-NLS-1$
+		    consumeOnlySynchronized();  
+			break;
+ 
+    case 314 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catches"); }  //$NON-NLS-1$
+		    consumeStatementTry(false);  
+			break;
+ 
+    case 315 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catchesopt Finally"); }  //$NON-NLS-1$
+		    consumeStatementTry(true);  
+			break;
+ 
+    case 317 : if (DEBUG) { System.out.println("ExitTryBlock ::="); }  //$NON-NLS-1$
+		    consumeExitTryBlock();  
+			break;
+ 
+    case 319 : if (DEBUG) { System.out.println("Catches ::= Catches CatchClause"); }  //$NON-NLS-1$
+		    consumeCatches();  
+			break;
+ 
+    case 320 : if (DEBUG) { System.out.println("CatchClause ::= catch LPAREN FormalParameter RPAREN..."); }  //$NON-NLS-1$
+		    consumeStatementCatch() ;  
+			break;
+ 
+    case 322 : if (DEBUG) { System.out.println("PushLPAREN ::= LPAREN"); }  //$NON-NLS-1$
+		    consumeLeftParen();  
+			break;
+ 
+    case 323 : if (DEBUG) { System.out.println("PushRPAREN ::= RPAREN"); }  //$NON-NLS-1$
+		    consumeRightParen();  
+			break;
+ 
+    case 328 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= this"); }  //$NON-NLS-1$
+		    consumePrimaryNoNewArrayThis();  
+			break;
+ 
+    case 329 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression_NotName..."); }  //$NON-NLS-1$
+		    consumePrimaryNoNewArray();  
+			break;
+ 
+    case 330 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Name PushRPAREN"); }  //$NON-NLS-1$
+		    consumePrimaryNoNewArrayWithName();  
+			break;
+ 
+    case 333 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT this"); }  //$NON-NLS-1$
+		    consumePrimaryNoNewArrayNameThis();  
+			break;
+ 
+    case 334 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT super"); }  //$NON-NLS-1$
+		    consumePrimaryNoNewArrayNameSuper();  
+			break;
+ 
+    case 335 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT class"); }  //$NON-NLS-1$
+		    consumePrimaryNoNewArrayName();  
+			break;
+ 
+    case 336 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name Dims DOT class"); }  //$NON-NLS-1$
+		    consumePrimaryNoNewArrayArrayType();  
+			break;
+ 
+    case 337 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType Dims DOT class"); }  //$NON-NLS-1$
+		    consumePrimaryNoNewArrayPrimitiveArrayType();  
+			break;
+ 
+    case 338 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class"); }  //$NON-NLS-1$
+		    consumePrimaryNoNewArrayPrimitiveType();  
+			break;
+ 
+    case 341 : if (DEBUG) { System.out.println("AllocationHeader ::= new ClassType LPAREN..."); }  //$NON-NLS-1$
+		    consumeAllocationHeader();  
+			break;
+ 
+    case 342 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new..."); }  //$NON-NLS-1$
+		    consumeClassInstanceCreationExpressionWithTypeArguments();  
+			break;
+ 
+    case 343 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new ClassType LPAREN"); }  //$NON-NLS-1$
+		    consumeClassInstanceCreationExpression();  
+			break;
+ 
+    case 344 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); }  //$NON-NLS-1$
+		    consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() ;  
+			break;
+ 
+    case 345 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); }  //$NON-NLS-1$
+		    consumeClassInstanceCreationExpressionQualified() ;  
+			break;
+ 
+    case 346 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); }  //$NON-NLS-1$
+		    consumeClassInstanceCreationExpressionQualified() ;  
+			break;
+ 
+    case 347 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); }  //$NON-NLS-1$
+		    consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() ;  
+			break;
+ 
+    case 348 : if (DEBUG) { System.out.println("ClassInstanceCreationExpressionName ::= Name DOT"); }  //$NON-NLS-1$
+		    consumeClassInstanceCreationExpressionName() ;  
+			break;
+ 
+    case 349 : if (DEBUG) { System.out.println("ClassBodyopt ::="); }  //$NON-NLS-1$
+		    consumeClassBodyopt();  
+			break;
+ 
+    case 351 : if (DEBUG) { System.out.println("ClassBodySimpleNameopt ::="); }  //$NON-NLS-1$
+		    consumeClassBodyopt();  
+			break;
+ 
+    case 353 : if (DEBUG) { System.out.println("EnterAnonymousClassBodySimpleName ::="); }  //$NON-NLS-1$
+		    consumeEnterAnonymousClassBodySimpleName();  
+			break;
+ 
+    case 354 : if (DEBUG) { System.out.println("EnterAnonymousClassBody ::="); }  //$NON-NLS-1$
+		    consumeEnterAnonymousClassBody();  
+			break;
+ 
+    case 356 : if (DEBUG) { System.out.println("ArgumentList ::= ArgumentList COMMA Expression"); }  //$NON-NLS-1$
+		    consumeArgumentList();  
+			break;
+ 
+    case 357 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new PrimitiveType..."); }  //$NON-NLS-1$
+		    consumeArrayCreationHeader();  
+			break;
+ 
+    case 358 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new ClassOrInterfaceType..."); }  //$NON-NLS-1$
+		    consumeArrayCreationHeader();  
+			break;
+ 
+    case 359 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); }  //$NON-NLS-1$
+		    consumeArrayCreationExpressionWithoutInitializer();  
+			break;
+ 
+    case 360 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new PrimitiveType"); }  //$NON-NLS-1$
+		    consumeArrayCreationExpressionWithInitializer();  
+			break;
+ 
+    case 361 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); }  //$NON-NLS-1$
+		    consumeArrayCreationExpressionWithoutInitializer();  
+			break;
+ 
+    case 362 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new..."); }  //$NON-NLS-1$
+		    consumeArrayCreationExpressionWithInitializer();  
+			break;
+ 
+    case 364 : if (DEBUG) { System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs..."); }  //$NON-NLS-1$
+		    consumeDimWithOrWithOutExprs();  
+			break;
+ 
+     case 366 : if (DEBUG) { System.out.println("DimWithOrWithOutExpr ::= LBRACKET RBRACKET"); }  //$NON-NLS-1$
+		    consumeDimWithOrWithOutExpr();  
+			break;
+ 
+     case 367 : if (DEBUG) { System.out.println("Dims ::= DimsLoop"); }  //$NON-NLS-1$
+		    consumeDims();  
+			break;
+ 
+     case 370 : if (DEBUG) { System.out.println("OneDimLoop ::= LBRACKET RBRACKET"); }  //$NON-NLS-1$
+		    consumeOneDimLoop();  
+			break;
+ 
+    case 371 : if (DEBUG) { System.out.println("FieldAccess ::= Primary DOT Identifier"); }  //$NON-NLS-1$
+		    consumeFieldAccess(false);  
+			break;
+ 
+    case 372 : if (DEBUG) { System.out.println("FieldAccess ::= super DOT Identifier"); }  //$NON-NLS-1$
+		    consumeFieldAccess(true);  
+			break;
+ 
+    case 373 : if (DEBUG) { System.out.println("MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN"); }  //$NON-NLS-1$
+		    consumeMethodInvocationName();  
+			break;
+ 
+    case 374 : if (DEBUG) { System.out.println("MethodInvocation ::= Name DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
+		    consumeMethodInvocationNameWithTypeArguments();  
+			break;
+ 
+    case 375 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
+		    consumeMethodInvocationPrimaryWithTypeArguments();  
+			break;
+ 
+    case 376 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT Identifier LPAREN..."); }  //$NON-NLS-1$
+		    consumeMethodInvocationPrimary();  
+			break;
+ 
+    case 377 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
+		    consumeMethodInvocationSuperWithTypeArguments();  
+			break;
+ 
+    case 378 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT Identifier LPAREN..."); }  //$NON-NLS-1$
+		    consumeMethodInvocationSuper();  
+			break;
+ 
+    case 379 : if (DEBUG) { System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET"); }  //$NON-NLS-1$
+		    consumeArrayAccess(true);  
+			break;
+ 
+    case 380 : if (DEBUG) { System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression..."); }  //$NON-NLS-1$
+		    consumeArrayAccess(false);  
+			break;
+ 
+    case 381 : if (DEBUG) { System.out.println("ArrayAccess ::= ArrayCreationWithArrayInitializer..."); }  //$NON-NLS-1$
+		    consumeArrayAccess(false);  
+			break;
+ 
+    case 383 : if (DEBUG) { System.out.println("PostfixExpression ::= Name"); }  //$NON-NLS-1$
+		    consumePostfixExpression();  
+			break;
+ 
+    case 386 : if (DEBUG) { System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS"); }  //$NON-NLS-1$
+		    consumeUnaryExpression(OperatorIds.PLUS,true);  
+			break;
+ 
+    case 387 : if (DEBUG) { System.out.println("PostDecrementExpression ::= PostfixExpression..."); }  //$NON-NLS-1$
+		    consumeUnaryExpression(OperatorIds.MINUS,true);  
+			break;
+ 
+    case 388 : if (DEBUG) { System.out.println("PushPosition ::="); }  //$NON-NLS-1$
+		    consumePushPosition();  
+			break;
+ 
+    case 391 : if (DEBUG) { System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression"); }  //$NON-NLS-1$
+		    consumeUnaryExpression(OperatorIds.PLUS);  
+			break;
+ 
+    case 392 : if (DEBUG) { System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression"); }  //$NON-NLS-1$
+		    consumeUnaryExpression(OperatorIds.MINUS);  
+			break;
+ 
+    case 394 : if (DEBUG) { System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition..."); }  //$NON-NLS-1$
+		    consumeUnaryExpression(OperatorIds.PLUS,false);  
+			break;
+ 
+    case 395 : if (DEBUG) { System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition..."); }  //$NON-NLS-1$
+		    consumeUnaryExpression(OperatorIds.MINUS,false);  
+			break;
+ 
+    case 397 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition..."); }  //$NON-NLS-1$
+		    consumeUnaryExpression(OperatorIds.TWIDDLE);  
+			break;
+ 
+    case 398 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition..."); }  //$NON-NLS-1$
+		    consumeUnaryExpression(OperatorIds.NOT);  
+			break;
+ 
+    case 400 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt..."); }  //$NON-NLS-1$
+		    consumeCastExpressionWithPrimitiveType();  
+			break;
+ 
+    case 401 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); }  //$NON-NLS-1$
+		    consumeCastExpressionWithGenericsArray();  
+			break;
+ 
+    case 402 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); }  //$NON-NLS-1$
+		    consumeCastExpressionWithQualifiedGenericsArray();  
+			break;
+ 
+    case 403 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name PushRPAREN..."); }  //$NON-NLS-1$
+		    consumeCastExpressionLL1();  
+			break;
+ 
+    case 404 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name Dims PushRPAREN..."); }  //$NON-NLS-1$
+		    consumeCastExpressionWithNameArray();  
+			break;
+ 
+    case 405 : if (DEBUG) { System.out.println("OnlyTypeArgumentsForCastExpression ::= OnlyTypeArguments"); }  //$NON-NLS-1$
+		    consumeOnlyTypeArgumentsForCastExpression();  
+			break;
+ 
+    case 406 : if (DEBUG) { System.out.println("InsideCastExpression ::="); }  //$NON-NLS-1$
+		    consumeInsideCastExpression();  
+			break;
+ 
+    case 407 : if (DEBUG) { System.out.println("InsideCastExpressionLL1 ::="); }  //$NON-NLS-1$
+		    consumeInsideCastExpressionLL1();  
+			break;
+ 
+    case 408 : if (DEBUG) { System.out.println("InsideCastExpressionWithQualifiedGenerics ::="); }  //$NON-NLS-1$
+		    consumeInsideCastExpressionWithQualifiedGenerics();  
+			break;
+ 
+    case 410 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.MULTIPLY);  
+			break;
+ 
+    case 411 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.DIVIDE);  
+			break;
+ 
+    case 412 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.REMAINDER);  
+			break;
+ 
+    case 414 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression PLUS..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.PLUS);  
+			break;
+ 
+    case 415 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression MINUS..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.MINUS);  
+			break;
+ 
+    case 417 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.LEFT_SHIFT);  
+			break;
+ 
+    case 418 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.RIGHT_SHIFT);  
+			break;
+ 
+    case 419 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT);  
+			break;
+ 
+    case 421 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.LESS);  
+			break;
+ 
+    case 422 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression GREATER..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.GREATER);  
+			break;
+ 
+    case 423 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL"); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.LESS_EQUAL);  
+			break;
+ 
+    case 424 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.GREATER_EQUAL);  
+			break;
+ 
+    case 426 : if (DEBUG) { System.out.println("InstanceofExpression ::= InstanceofExpression instanceof"); }  //$NON-NLS-1$
+		    consumeInstanceOfExpression(OperatorIds.INSTANCEOF);  
+			break;
+ 
+    case 428 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL..."); }  //$NON-NLS-1$
+		    consumeEqualityExpression(OperatorIds.EQUAL_EQUAL);  
+			break;
+ 
+    case 429 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL..."); }  //$NON-NLS-1$
+		    consumeEqualityExpression(OperatorIds.NOT_EQUAL);  
+			break;
+ 
+    case 431 : if (DEBUG) { System.out.println("AndExpression ::= AndExpression AND EqualityExpression"); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.AND);  
+			break;
+ 
+    case 433 : if (DEBUG) { System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.XOR);  
+			break;
+ 
+    case 435 : if (DEBUG) { System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.OR);  
+			break;
+ 
+    case 437 : if (DEBUG) { System.out.println("ConditionalAndExpression ::= ConditionalAndExpression..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.AND_AND);  
+			break;
+ 
+    case 439 : if (DEBUG) { System.out.println("ConditionalOrExpression ::= ConditionalOrExpression..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.OR_OR);  
+			break;
+ 
+    case 441 : if (DEBUG) { System.out.println("ConditionalExpression ::= ConditionalOrExpression..."); }  //$NON-NLS-1$
+		    consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ;  
+			break;
+ 
+    case 444 : if (DEBUG) { System.out.println("Assignment ::= PostfixExpression AssignmentOperator..."); }  //$NON-NLS-1$
+		    consumeAssignment();  
+			break;
+ 
+    case 446 : if (DEBUG) { System.out.println("Assignment ::= InvalidArrayInitializerAssignement"); }  //$NON-NLS-1$
+		    ignoreExpressionAssignment(); 
+			break;
+ 
+    case 447 : if (DEBUG) { System.out.println("AssignmentOperator ::= EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(EQUAL);  
+			break;
+ 
+    case 448 : if (DEBUG) { System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(MULTIPLY);  
+			break;
+ 
+    case 449 : if (DEBUG) { System.out.println("AssignmentOperator ::= DIVIDE_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(DIVIDE);  
+			break;
+ 
+    case 450 : if (DEBUG) { System.out.println("AssignmentOperator ::= REMAINDER_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(REMAINDER);  
+			break;
+ 
+    case 451 : if (DEBUG) { System.out.println("AssignmentOperator ::= PLUS_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(PLUS);  
+			break;
+ 
+    case 452 : if (DEBUG) { System.out.println("AssignmentOperator ::= MINUS_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(MINUS);  
+			break;
+ 
+    case 453 : if (DEBUG) { System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(LEFT_SHIFT);  
+			break;
+ 
+    case 454 : if (DEBUG) { System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(RIGHT_SHIFT);  
+			break;
+ 
+    case 455 : if (DEBUG) { System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT);  
+			break;
+ 
+    case 456 : if (DEBUG) { System.out.println("AssignmentOperator ::= AND_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(AND);  
+			break;
+ 
+    case 457 : if (DEBUG) { System.out.println("AssignmentOperator ::= XOR_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(XOR);  
+			break;
+ 
+    case 458 : if (DEBUG) { System.out.println("AssignmentOperator ::= OR_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(OR);  
+			break;
+ 
+    case 462 : if (DEBUG) { System.out.println("Expressionopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyExpression();  
+			break;
+ 
+    case 467 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyClassBodyDeclarationsopt();  
+			break;
+ 
+    case 468 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
+		    consumeClassBodyDeclarationsopt();  
+			break;
+ 
+     case 469 : if (DEBUG) { System.out.println("Modifiersopt ::="); }  //$NON-NLS-1$
+		    consumeDefaultModifiers();  
+			break;
+ 
+    case 470 : if (DEBUG) { System.out.println("Modifiersopt ::= Modifiers"); }  //$NON-NLS-1$
+		    consumeModifiers();  
+			break;
+ 
+    case 471 : if (DEBUG) { System.out.println("BlockStatementsopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyBlockStatementsopt();  
+			break;
+ 
+     case 473 : if (DEBUG) { System.out.println("Dimsopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyDimsopt();  
+			break;
+ 
+     case 475 : if (DEBUG) { System.out.println("ArgumentListopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyArgumentListopt();  
+			break;
+ 
+    case 479 : if (DEBUG) { System.out.println("FormalParameterListopt ::="); }  //$NON-NLS-1$
+		    consumeFormalParameterListopt();  
+			break;
+ 
+     case 483 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyInterfaceMemberDeclarationsopt();  
+			break;
+ 
+     case 484 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
+		    consumeInterfaceMemberDeclarationsopt();  
+			break;
+ 
+    case 485 : if (DEBUG) { System.out.println("NestedType ::="); }  //$NON-NLS-1$
+		    consumeNestedType();  
+			break;
 
-	case 426 : // System.out.println("ForInitopt ::=");  //$NON-NLS-1$
-		consumeEmptyForInitopt();  
-		break ;
-		
-	case 428 : // System.out.println("ForUpdateopt ::=");  //$NON-NLS-1$
-		consumeEmptyForUpdateopt();  
-		break ;
-		
-	case 432 : // System.out.println("Catchesopt ::=");  //$NON-NLS-1$
-		consumeEmptyCatchesopt();  
-		break ;
-		
+     case 486 : if (DEBUG) { System.out.println("ForInitopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyForInitopt();  
+			break;
+ 
+     case 488 : if (DEBUG) { System.out.println("ForUpdateopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyForUpdateopt();  
+			break;
+ 
+     case 492 : if (DEBUG) { System.out.println("Catchesopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyCatchesopt();  
+			break;
+ 
+     case 494 : if (DEBUG) { System.out.println("EnumDeclaration ::= EnumHeader EnumBody"); }  //$NON-NLS-1$
+		    consumeEnumDeclaration();  
+			break;
+ 
+     case 495 : if (DEBUG) { System.out.println("EnumHeader ::= EnumHeaderName ClassHeaderImplementsopt"); }  //$NON-NLS-1$
+		    consumeEnumHeader();  
+			break;
+ 
+     case 496 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier"); }  //$NON-NLS-1$
+		    consumeEnumHeaderName();  
+			break;
+ 
+     case 497 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumBodyDeclarationsopt RBRACE"); }  //$NON-NLS-1$
+		    consumeEnumBodyNoConstants();  
+			break;
+ 
+     case 498 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE COMMA EnumBodyDeclarationsopt..."); }  //$NON-NLS-1$
+		    consumeEnumBodyNoConstants();  
+			break;
+ 
+     case 499 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants COMMA..."); }  //$NON-NLS-1$
+		    consumeEnumBodyWithConstants();  
+			break;
+ 
+     case 500 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants..."); }  //$NON-NLS-1$
+		    consumeEnumBodyWithConstants();  
+			break;
+ 
+    case 502 : if (DEBUG) { System.out.println("EnumConstants ::= EnumConstants COMMA EnumConstant"); }  //$NON-NLS-1$
+		    consumeEnumConstants();  
+			break;
+ 
+    case 503 : if (DEBUG) { System.out.println("EnumConstantHeaderName ::= Modifiersopt Identifier"); }  //$NON-NLS-1$
+		    consumeEnumConstantHeaderName();  
+			break;
+ 
+    case 504 : if (DEBUG) { System.out.println("EnumConstantHeader ::= EnumConstantHeaderName..."); }  //$NON-NLS-1$
+		    consumeEnumConstantHeader();  
+			break;
+ 
+    case 505 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader ForceNoDiet..."); }  //$NON-NLS-1$
+		    consumeEnumConstantWithClassBody();  
+			break;
+ 
+    case 506 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader"); }  //$NON-NLS-1$
+		    consumeEnumConstantNoClassBody();  
+			break;
+ 
+    case 507 : if (DEBUG) { System.out.println("Arguments ::= LPAREN ArgumentListopt RPAREN"); }  //$NON-NLS-1$
+		    consumeArguments();  
+			break;
+ 
+    case 508 : if (DEBUG) { System.out.println("Argumentsopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyArguments();  
+			break;
+ 
+    case 510 : if (DEBUG) { System.out.println("EnumDeclarations ::= SEMICOLON ClassBodyDeclarationsopt"); }  //$NON-NLS-1$
+		    consumeEnumDeclarations();  
+			break;
+ 
+    case 511 : if (DEBUG) { System.out.println("EnumBodyDeclarationsopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyEnumDeclarations();  
+			break;
+ 
+    case 513 : if (DEBUG) { System.out.println("EnhancedForStatement ::= EnhancedForStatementHeader..."); }  //$NON-NLS-1$
+		    consumeEnhancedForStatement();  
+			break;
+ 
+    case 514 : if (DEBUG) { System.out.println("EnhancedForStatementNoShortIf ::=..."); }  //$NON-NLS-1$
+		    consumeEnhancedForStatement();  
+			break;
+ 
+    case 515 : if (DEBUG) { System.out.println("EnhancedForStatementHeader ::= for LPAREN Type..."); }  //$NON-NLS-1$
+		    consumeEnhancedForStatementHeader(false);  
+			break;
+ 
+    case 516 : if (DEBUG) { System.out.println("EnhancedForStatementHeader ::= for LPAREN Modifiers Type"); }  //$NON-NLS-1$
+		    consumeEnhancedForStatementHeader(true);  
+			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(OperatorIds.INSTANCEOF);  
+			break;
+ 
+    case 620 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::=..."); }  //$NON-NLS-1$
+		    consumeInstanceOfExpression(OperatorIds.INSTANCEOF);  
+			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 647 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); }  //$NON-NLS-1$
+		    consumeAnnotationTypeDeclarationHeaderName() ;  
+			break;
+ 
+    case 648 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); }  //$NON-NLS-1$
+		    consumeAnnotationTypeDeclarationHeaderName() ;  
+			break;
+ 
+    case 649 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeader ::=..."); }  //$NON-NLS-1$
+		    consumeAnnotationTypeDeclarationHeader() ;  
+			break;
+ 
+    case 650 : if (DEBUG) { System.out.println("AnnotationTypeDeclaration ::=..."); }  //$NON-NLS-1$
+		    consumeAnnotationTypeDeclaration() ;  
+			break;
+ 
+    case 652 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyAnnotationTypeMemberDeclarationsopt() ;  
+			break;
+ 
+    case 655 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarations ::=..."); }  //$NON-NLS-1$
+		    consumeAnnotationTypeMemberDeclarations() ;  
+			break;
+ 
+    case 656 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt..."); }  //$NON-NLS-1$
+		    consumeMethodHeaderNameWithTypeParameters(true);  
+			break;
+ 
+    case 657 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt Type..."); }  //$NON-NLS-1$
+		    consumeMethodHeaderName(true);  
+			break;
+ 
+    case 658 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyMethodHeaderDefaultValue() ;  
+			break;
+ 
+    case 659 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::= DefaultValue"); }  //$NON-NLS-1$
+		    consumeMethodHeaderDefaultValue();  
+			break;
+ 
+    case 660 : if (DEBUG) { System.out.println("AnnotationMethodHeader ::= AnnotationMethodHeaderName..."); }  //$NON-NLS-1$
+		    consumeMethodHeader();  
+			break;
+ 
+    case 661 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclaration ::=..."); }  //$NON-NLS-1$
+		    consumeAnnotationTypeMemberDeclaration() ;  
+			break;
+ 
+    case 669 : if (DEBUG) { System.out.println("AnnotationName ::= AT Name"); }  //$NON-NLS-1$
+		    consumeAnnotationName() ;  
+			break;
+ 
+    case 670 : if (DEBUG) { System.out.println("NormalAnnotation ::= AnnotationName LPAREN..."); }  //$NON-NLS-1$
+		    consumeNormalAnnotation() ;  
+			break;
+ 
+    case 671 : if (DEBUG) { System.out.println("MemberValuePairsopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyMemberValuePairsopt() ;  
+			break;
+ 
+    case 674 : if (DEBUG) { System.out.println("MemberValuePairs ::= MemberValuePairs COMMA..."); }  //$NON-NLS-1$
+		    consumeMemberValuePairs() ;  
+			break;
+ 
+    case 675 : if (DEBUG) { System.out.println("MemberValuePair ::= SimpleName EQUAL MemberValue"); }  //$NON-NLS-1$
+		    consumeMemberValuePair() ;  
+			break;
+ 
+    case 677 : if (DEBUG) { System.out.println("MemberValue ::= Name"); }  //$NON-NLS-1$
+		    consumeMemberValueAsName() ;  
+			break;
+ 
+    case 680 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::= LBRACE PushLeftBrace..."); }  //$NON-NLS-1$
+		    consumeMemberValueArrayInitializer() ;  
+			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$
+		    consumeEmptyMemberValueArrayInitializer() ;  
+			break;
+ 
+    case 683 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::= LBRACE PushLeftBrace..."); }  //$NON-NLS-1$
+		    consumeEmptyMemberValueArrayInitializer() ;  
+			break;
+ 
+    case 685 : if (DEBUG) { System.out.println("MemberValues ::= MemberValues COMMA MemberValue"); }  //$NON-NLS-1$
+		    consumeMemberValues() ;  
+			break;
+ 
+    case 686 : if (DEBUG) { System.out.println("MarkerAnnotation ::= AnnotationName"); }  //$NON-NLS-1$
+		    consumeMarkerAnnotation() ;  
+			break;
+ 
+    case 687 : if (DEBUG) { System.out.println("SingleMemberAnnotation ::= AnnotationName LPAREN..."); }  //$NON-NLS-1$
+		    consumeSingleMemberAnnotation() ;  
+			break;
+ 
+    case 688 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt TypeParameters"); }  //$NON-NLS-1$
+		    consumeRecoveryMethodHeaderNameWithTypeParameters();  
+			break;
+ 
+    case 689 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt Type..."); }  //$NON-NLS-1$
+		    consumeRecoveryMethodHeaderName();  
+			break;
+ 
+    case 690 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); }  //$NON-NLS-1$
+		    consumeMethodHeader();  
+			break;
+ 
+    case 691 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); }  //$NON-NLS-1$
+		    consumeMethodHeader();  
+			break;
+ 
 	}
 } 
 protected void consumeSimpleAssertStatement() {
@@ -3494,23 +6129,82 @@
 	this.expressionLengthPtr--;
 	pushOnAstStack(new AssertStatement(this.expressionStack[this.expressionPtr--], this.intStack[this.intPtr--]));	
 }
+protected void consumeSingleMemberAnnotation() {
+	// SingleMemberAnnotation ::= '@' Name '(' MemberValue ')'
+	SingleMemberAnnotation singleMemberAnnotation = null;
+	int length = this.identifierLengthStack[this.identifierLengthPtr--];
+	TypeReference typeReference;
+	if (length == 1) {
+		typeReference = new SingleTypeReference(
+				this.identifierStack[this.identifierPtr], 
+				this.identifierPositionStack[this.identifierPtr--]);
+	} else {
+		char[][] tokens = new char[length][];
+		this.identifierPtr -= length;
+		long[] positions = new long[length];
+		System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+		System.arraycopy(
+			this.identifierPositionStack, 
+			this.identifierPtr + 1, 
+			positions, 
+			0, 
+			length);
+		typeReference = new QualifiedTypeReference(tokens, positions);
+	}
+	singleMemberAnnotation = new SingleMemberAnnotation(typeReference, this.intStack[this.intPtr--]);
+	singleMemberAnnotation.memberValue = this.expressionStack[this.expressionPtr--];
+	this.expressionLengthPtr--;
+	int sourceStart = singleMemberAnnotation.sourceStart;
+	if (this.modifiersSourceStart < 0) {
+		this.modifiersSourceStart = sourceStart;
+	} else if (this.modifiersSourceStart > sourceStart) {
+		this.modifiersSourceStart = sourceStart;
+	}
+	singleMemberAnnotation.declarationSourceEnd = this.rParenPos;
+	pushOnExpressionStack(singleMemberAnnotation);
+	if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+			this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+		this.problemReporter().invalidUsageOfAnnotation(singleMemberAnnotation);
+	}
+}
+protected void consumeSingleStaticImportDeclarationName() {
+	// SingleTypeImportDeclarationName ::= 'import' 'static' Name
+	/* push an ImportRef build from the last name 
+	stored in the identifier stack. */
+
+	ImportReference impt;
+	int length;
+	char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
+	this.identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+	System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
+	pushOnAstStack(impt = new ImportReference(tokens, positions, false, AccStatic));
+
+	this.modifiers = AccDefault;
+	this.modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int)
 	
-protected void consumeSingleTypeImportDeclaration() {
-	// SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName ';'
+	if (this.currentToken == TokenNameSEMICOLON){
+		impt.declarationSourceEnd = this.scanner.currentPosition - 1;
+	} else {
+		impt.declarationSourceEnd = impt.sourceEnd;
+	}
+	impt.declarationEnd = impt.declarationSourceEnd;
+	//this.endPosition is just before the ;
+	impt.declarationSourceStart = this.intStack[this.intPtr--];
 
-	ImportReference impt = (ImportReference) this.astStack[this.astPtr];
-	// flush comments defined prior to import statements
-	impt.declarationEnd = this.endStatementPosition;
-	impt.declarationSourceEnd = 
-		this.flushCommentsDefinedPriorTo(impt.declarationSourceEnd); 
-
+	if(this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
+			this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+		impt.modifiers = AccDefault; // convert the static import reference to a non-static importe reference
+		this.problemReporter().invalidUsageOfStaticImports(impt);
+	}
+	
 	// recovery
-	if (this.currentElement != null) {
-		this.lastCheckPoint = impt.declarationSourceEnd + 1;
+	if (this.currentElement != null){
+		this.lastCheckPoint = impt.declarationSourceEnd+1;
 		this.currentElement = this.currentElement.add(impt, 0);
 		this.lastIgnoredToken = -1;
-		this.restartRecovery = true; 
-		// used to avoid branching back into the regular automaton
+		this.restartRecovery = true; // used to avoid branching back into the regular automaton		
 	}
 }
 protected void consumeSingleTypeImportDeclarationName() {
@@ -3533,7 +6227,7 @@
 		impt.declarationSourceEnd = impt.sourceEnd;
 	}
 	impt.declarationEnd = impt.declarationSourceEnd;
-	//endPosition is just before the ;
+	//this.endPosition is just before the ;
 	impt.declarationSourceStart = this.intStack[this.intPtr--];
 
 	// recovery
@@ -3546,13 +6240,13 @@
 }
 protected void consumeStatementBreak() {
 	// BreakStatement ::= 'break' ';'
-	// break pushs a position on intStack in case there is no label
+	// break pushs a position on this.intStack in case there is no label
 
 	pushOnAstStack(new BreakStatement(null, this.intStack[this.intPtr--], this.endPosition));
 }
 protected void consumeStatementBreakWithLabel() {
 	// BreakStatement ::= 'break' Identifier ';'
-	// break pushs a position on intStack in case there is no label
+	// break pushs a position on this.intStack in case there is no label
 
 	pushOnAstStack(
 		new BreakStatement(
@@ -3575,7 +6269,7 @@
 }
 protected void consumeStatementContinue() {
 	// ContinueStatement ::= 'continue' ';'
-	// continue pushs a position on intStack in case there is no label
+	// continue pushs a position on this.intStack in case there is no label
 
 	pushOnAstStack(
 		new ContinueStatement(
@@ -3585,7 +6279,7 @@
 }
 protected void consumeStatementContinueWithLabel() {
 	// ContinueStatement ::= 'continue' Identifier ';'
-	// continue pushs a position on intStack in case there is no label
+	// continue pushs a position on this.intStack in case there is no label
 
 	pushOnAstStack(
 		new ContinueStatement(
@@ -3597,7 +6291,7 @@
 protected void consumeStatementDo() {
 	// DoStatement ::= 'do' Statement 'while' '(' Expression ')' ';'
 
-	//the 'while' pushes a value on intStack that we need to remove
+	//the 'while' pushes a value on this.intStack that we need to remove
 	this.intPtr--;
 
 	Statement statement = (Statement) this.astStack[this.astPtr];
@@ -3647,7 +6341,7 @@
 		inits = null;
 		scope = false;
 	} else {
-		if (length == -1) { //on expressionStack
+		if (length == -1) { //on this.expressionStack
 			scope = false;
 			length = this.expressionLengthStack[this.expressionLengthPtr--];
 			this.expressionPtr -= length;
@@ -3657,7 +6351,7 @@
 				inits = new Statement[length], 
 				0, 
 				length); 
-		} else { //on astStack
+		} else { //on this.astStack
 			this.astPtr -= length;
 			System.arraycopy(
 				this.astStack, 
@@ -3724,7 +6418,7 @@
 }
 protected void consumeStatementReturn() {
 	// ReturnStatement ::= 'return' Expressionopt ';'
-	// return pushs a position on intStack in case there is no expression
+	// return pushs a position on this.intStack in case there is no expression
 
 	if (this.expressionLengthStack[this.expressionLengthPtr--] != 0) {
 		pushOnAstStack(
@@ -3842,6 +6536,46 @@
 			this.intStack[this.intPtr--], 
 			this.endStatementPosition); 
 }
+protected void consumeStaticImportOnDemandDeclarationName() {
+	// TypeImportOnDemandDeclarationName ::= 'import' 'static' Name '.' '*'
+	/* push an ImportRef build from the last name 
+	stored in the identifier stack. */
+
+	ImportReference impt;
+	int length;
+	char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
+	this.identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+	System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
+	pushOnAstStack(impt = new ImportReference(tokens, positions, true, AccStatic));
+
+	this.modifiers = AccDefault;
+	this.modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int)
+	
+	if (this.currentToken == TokenNameSEMICOLON){
+		impt.declarationSourceEnd = this.scanner.currentPosition - 1;
+	} else {
+		impt.declarationSourceEnd = impt.sourceEnd;
+	}
+	impt.declarationEnd = impt.declarationSourceEnd;
+	//this.endPosition is just before the ;
+	impt.declarationSourceStart = this.intStack[this.intPtr--];
+
+	if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+			this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+		impt.modifiers = AccDefault; // convert the static import reference to a non-static importe reference
+		this.problemReporter().invalidUsageOfStaticImports(impt);
+	}
+	
+	// recovery
+	if (this.currentElement != null){
+		this.lastCheckPoint = impt.declarationSourceEnd+1;
+		this.currentElement = this.currentElement.add(impt, 0);
+		this.lastIgnoredToken = -1;
+		this.restartRecovery = true; // used to avoid branching back into the regular automaton		
+	}	
+}
 protected void consumeStaticInitializer() {
 	// StaticInitializer ::=  StaticOnly Block
 	//push an Initializer
@@ -3927,110 +6661,115 @@
 	switch (type) {
 		case TokenNameIdentifier :
 			pushIdentifier();
-			if (this.scanner.useAssertAsAnIndentifier) {
+			if (this.scanner.useAssertAsAnIndentifier  &&
+					this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
 				long positions = this.identifierPositionStack[this.identifierPtr];
 				problemReporter().useAssertAsAnIdentifier((int) (positions >>> 32), (int) positions);
 			}
-//			this.scanner.commentPtr = -1;
+			if (this.scanner.useEnumAsAnIndentifier  &&
+					this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+				long positions = this.identifierPositionStack[this.identifierPtr];
+				problemReporter().useEnumAsAnIdentifier((int) (positions >>> 32), (int) positions);
+			}
 			break;
 		case TokenNameinterface :
-			adjustInterfaceModifiers();
 			//'class' is pushing two int (positions) on the stack ==> 'interface' needs to do it too....
 			pushOnIntStack(this.scanner.currentPosition - 1);			
 			pushOnIntStack(this.scanner.startPosition);
-//			this.scanner.commentPtr = -1;
 			break;
 		case TokenNameabstract :
 			checkAndSetModifiers(AccAbstract);
+			pushOnExpressionStackLengthStack(0);
 			break;
 		case TokenNamestrictfp :
 			checkAndSetModifiers(AccStrictfp);
+			pushOnExpressionStackLengthStack(0);
 			break;
 		case TokenNamefinal :
 			checkAndSetModifiers(AccFinal);
+			pushOnExpressionStackLengthStack(0);
 			break;
 		case TokenNamenative :
 			checkAndSetModifiers(AccNative);
+			pushOnExpressionStackLengthStack(0);
 			break;
 		case TokenNameprivate :
 			checkAndSetModifiers(AccPrivate);
+			pushOnExpressionStackLengthStack(0);
 			break;
 		case TokenNameprotected :
 			checkAndSetModifiers(AccProtected);
+			pushOnExpressionStackLengthStack(0);
 			break;
 		case TokenNamepublic :
 			checkAndSetModifiers(AccPublic);
+			pushOnExpressionStackLengthStack(0);
 			break;
 		case TokenNametransient :
 			checkAndSetModifiers(AccTransient);
+			pushOnExpressionStackLengthStack(0);
 			break;
 		case TokenNamevolatile :
 			checkAndSetModifiers(AccVolatile);
+			pushOnExpressionStackLengthStack(0);
 			break;
 		case TokenNamestatic :
 			checkAndSetModifiers(AccStatic);
+			pushOnExpressionStackLengthStack(0);
 			break;
 		case TokenNamesynchronized :
 			this.synchronizedBlockSourceStart = this.scanner.startPosition;	
 			checkAndSetModifiers(AccSynchronized);
+			pushOnExpressionStackLengthStack(0);
 			break;
 			//==============================
 		case TokenNamevoid :
 			pushIdentifier(-T_void);
 			pushOnIntStack(this.scanner.currentPosition - 1);				
 			pushOnIntStack(this.scanner.startPosition);
-//			this.scanner.commentPtr = -1;
 			break;
 			//push a default dimension while void is not part of the primitive
 			//declaration baseType and so takes the place of a type without getting into
-			//regular type parsing that generates a dimension on intStack
+			//regular type parsing that generates a dimension on this.intStack
 		case TokenNameboolean :
 			pushIdentifier(-T_boolean);
 			pushOnIntStack(this.scanner.currentPosition - 1);				
 			pushOnIntStack(this.scanner.startPosition);		
-//			this.scanner.commentPtr = -1;
 			break;
 		case TokenNamebyte :
 			pushIdentifier(-T_byte);
 			pushOnIntStack(this.scanner.currentPosition - 1);				
 			pushOnIntStack(this.scanner.startPosition);					
-//			this.scanner.commentPtr = -1;
 			break;
 		case TokenNamechar :
 			pushIdentifier(-T_char);
 			pushOnIntStack(this.scanner.currentPosition - 1);				
 			pushOnIntStack(this.scanner.startPosition);					
-//			this.scanner.commentPtr = -1;
 			break;
 		case TokenNamedouble :
 			pushIdentifier(-T_double);
 			pushOnIntStack(this.scanner.currentPosition - 1);				
 			pushOnIntStack(this.scanner.startPosition);					
-//			this.scanner.commentPtr = -1;
 			break;
 		case TokenNamefloat :
 			pushIdentifier(-T_float);
 			pushOnIntStack(this.scanner.currentPosition - 1);				
 			pushOnIntStack(this.scanner.startPosition);					
-//			this.scanner.commentPtr = -1;
 			break;
 		case TokenNameint :
 			pushIdentifier(-T_int);
 			pushOnIntStack(this.scanner.currentPosition - 1);				
 			pushOnIntStack(this.scanner.startPosition);					
-//			this.scanner.commentPtr = -1;
 			break;
 		case TokenNamelong :
 			pushIdentifier(-T_long);
 			pushOnIntStack(this.scanner.currentPosition - 1);				
 			pushOnIntStack(this.scanner.startPosition);					
-//			this.scanner.commentPtr = -1;
 			break;
 		case TokenNameshort :
 			pushIdentifier(-T_short);
 			pushOnIntStack(this.scanner.currentPosition - 1);				
 			pushOnIntStack(this.scanner.startPosition);					
-//			this.scanner.commentPtr = -1;
 			break;
 			//==============================
 		case TokenNameIntegerLiteral :
@@ -4039,7 +6778,6 @@
 					this.scanner.getCurrentTokenSource(), 
 					this.scanner.startPosition, 
 					this.scanner.currentPosition - 1)); 
-//			this.scanner.commentPtr = -1;
 			break;
 		case TokenNameLongLiteral :
 			pushOnExpressionStack(
@@ -4047,7 +6785,6 @@
 					this.scanner.getCurrentTokenSource(), 
 					this.scanner.startPosition, 
 					this.scanner.currentPosition - 1)); 
-//			this.scanner.commentPtr = -1;
 			break;
 		case TokenNameFloatingPointLiteral :
 			pushOnExpressionStack(
@@ -4055,7 +6792,6 @@
 					this.scanner.getCurrentTokenSource(), 
 					this.scanner.startPosition, 
 					this.scanner.currentPosition - 1)); 
-//			this.scanner.commentPtr = -1;
 			break;
 		case TokenNameDoubleLiteral :
 			pushOnExpressionStack(
@@ -4063,7 +6799,6 @@
 					this.scanner.getCurrentTokenSource(), 
 					this.scanner.startPosition, 
 					this.scanner.currentPosition - 1)); 
-//			this.scanner.commentPtr = -1;
 			break;
 		case TokenNameCharacterLiteral :
 			pushOnExpressionStack(
@@ -4071,7 +6806,6 @@
 					this.scanner.getCurrentTokenSource(), 
 					this.scanner.startPosition, 
 					this.scanner.currentPosition - 1)); 
-//			this.scanner.commentPtr = -1;
 			break;
 		case TokenNameStringLiteral :
 			StringLiteral stringLiteral = new StringLiteral(
@@ -4079,12 +6813,10 @@
 					this.scanner.startPosition, 
 					this.scanner.currentPosition - 1); 
 			pushOnExpressionStack(stringLiteral); 
-//			this.scanner.commentPtr = -1;
 			break;
 		case TokenNamefalse :
 			pushOnExpressionStack(
 				new FalseLiteral(this.scanner.startPosition, this.scanner.currentPosition - 1)); 
-//			this.scanner.commentPtr = -1;
 			break;
 		case TokenNametrue :
 			pushOnExpressionStack(
@@ -4125,16 +6857,24 @@
 			pushOnIntStack(this.scanner.currentPosition - 1);
 			pushOnIntStack(this.scanner.startPosition);
 			break;
+		case TokenNameenum :
+			pushOnIntStack(this.scanner.currentPosition - 1);
+			pushOnIntStack(this.scanner.startPosition);
+			break;
 		case TokenNamedefault :
 			pushOnIntStack(this.scanner.startPosition);
 			pushOnIntStack(this.scanner.currentPosition - 1);
 			break;
 			//let extra semantic action decide when to push
 		case TokenNameRBRACKET :
+			this.endPosition = this.scanner.startPosition;
+			this.endStatementPosition = this.scanner.currentPosition - 1;
+			break;
 		case TokenNamePLUS :
 		case TokenNameMINUS :
 		case TokenNameNOT :
 		case TokenNameTWIDDLE :
+		case TokenNameLBRACE :
 			this.endPosition = this.scanner.startPosition;
 			break;
 		case TokenNamePLUS_PLUS :
@@ -4148,14 +6888,26 @@
 			this.endPosition = this.scanner.startPosition - 1; 
 			//the item is not part of the potential futur expression/statement
 			break;
-			// in order to handle ( expression) ////// (cast)expression///// foo(x)
 		case TokenNameRPAREN :
+			// in order to handle ( expression) ////// (cast)expression///// foo(x)
 			this.rParenPos = this.scanner.currentPosition - 1; // position of the end of right parenthesis (in case of unicode \u0029) lex00101
 			break;
 		case TokenNameLPAREN :
 			this.lParenPos = this.scanner.startPosition;
 			break;
-			//  case TokenNameQUESTION  :
+		case TokenNameAT :
+			pushOnIntStack(this.scanner.startPosition);
+			break;
+		case TokenNameQUESTION  :
+			pushOnIntStack(this.scanner.startPosition);
+			pushOnIntStack(this.scanner.currentPosition - 1);
+			break;
+		case TokenNameLESS :
+			pushOnIntStack(this.scanner.startPosition);
+			break;
+		case TokenNameELLIPSIS :
+			pushOnIntStack(this.scanner.currentPosition - 1);
+			break;			
 			//  case TokenNameCOMMA :
 			//  case TokenNameCOLON  :
 			//  case TokenNameEQUAL  :
@@ -4198,39 +6950,49 @@
 			//  case TokenNameOR  :
 			//  case TokenNameDIVIDE :
 			//  case TokenNameGREATER  :
-			//  case TokenNameLESS  :
+	}
+}
+protected void consumeTypeArgument() {
+	pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--]));	
+}
+protected void consumeTypeArgumentList() {
+	concatGenericsLists();
+}
+protected void consumeTypeArgumentList1() {
+	concatGenericsLists();
+}
+protected void consumeTypeArgumentList2() {
+	concatGenericsLists();
+}
+protected void consumeTypeArgumentList3() {
+	concatGenericsLists();
+}
+protected void consumeTypeArgumentReferenceType1() {
+	concatGenericsLists();
+	pushOnGenericsStack(getTypeReference(0));	
+	intPtr--;
+}
+protected void consumeTypeArgumentReferenceType2() {
+	concatGenericsLists();
+	pushOnGenericsStack(getTypeReference(0));	
+	intPtr--;
+}
+protected void consumeTypeArguments() {
+	concatGenericsLists();
+	intPtr--;
+
+	if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+			this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+		int length = this.genericsLengthStack[this.genericsLengthPtr];
+		this.problemReporter().invalidUsageOfTypeArguments(
+			(TypeReference)this.genericsStack[this.genericsPtr - length + 1],
+			(TypeReference)this.genericsStack[this.genericsPtr]);
 	}
 }
 protected void consumeTypeDeclarations() {
 	// TypeDeclarations ::= TypeDeclarations TypeDeclaration
 	concatNodeLists();
 }
-protected void consumeTypeDeclarationsopt() {
-	// TypeDeclarationsopt ::= TypeDeclarations
-	int length;
-	if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
-		this.astPtr -= length;
-		System.arraycopy(this.astStack, this.astPtr + 1, this.compilationUnit.types = new TypeDeclaration[length], 0, length);
-	}
-}
-protected void consumeTypeImportOnDemandDeclaration() {
-	// TypeImportOnDemandDeclaration ::= TypeImportOnDemandDeclarationName ';'
-
-	ImportReference impt = (ImportReference) this.astStack[this.astPtr];
-	// flush comments defined prior to import statements
-	impt.declarationEnd = this.endStatementPosition;
-	impt.declarationSourceEnd = 
-		this.flushCommentsDefinedPriorTo(impt.declarationSourceEnd); 
-
-	// recovery
-	if (this.currentElement != null) {
-		this.lastCheckPoint = impt.declarationSourceEnd + 1;
-		this.currentElement = this.currentElement.add(impt, 0);
-		this.restartRecovery = true;
-		this.lastIgnoredToken = -1;
-		// used to avoid branching back into the regular automaton
-	}
-}
 protected void consumeTypeImportOnDemandDeclarationName() {
 	// TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
 	/* push an ImportRef build from the last name 
@@ -4251,7 +7013,7 @@
 		impt.declarationSourceEnd = impt.sourceEnd;
 	}
 	impt.declarationEnd = impt.declarationSourceEnd;
-	//endPosition is just before the ;
+	//this.endPosition is just before the ;
 	impt.declarationSourceStart = this.intStack[this.intPtr--];
 
 	// recovery
@@ -4262,6 +7024,93 @@
 		this.restartRecovery = true; // used to avoid branching back into the regular automaton		
 	}	
 }
+protected void consumeTypeParameterHeader() {
+	//TypeParameterHeader ::= Identifier
+	TypeParameter typeParameter = new TypeParameter();
+	long pos = this.identifierPositionStack[this.identifierPtr];
+	final int end = (int) pos;
+	typeParameter.declarationSourceEnd = end;
+	typeParameter.sourceEnd = end;
+	final int start = (int) (pos >>> 32);
+	typeParameter.declarationSourceStart = start;
+	typeParameter.sourceStart = start;
+	typeParameter.name = this.identifierStack[this.identifierPtr--];
+	this.identifierLengthPtr--;
+	pushOnGenericsStack(typeParameter);
+	
+	this.listTypeParameterLength++;
+}
+protected void consumeTypeParameter1() {
+	// nothing to do
+}
+protected void consumeTypeParameter1WithExtends() {
+	//TypeParameter1 ::= TypeParameterHeader 'extends' ReferenceType1
+	TypeReference superType = (TypeReference) this.genericsStack[this.genericsPtr--];
+	this.genericsLengthPtr--;
+	TypeParameter typeParameter = (TypeParameter) this.genericsStack[this.genericsPtr];
+	typeParameter.declarationSourceEnd = superType.sourceEnd;
+	typeParameter.type = superType;
+	superType.bits |= ASTNode.IsSuperType;
+	this.genericsStack[this.genericsPtr] = typeParameter;
+}
+protected void consumeTypeParameter1WithExtendsAndBounds() {
+	//TypeParameter1 ::= TypeParameterHeader 'extends' ReferenceType AdditionalBoundList1
+	int additionalBoundsLength = this.genericsLengthStack[this.genericsLengthPtr--];
+	TypeReference[] bounds = new TypeReference[additionalBoundsLength];
+	this.genericsPtr -= additionalBoundsLength;
+	System.arraycopy(this.genericsStack, this.genericsPtr + 1, bounds, 0, additionalBoundsLength);
+	TypeReference superType = getTypeReference(this.intStack[this.intPtr--]);
+	TypeParameter typeParameter = (TypeParameter) this.genericsStack[this.genericsPtr];
+	typeParameter.declarationSourceEnd = bounds[additionalBoundsLength - 1].sourceEnd;
+	typeParameter.type = superType;
+	superType.bits |= ASTNode.IsSuperType;	
+	typeParameter.bounds = bounds;
+	for (int i = 0, max = bounds.length; i < max; i++) {
+		bounds[i].bits |= ASTNode.IsSuperType;
+	}	
+}
+protected void consumeTypeParameterList() {
+	//TypeParameterList ::= TypeParameterList ',' TypeParameter
+	concatGenericsLists();
+}
+protected void consumeTypeParameterList1() {
+	//TypeParameterList1 ::= TypeParameterList ',' TypeParameter1
+	concatGenericsLists();
+}
+protected void consumeTypeParameters() {
+	intPtr--;
+	if(options.sourceLevel < ClassFileConstants.JDK1_5&&
+			this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+		int length = this.genericsLengthStack[this.genericsLengthPtr];
+		this.problemReporter().invalidUsageOfTypeParameters(
+			(TypeParameter) this.genericsStack[genericsPtr - length + 1],
+			(TypeParameter) this.genericsStack[genericsPtr]);
+	}
+}
+protected void consumeTypeParameterWithExtends() {
+	//TypeParameter ::= TypeParameterHeader 'extends' ReferenceType
+	TypeReference superType = getTypeReference(this.intStack[this.intPtr--]);
+	TypeParameter typeParameter = (TypeParameter) this.genericsStack[this.genericsPtr];
+	typeParameter.declarationSourceEnd = superType.sourceEnd;
+	typeParameter.type = superType;
+	superType.bits |= ASTNode.IsSuperType;
+}
+protected void consumeTypeParameterWithExtendsAndBounds() {
+	//TypeParameter ::= TypeParameterHeader 'extends' ReferenceType AdditionalBoundList
+	int additionalBoundsLength = this.genericsLengthStack[this.genericsLengthPtr--];
+	TypeReference[] bounds = new TypeReference[additionalBoundsLength];
+	this.genericsPtr -= additionalBoundsLength;
+	System.arraycopy(this.genericsStack, this.genericsPtr + 1, bounds, 0, additionalBoundsLength);
+	TypeReference superType = getTypeReference(this.intStack[this.intPtr--]);
+	TypeParameter typeParameter = (TypeParameter) this.genericsStack[this.genericsPtr];
+	typeParameter.type = superType;
+	superType.bits |= ASTNode.IsSuperType;
+	typeParameter.bounds = bounds;
+	typeParameter.declarationSourceEnd = bounds[additionalBoundsLength - 1].sourceEnd;
+	for (int i = 0, max = bounds.length; i < max; i++) {
+		bounds[i].bits |= ASTNode.IsSuperType;
+	}		
+}
 protected void consumeUnaryExpression(int op) {
 	// UnaryExpression ::= '+' PushPosition UnaryExpression
 	// UnaryExpression ::= '-' PushPosition UnaryExpression
@@ -4275,7 +7124,7 @@
 	//is Integer.MAX_VALUE+1.....)
 	//Same for -9223372036854775808L ............
 
-	//intStack have the position of the operator
+	//this.intStack have the position of the operator
 
 	Expression r, exp = this.expressionStack[this.expressionPtr];
 	if (op == MINUS) {
@@ -4301,7 +7150,7 @@
 	// ++ and -- operators
 	//optimize the push/pop
 
-	//intStack has the position of the operator when prefix
+	//this.intStack has the position of the operator when prefix
 
 	Expression leftHandSide = this.expressionStack[this.expressionPtr];
 	if (leftHandSide instanceof Reference) {
@@ -4337,6 +7186,114 @@
 	// VariableInitializers ::= VariableInitializers ',' VariableInitializer
 	concatExpressionLists();
 }
+protected void consumeWildcard() {
+	final Wildcard wildcard = new Wildcard(Wildcard.UNBOUND);
+	wildcard.sourceEnd = this.intStack[this.intPtr--];
+	wildcard.sourceStart = this.intStack[this.intPtr--];
+	pushOnGenericsStack(wildcard);
+}
+protected void consumeWildcard1() {
+	final Wildcard wildcard = new Wildcard(Wildcard.UNBOUND);
+	wildcard.sourceEnd = this.intStack[this.intPtr--];
+	wildcard.sourceStart = this.intStack[this.intPtr--];
+	pushOnGenericsStack(wildcard);
+}
+protected void consumeWildcard1WithBounds() {
+	// Nothing to do
+	// The wildcard is created by the consumeWildcardBounds1Extends or by consumeWildcardBounds1Super
+}
+protected void consumeWildcard2() {
+	final Wildcard wildcard = new Wildcard(Wildcard.UNBOUND);
+	wildcard.sourceEnd = this.intStack[this.intPtr--];
+	wildcard.sourceStart = this.intStack[this.intPtr--];
+	pushOnGenericsStack(wildcard);
+}
+protected void consumeWildcard2WithBounds() {
+	// Nothing to do
+	// The wildcard is created by the consumeWildcardBounds2Extends or by consumeWildcardBounds2Super
+}
+protected void consumeWildcard3() {
+	final Wildcard wildcard = new Wildcard(Wildcard.UNBOUND);
+	wildcard.sourceEnd = this.intStack[this.intPtr--];
+	wildcard.sourceStart = this.intStack[this.intPtr--];
+	pushOnGenericsStack(wildcard);
+}
+protected void consumeWildcard3WithBounds() {
+	// Nothing to do
+	// The wildcard is created by the consumeWildcardBounds3Extends or by consumeWildcardBounds3Super
+}
+protected void consumeWildcardBounds1Extends() {
+	Wildcard wildcard = new Wildcard(Wildcard.EXTENDS);
+	wildcard.bound = (TypeReference) this.genericsStack[this.genericsPtr];
+	wildcard.sourceEnd = wildcard.bound.sourceEnd;
+	this.intPtr--; // remove end position of the '?'
+	wildcard.sourceStart = this.intStack[this.intPtr--];
+	this.genericsStack[this.genericsPtr] = wildcard;
+}
+protected void consumeWildcardBounds1Super() {
+	Wildcard wildcard = new Wildcard(Wildcard.SUPER);
+	wildcard.bound = (TypeReference) this.genericsStack[this.genericsPtr];
+	this.intPtr--; // remove the starting position of the super keyword
+	wildcard.sourceEnd = wildcard.bound.sourceEnd;
+	this.intPtr--; // remove end position of the '?'
+	wildcard.sourceStart = this.intStack[this.intPtr--];
+	this.genericsStack[this.genericsPtr] = wildcard;
+}
+protected void consumeWildcardBounds2Extends() {
+	Wildcard wildcard = new Wildcard(Wildcard.EXTENDS);
+	wildcard.bound = (TypeReference) this.genericsStack[this.genericsPtr];
+	wildcard.sourceEnd = wildcard.bound.sourceEnd;
+	this.intPtr--; // remove end position of the '?'
+	wildcard.sourceStart = this.intStack[this.intPtr--];
+	this.genericsStack[this.genericsPtr] = wildcard;
+}
+protected void consumeWildcardBounds2Super() {
+	Wildcard wildcard = new Wildcard(Wildcard.SUPER);
+	wildcard.bound = (TypeReference) this.genericsStack[this.genericsPtr];
+	this.intPtr--; // remove the starting position of the super keyword
+	wildcard.sourceEnd = wildcard.bound.sourceEnd;
+	this.intPtr--; // remove end position of the '?'
+	wildcard.sourceStart = this.intStack[this.intPtr--];
+	this.genericsStack[this.genericsPtr] = wildcard;
+}
+protected void consumeWildcardBounds3Extends() {
+	Wildcard wildcard = new Wildcard(Wildcard.EXTENDS);
+	wildcard.bound = (TypeReference) this.genericsStack[this.genericsPtr];
+	wildcard.sourceEnd = wildcard.bound.sourceEnd;
+	this.intPtr--; // remove end position of the '?'
+	wildcard.sourceStart = this.intStack[this.intPtr--];
+	this.genericsStack[this.genericsPtr] = wildcard;
+}
+protected void consumeWildcardBounds3Super() {
+	Wildcard wildcard = new Wildcard(Wildcard.SUPER);
+	wildcard.bound = (TypeReference) this.genericsStack[this.genericsPtr];
+	this.intPtr--; // remove the starting position of the super keyword
+	wildcard.sourceEnd = wildcard.bound.sourceEnd;
+	this.intPtr--; // remove end position of the '?'
+	wildcard.sourceStart = this.intStack[this.intPtr--];
+	this.genericsStack[this.genericsPtr] = wildcard;
+}
+protected void consumeWildcardBoundsExtends() {
+	Wildcard wildcard = new Wildcard(Wildcard.EXTENDS);
+	wildcard.bound = getTypeReference(this.intStack[this.intPtr--]);
+	wildcard.sourceEnd = wildcard.bound.sourceEnd;
+	this.intPtr--; // remove end position of the '?'
+	wildcard.sourceStart = this.intStack[this.intPtr--];
+	pushOnGenericsStack(wildcard);
+}
+protected void consumeWildcardBoundsSuper() {
+	Wildcard wildcard = new Wildcard(Wildcard.SUPER);
+	wildcard.bound = getTypeReference(this.intStack[this.intPtr--]);
+	this.intPtr--; // remove the starting position of the super keyword
+	wildcard.sourceEnd = wildcard.bound.sourceEnd;
+	this.intPtr--; // remove end position of the '?'
+	wildcard.sourceStart = this.intStack[this.intPtr--];
+	pushOnGenericsStack(wildcard);
+}
+protected void consumeWildcardWithBounds() {
+	// Nothing to do
+	// The wildcard is created by the consumeWildcardBoundsExtends or by consumeWildcardBoundsSuper
+}
 /**
  * Given the current comment stack, answer whether some comment is available in a certain exclusive range
  * 
@@ -4358,6 +7315,7 @@
 }
 public MethodDeclaration convertToMethodDeclaration(ConstructorDeclaration c, CompilationResult compilationResult) {
 	MethodDeclaration m = new MethodDeclaration(compilationResult);
+	m.typeParameters = c.typeParameters;
 	m.sourceStart = c.sourceStart;
 	m.sourceEnd = c.sourceEnd;
 	m.bodyStart = c.bodyStart;
@@ -4367,6 +7325,7 @@
 	m.selector = c.selector;
 	m.statements = c.statements;
 	m.modifiers = c.modifiers;
+	m.annotations = c.annotations;
 	m.arguments = c.arguments;
 	m.thrownExceptions = c.thrownExceptions;
 	m.explicitDeclarations = c.explicitDeclarations;
@@ -4383,7 +7342,16 @@
 protected LocalDeclaration createLocalDeclaration(char[] localDeclarationName, int sourceStart, int sourceEnd) {
 	return new LocalDeclaration(localDeclarationName, sourceStart, sourceEnd);
 }
-
+protected RecoveredType currentRecoveryType() {
+	if(this.currentElement != null) {
+		if(this.currentElement instanceof RecoveredType) {
+			return (RecoveredType) this.currentElement;
+		} else {
+			return this.currentElement.enclosingType();
+		}
+	}
+	return null;
+}
 public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult) {
 
 	CompilationUnitDeclaration parsedUnit;
@@ -4398,7 +7366,7 @@
 	return parsedUnit;
 }
 protected void dispatchDeclarationInto(int length) {
-	/* they are length on astStack that should go into
+	/* they are length on this.astStack that should go into
 	   methods fields constructors lists of the typeDecl
 
 	   Return if there is a constructor declaration in the methods declaration */
@@ -4410,32 +7378,38 @@
 		return;
 	int[] flag = new int[length + 1]; //plus one -- see <HERE>
 	int size1 = 0, size2 = 0, size3 = 0;
+	boolean hasAbstractMethods = false;
 	for (int i = length - 1; i >= 0; i--) {
 		ASTNode astNode = this.astStack[this.astPtr--];
 		if (astNode instanceof AbstractMethodDeclaration) {
 			//methods and constructors have been regrouped into one single list
-			flag[i] = 3;
+			flag[i] = 2;
 			size2++;
-		} else {
-			if (astNode instanceof TypeDeclaration) {
-				flag[i] = 4;
-				size3++;
-			} else {
-				//field
-				flag[i] = 1;
-				size1++;
+			if (((AbstractMethodDeclaration) astNode).isAbstract()) {
+				hasAbstractMethods = true;
 			}
+		} else if (astNode instanceof TypeDeclaration) {
+			flag[i] = 3;
+			size3++;
+		} else {
+			//field
+			flag[i] = 1;
+			size1++;
 		}
 	}
 
 	//arrays creation
 	TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
-	if (size1 != 0)
+	if (size1 != 0) {
 		typeDecl.fields = new FieldDeclaration[size1];
-	if (size2 != 0)
+	}
+	if (size2 != 0) {
 		typeDecl.methods = new AbstractMethodDeclaration[size2];
-	if (size3 != 0)
+		if (hasAbstractMethods) typeDecl.bits |= ASTNode.HasAbstractMethods;
+	}
+	if (size3 != 0) {
 		typeDecl.memberTypes = new TypeDeclaration[size3];
+	}
 
 	//arrays fill up
 	size1 = size2 = size3 = 0;
@@ -4455,7 +7429,7 @@
 						size1 - length2, 
 						length2); 
 					break;
-				case 3 :
+				case 2 :
 					size2 += (length2 = end - start);
 					System.arraycopy(
 						this.astStack, 
@@ -4464,7 +7438,7 @@
 						size2 - length2, 
 						length2); 
 					break;
-				case 4 :
+				case 3 :
 					size3 += (length2 = end - start);
 					System.arraycopy(
 						this.astStack, 
@@ -4484,6 +7458,95 @@
 		}
 	}
 }
+protected void dispatchDeclarationIntoEnumDeclaration(int length) {
+	
+	if (length == 0)
+      return;
+   int[] flag = new int[length + 1]; //plus one -- see <HERE>
+   int size1 = 0, size2 = 0, size3 = 0;
+   TypeDeclaration enumDeclaration = (TypeDeclaration) this.astStack[this.astPtr - length];
+   boolean hasAbstractMethods = false;
+   for (int i = length - 1; i >= 0; i--) {
+      ASTNode astNode = this.astStack[this.astPtr--];
+      if (astNode instanceof AbstractMethodDeclaration) {
+         //methods and constructors have been regrouped into one single list
+         flag[i] = 2;
+         size2++;
+		if (((AbstractMethodDeclaration) astNode).isAbstract()) {
+			hasAbstractMethods = true;
+		}         
+      } else if (astNode instanceof TypeDeclaration) {
+         flag[i] = 3;
+         size3++;
+      } else if (astNode instanceof FieldDeclaration) {
+         flag[i] = 1;
+         size1++;
+//         if(astNode instanceof EnumConstant) {
+//            EnumConstant constant = (EnumConstant) astNode;
+//            ((AllocationExpression)constant.initialization).type = new SingleTypeReference(enumDeclaration.name,
+//                  (((long) enumDeclaration.sourceStart) << 32) + enumDeclaration.sourceEnd);
+//         }
+      }
+   }
+ 
+   //arrays creation
+   if (size1 != 0) {
+      enumDeclaration.fields = new FieldDeclaration[size1];
+   }
+   if (size2 != 0) {
+      enumDeclaration.methods = new AbstractMethodDeclaration[size2];
+      if (hasAbstractMethods) enumDeclaration.bits |= ASTNode.HasAbstractMethods;
+   }
+   if (size3 != 0) {
+      enumDeclaration.memberTypes = new TypeDeclaration[size3];
+   }
+ 
+   //arrays fill up
+   size1 = size2 = size3 = 0;
+   int flagI = flag[0], start = 0;
+   int length2;
+   for (int end = 0; end <= length; end++) //<HERE> the plus one allows to 
+      {
+      if (flagI != flag[end]) //treat the last element as a ended flag.....
+         { //array copy
+         switch (flagI) {
+            case 1 :
+               size1 += (length2 = end - start);
+               System.arraycopy(
+                  this.astStack, 
+                  this.astPtr + start + 1, 
+                  enumDeclaration.fields, 
+                  size1 - length2, 
+                  length2); 
+               break;
+            case 2 :
+               size2 += (length2 = end - start);
+               System.arraycopy(
+                  this.astStack, 
+                  this.astPtr + start + 1, 
+                  enumDeclaration.methods, 
+                  size2 - length2, 
+                  length2); 
+               break;
+            case 3 :
+               size3 += (length2 = end - start);
+               System.arraycopy(
+                  this.astStack, 
+                  this.astPtr + start + 1, 
+                  enumDeclaration.memberTypes, 
+                  size3 - length2, 
+                  length2); 
+               break;
+         }
+         flagI = flag[start = end];
+      }
+   }
+ 
+   if (enumDeclaration.memberTypes != null) {
+      for (int i = enumDeclaration.memberTypes.length - 1; i >= 0; i--) {
+         enumDeclaration.memberTypes[i].enclosingType = enumDeclaration;
+      }
+   }}
 protected CompilationUnitDeclaration endParse(int act) {
 
 	this.lastAct = act;
@@ -4569,7 +7632,7 @@
 	this.scanner.commentPtr = validCount - 1;
 	return position;
 }
-public final int getFirstToken() {
+public int getFirstToken() {
 	// the first token is a virtual token that
 	// allows the parser to parse several goals
 	// even if they aren't LALR(1)....
@@ -4642,20 +7705,17 @@
 		if ((unit.bits & ASTNode.HasAllMethodBodies) != 0)
 			return; //work already done ...
 
-		//real parse of the method....
-		char[] contents = unit.compilationResult.compilationUnit.getContents();
-		this.scanner.setSource(contents);
-		
 		// save existing values to restore them at the end of the parsing process
 		// see bug 47079 for more details
 		int[] oldLineEnds = this.scanner.lineEnds;
 		int oldLinePtr = this.scanner.linePtr;
 
-		final int[] lineSeparatorPositions = unit.compilationResult.lineSeparatorPositions;
-		this.scanner.lineEnds = lineSeparatorPositions;
-		this.scanner.linePtr = lineSeparatorPositions.length - 1;
-
+		//real parse of the method....
+		CompilationResult compilationResult = unit.compilationResult;
+		this.scanner.setSource(compilationResult);
+		
 		if (this.javadocParser != null && this.javadocParser.checkDocComment) {
+			char[] contents = compilationResult.compilationUnit.getContents();
 			this.javadocParser.scanner.setSource(contents);
 		}
 		if (unit.types != null) {
@@ -4671,37 +7731,69 @@
 		this.scanner.lineEnds = oldLineEnds;
 		this.scanner.linePtr = oldLinePtr;
 	}
-protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
-This variable is a type reference and dim will be its dimensions*/
+protected char getNextCharacter(char[] comment, int[] index) {
+	char nextCharacter = comment[index[0]++];
+	switch(nextCharacter) {
+		case '\\' :
+			int c1, c2, c3, c4;
+			index[0]++;
+			while (comment[index[0]] == 'u') index[0]++;
+			if (!(((c1 = Character.getNumericValue(comment[index[0]++])) > 15
+				|| c1 < 0)
+				|| ((c2 = Character.getNumericValue(comment[index[0]++])) > 15 || c2 < 0)
+				|| ((c3 = Character.getNumericValue(comment[index[0]++])) > 15 || c3 < 0)
+				|| ((c4 = Character.getNumericValue(comment[index[0]++])) > 15 || c4 < 0))) {
+					nextCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+			}
+			break;
+	}
+	return nextCharacter;
+}
+protected Expression getTypeReference(Expression exp) {
+	
+	exp.bits &= ~ASTNode.RestrictiveFlagMASK;
+	exp.bits |= Binding.TYPE;
+	return exp;
+}
+protected TypeReference getTypeReference(int dim) {
+	/* build a Reference on a variable that may be qualified or not
+	 This variable is a type reference and dim will be its dimensions*/
 
-	int length;
 	TypeReference ref;
-	if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1) {
-		// single variable reference
+	int length = this.identifierLengthStack[this.identifierLengthPtr--];
+	if (length < 0) { //flag for precompiled type reference on base types
+		ref = TypeReference.baseTypeReference(-length, dim);
+		ref.sourceStart = this.intStack[this.intPtr--];
 		if (dim == 0) {
-			ref = 
-				new SingleTypeReference(
-					this.identifierStack[this.identifierPtr], 
-					this.identifierPositionStack[this.identifierPtr--]); 
+			ref.sourceEnd = this.intStack[this.intPtr--];
 		} else {
-			ref = 
-				new ArrayTypeReference(
-					this.identifierStack[this.identifierPtr], 
-					dim, 
-					this.identifierPositionStack[this.identifierPtr--]); 
-			ref.sourceEnd = this.endPosition;			
+			this.intPtr--;
+			ref.sourceEnd = this.endPosition;
 		}
 	} else {
-		if (length < 0) { //flag for precompiled type reference on base types
-			ref = TypeReference.baseTypeReference(-length, dim);
-			ref.sourceStart = this.intStack[this.intPtr--];
+		int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr--];
+		if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
+			// generic type
+			ref = getTypeReferenceForGenericType(dim, length, numberOfIdentifiers);
+		} else if (length == 1) {
+			// single variable reference
+			this.genericsLengthPtr--; // pop the 0
 			if (dim == 0) {
-				ref.sourceEnd = this.intStack[this.intPtr--];
+				ref = 
+					new SingleTypeReference(
+						this.identifierStack[this.identifierPtr], 
+						this.identifierPositionStack[this.identifierPtr--]); 
 			} else {
-				this.intPtr--;
-				ref.sourceEnd = this.endPosition;
+				ref = 
+					new ArrayTypeReference(
+						this.identifierStack[this.identifierPtr], 
+						dim, 
+						this.identifierPositionStack[this.identifierPtr--]); 
+				ref.sourceEnd = this.endPosition;			
 			}
-		} else { //Qualified variable reference
+		} else {
+			this.genericsLengthPtr--;
+			//Qualified variable reference
 			char[][] tokens = new char[length][];
 			this.identifierPtr -= length;
 			long[] positions = new long[length];
@@ -4722,11 +7814,48 @@
 	}
 	return ref;
 }
-protected Expression getTypeReference(Expression exp) {
-	
-	exp.bits &= ~ASTNode.RestrictiveFlagMASK;
-	exp.bits |= TYPE;
-	return exp;
+protected TypeReference getTypeReferenceForGenericType(int dim, int identifierLength, int numberOfIdentifiers) {
+	if (identifierLength == 1 && numberOfIdentifiers == 1) {
+		int currentTypeArgumentsLength = this.genericsLengthStack[this.genericsLengthPtr--];
+		TypeReference[] typeArguments = new TypeReference[currentTypeArgumentsLength];
+		this.genericsPtr -= currentTypeArgumentsLength;
+		System.arraycopy(this.genericsStack, this.genericsPtr + 1, typeArguments, 0, currentTypeArgumentsLength);
+		ParameterizedSingleTypeReference parameterizedSingleTypeReference = new ParameterizedSingleTypeReference(this.identifierStack[this.identifierPtr], typeArguments, dim, this.identifierPositionStack[this.identifierPtr--]);
+		if (dim != 0) {
+			parameterizedSingleTypeReference.sourceEnd = this.endPosition;
+		}
+		return parameterizedSingleTypeReference;
+	} else {
+		TypeReference[][] typeArguments = new TypeReference[numberOfIdentifiers][];
+		char[][] tokens = new char[numberOfIdentifiers][];
+		long[] positions = new long[numberOfIdentifiers];
+		int index = numberOfIdentifiers;
+		int currentIdentifiersLength = identifierLength;
+		while (index > 0) {
+			int currentTypeArgumentsLength = this.genericsLengthStack[this.genericsLengthPtr--];
+			if (currentTypeArgumentsLength != 0) {
+				this.genericsPtr -= currentTypeArgumentsLength;
+				System.arraycopy(this.genericsStack, this.genericsPtr + 1, typeArguments[index - 1] = new TypeReference[currentTypeArgumentsLength], 0, currentTypeArgumentsLength);
+			}
+			switch(currentIdentifiersLength) {
+				case 1 :
+					// we are in a case A<B>.C<D> or A<B>.C<D>
+					tokens[index - 1] = this.identifierStack[this.identifierPtr];
+					positions[index - 1] = this.identifierPositionStack[this.identifierPtr--];
+					break;
+				default:
+					// we are in a case A.B.C<B>.C<D> or A.B.C<B>...
+					this.identifierPtr -= currentIdentifiersLength;
+					System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, index - currentIdentifiersLength, currentIdentifiersLength);
+					System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, index - currentIdentifiersLength, currentIdentifiersLength);
+			}
+			index -= currentIdentifiersLength;
+			if (index > 0) {
+				currentIdentifiersLength = this.identifierLengthStack[this.identifierLengthPtr--];
+			}
+		}
+		return new ParameterizedQualifiedTypeReference(tokens, typeArguments, dim, positions);
+	}
 }
 protected NameReference getUnspecifiedReference() {
 	/* build a (unspecified) NameReference which may be qualified*/
@@ -4772,7 +7901,7 @@
 				this.identifierStack[this.identifierPtr], 
 				this.identifierPositionStack[this.identifierPtr--]); 
 		ref.bits &= ~ASTNode.RestrictiveFlagMASK;
-		ref.bits |= LOCAL | FIELD;
+		ref.bits |= Binding.LOCAL | Binding.FIELD;
 		return ref;
 	}
 
@@ -4793,7 +7922,7 @@
 			(int) (this.identifierPositionStack[this.identifierPtr + 1] >> 32), // sourceStart
 			(int) this.identifierPositionStack[this.identifierPtr + length]); // sourceEnd
 	ref.bits &= ~ASTNode.RestrictiveFlagMASK;
-	ref.bits |= LOCAL | FIELD;
+	ref.bits |= Binding.LOCAL | Binding.FIELD;
 	return ref;
 }
 public void goForBlockStatementsopt() {
@@ -4818,7 +7947,6 @@
 	//tells the scanner to go for compilation unit parsing
 
 	this.firstToken = TokenNamePLUS_PLUS ;
-	this.scanner.linePtr = -1;	
 	this.scanner.foundTaskCount = 0;
 	this.scanner.recordLineSeparator = true;
 	this.scanner.currentLine= null;
@@ -4843,8 +7971,12 @@
 }
 public void goForHeaders(){
 	//tells the scanner to go for headers only parsing
-
-	this.firstToken = TokenNameUNSIGNED_RIGHT_SHIFT;
+	RecoveredType currentType = this.currentRecoveryType();
+	if(currentType != null && currentType.insideEnumConstantPart) {
+		this.firstToken = TokenNameNOT;
+	} else {
+		this.firstToken = TokenNameUNSIGNED_RIGHT_SHIFT;
+	}
 	this.scanner.recordLineSeparator = true; // recovery goals must record line separators
 }
 public void goForImportDeclaration(){
@@ -4859,6 +7991,12 @@
 	this.firstToken = TokenNameRIGHT_SHIFT ;
 	this.scanner.recordLineSeparator = false;
 }
+public void goForMemberValue() {
+	//tells the scanner to go for a memeber value parsing
+
+	this.firstToken = TokenNameOR_OR;
+	this.scanner.recordLineSeparator = true; // recovery goals must record line separators
+}
 public void goForMethodBody(){
 	//tells the scanner to go for method body parsing
 
@@ -4918,11 +8056,11 @@
 	// InvalidConstructorDeclaration ::= ConstructorHeader ';' ==> false
 
 	/*
-	astStack : modifiers arguments throws statements
-	identifierStack : name
+	this.astStack : modifiers arguments throws statements
+	this.identifierStack : name
 	 ==>
-	astStack : MethodDeclaration
-	identifierStack :
+	this.astStack : MethodDeclaration
+	this.identifierStack :
 	*/
 	if (hasBody) {
 		// pop the position of the {  (body of the method) pushed in block decl
@@ -4949,13 +8087,13 @@
 	// InterfaceMemberDeclaration ::= InvalidMethodDeclaration
 
 	/*
-	astStack : modifiers arguments throws statements
-	identifierStack : type name
-	intStack : dim dim dim
+	this.astStack : modifiers arguments throws statements
+	this.identifierStack : type name
+	this.intStack : dim dim dim
 	 ==>
-	astStack : MethodDeclaration
-	identifierStack :
-	intStack : 
+	this.astStack : MethodDeclaration
+	this.identifierStack :
+	this.intStack : 
 	*/
 
 	// pop the position of the {  (body of the method) pushed in block decl
@@ -5013,7 +8151,7 @@
 	}
 	System.arraycopy(this.noExpressions, 0, this.expressionStack, 0, expressionLength);
 
-	// reset scanner state
+	// reset this.scanner state
 	this.scanner.commentPtr = -1;
 	this.scanner.foundTaskCount = 0;
 	this.scanner.eofPosition = Integer.MAX_VALUE;
@@ -5031,11 +8169,18 @@
 	this.recoveredStaticInitializerStart = 0;
 	this.lastIgnoredToken = -1;
 	this.lastErrorEndPosition = -1;
+	this.lastErrorEndPositionBeforeRecovery = -1;
+	this.lastJavadocEnd = -1;
 	this.listLength = 0;
+	this.listTypeParameterLength = 0;
 	
 	this.rBraceStart = 0;
 	this.rBraceEnd = 0;
 	this.rBraceSuccessorStart = 0;
+
+	this.genericsIdentifiersLengthPtr = -1;
+	this.genericsLengthPtr = -1;
+	this.genericsPtr = -1;
 }
 public void initializeScanner(){
 	this.scanner = new Scanner(
@@ -5047,45 +8192,7 @@
 		this.options.taskPriorites/*taskPriorities*/,
 		this.options.isTaskCaseSensitive/*taskCaseSensitive*/);
 }
-public final static void initTables() throws java.io.IOException {
-
-	final String prefix = FILEPREFIX;
-	int i = 0;
-	lhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	char[] chars = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	check_table = new short[chars.length];
-	for (int c = chars.length; c-- > 0;) {
-		check_table[c] = (short) (chars[c] - 32768);
-	}
-	asb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	asr = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	nasb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	nasr = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	terminal_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	non_terminal_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	term_action = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	
-	scope_prefix = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	scope_suffix = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	scope_lhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	scope_state_set = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	scope_rhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	scope_state = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	in_symb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	
-	rhs = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	term_check = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	scope_la = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	
-	name = readNameTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	readableName = readReadableNameTable(READABLE_NAMES);
-	
-	base_action = lhs;
-}
-public static int in_symbol(int state) {
-	return in_symb[original_state(state)];
-}
-public final void jumpOverMethodBody() {
+public void jumpOverMethodBody() {
 	//on diet parsing.....do not buffer method statements
 
 	//the scanner.diet is reinitialized to false
@@ -5130,7 +8237,7 @@
 protected boolean moveRecoveryCheckpoint() {
 
 	int pos = this.lastCheckPoint;
-	/* reset scanner, and move checkpoint by one token */
+	/* reset this.scanner, and move checkpoint by one token */
 	this.scanner.startPosition = pos;
 	this.scanner.currentPosition = pos;
 	this.scanner.diet = false; // quit jumping over method bodies
@@ -5166,7 +8273,7 @@
 	}
 	this.lastCheckPoint = this.scanner.currentPosition;
 	
-	/* reset scanner again to previous checkpoint location*/
+	/* reset this.scanner again to previous checkpoint location*/
 	this.scanner.startPosition = pos;
 	this.scanner.currentPosition = pos;
 	this.scanner.commentPtr = -1;
@@ -5179,7 +8286,7 @@
  	The following implementation moves the checkpoint location by one line:
 	 
 	int pos = this.lastCheckPoint;
-	// reset scanner, and move checkpoint by one token
+	// reset this.scanner, and move checkpoint by one token
 	this.scanner.startPosition = pos;
 	this.scanner.currentPosition = pos;
 	this.scanner.diet = false; // quit jumping over method bodies
@@ -5234,7 +8341,7 @@
 	}
 	this.lastCheckPoint = this.scanner.currentPosition;
 	
-	// reset scanner again to previous checkpoint location
+	// reset this.scanner again to previous checkpoint location
 	this.scanner.startPosition = pos;
 	this.scanner.currentPosition = pos;
 	this.scanner.commentPtr = -1;
@@ -5259,35 +8366,40 @@
 	}
 	return m;
 }
-public static int nasi(int state) {
-	return nasb[original_state(state)];
+protected MessageSend newMessageSendWithTypeArguments() {
+	MessageSend m = new MessageSend();
+	int length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		this.expressionPtr -= length;
+		System.arraycopy(
+			this.expressionStack, 
+			this.expressionPtr + 1, 
+			m.arguments = new Expression[length], 
+			0, 
+			length); 
+	}
+	return m;
 }
-public static int ntAction(int state, int sym) {
-	return base_action[state + sym];
-}
-private final void optimizedConcatNodeLists() {
+protected void optimizedConcatNodeLists() {
 	/*back from a recursive loop. Virtualy group the
-	astNode into an array using astLengthStack*/
+	astNode into an array using this.astLengthStack*/
 
 	/*
-	 * This is a case where you have two sublists into the astStack that you want
-	 * to merge in one list. There is no action required on the astStack. The only
+	 * This is a case where you have two sublists into the this.astStack that you want
+	 * to merge in one list. There is no action required on the this.astStack. The only
 	 * thing you need to do is merge the two lengths specified on the astStackLength.
 	 * The top two length are for example:
 	 * ... p   n
 	 * and you want to result in a list like:
 	 * ... n+p 
 	 * This means that the p could be equals to 0 in case there is no astNode pushed
-	 * on the astStack.
+	 * on the this.astStack.
 	 * Look at the InterfaceMemberDeclarations for an example.
 	 * This case optimizes the fact that p == 1.
 	 */
 
 	this.astLengthStack[--this.astLengthPtr]++;
 }
-protected static int original_state(int state) {
-	return -base_check(state);
-}
 /*main loop of the automat
 When a rule is reduced, the method consumeRule(int) is called with the number
 of the consumed rule. When a terminal is consumed, the method consumeToken(int) is 
@@ -5295,6 +8407,7 @@
 // (int)asr[asi(act)]
 // name[symbol_index[currentKind]]
 protected void parse() {
+	if (DEBUG) System.out.println("-- ENTER INSIDE PARSE METHOD --");  //$NON-NLS-1$
 	boolean isDietParse = this.diet;
 	int oldFirstToken = getFirstToken();
 	this.hasError = false;
@@ -5314,10 +8427,9 @@
 		this.stack[this.stateStackTop] = act;
 
 		act = tAction(act, this.currentToken);
-
 		if (act == ERROR_ACTION || this.restartRecovery) {
 			int errorPos = this.scanner.currentPosition;
-			if (!this.hasReportedError){
+			if (!this.hasReportedError) {
 				this.hasError = true;
 			}
 			if (resumeOnSyntaxError()) {
@@ -5332,7 +8444,7 @@
 		}
 		if (act <= NUM_RULES) {
 			this.stateStackTop--;
-			
+
 		} else if (act > ERROR_ACTION) { /* shift-reduce */
 			consumeToken(this.currentToken);
 			if (this.currentElement != null) this.recoveryTokenCheck();
@@ -5366,6 +8478,7 @@
 			}
 			break ProcessTerminals;
 		}
+			
 		ProcessNonTerminals : do { /* reduce */
 			consumeRule(act);
 			this.stateStackTop -= (rhs[act] - 1);
@@ -5377,68 +8490,7 @@
 	if (this.reportSyntaxErrorIsRequired && this.hasError) {
 		reportSyntaxErrors(isDietParse, oldFirstToken);
 	}
-}
-// A P I
-protected void reportSyntaxErrors(boolean isDietParse, int oldFirstToken) {
-	if(this.referenceContext instanceof MethodDeclaration) {
-		MethodDeclaration methodDeclaration = (MethodDeclaration) this.referenceContext;
-		if(methodDeclaration.errorInSignature){
-			return;
-		}
-	}
-	this.compilationUnit.compilationResult.lineSeparatorPositions = this.scanner.getLineEnds();
-	this.scanner.recordLineSeparator = false;
-	
-	int start = this.scanner.initialPosition;
-	int end = this.scanner.eofPosition <= Integer.MAX_VALUE ? this.scanner.eofPosition - 1 : this.scanner.eofPosition;
-	if(isDietParse) {
-		TypeDeclaration[] types = this.compilationUnit.types;
-		
-		int[][] intervalToSkip = org.eclipse.jdt.internal.compiler.parser.diagnose.RangeUtil.computeDietRange(types);
-		DiagnoseParser diagnoseParser = new DiagnoseParser(this, oldFirstToken, start, end, intervalToSkip[0], intervalToSkip[1], intervalToSkip[2]);
-		diagnoseParser.diagnoseParse();
-		
-		reportSyntaxErrorsForSkippedMethod(types);
-		this.scanner.resetTo(start, end);
-	} else {
-		DiagnoseParser diagnoseParser = new DiagnoseParser(this, oldFirstToken, start, end);
-		diagnoseParser.diagnoseParse();
-	}
-}
-private void reportSyntaxErrorsForSkippedMethod(TypeDeclaration[] types){
-	if(types != null) {
-		for (int i = 0; i < types.length; i++) {
-			TypeDeclaration[] memberTypes = types[i].memberTypes;
-			if(memberTypes != null) {
-				reportSyntaxErrorsForSkippedMethod(memberTypes);
-			}
-			
-			AbstractMethodDeclaration[] methods = types[i].methods;
-			if(methods != null) {
-				for (int j = 0; j < methods.length; j++) {
-					AbstractMethodDeclaration method = methods[j];
-					if(methods[j].errorInSignature) {
-						DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameDIVIDE, method.declarationSourceStart, method.declarationSourceEnd);
-						diagnoseParser.diagnoseParse();
-					}
-				}
-			}
-			
-			FieldDeclaration[] fields = types[i].fields;
-			if (fields != null) {
-				int length = fields.length;
-				for (int j = 0; j < length; j++) {
-					if (fields[j] instanceof Initializer) {
-						Initializer initializer = (Initializer)fields[j];
-						if(initializer.errorInSignature){
-							DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameRIGHT_SHIFT, initializer.declarationSourceStart, initializer.declarationSourceEnd);
-							diagnoseParser.diagnoseParse();
-						}
-					}
-				}
-			}
-		}
-	}
+	if (DEBUG) System.out.println("-- EXIT FROM PARSE METHOD --");  //$NON-NLS-1$
 }
 public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
 	parse(cd, unit, false);
@@ -5553,6 +8605,57 @@
 }
 // A P I
 
+public CompilationUnitDeclaration parse(
+	ICompilationUnit sourceUnit, 
+	CompilationResult compilationResult) {
+	// parses a compilation unit and manages error handling (even bugs....)
+
+	return parse(sourceUnit, compilationResult, -1, -1/*parse without reseting the scanner*/);
+}
+// A P I
+
+public CompilationUnitDeclaration parse(
+	ICompilationUnit sourceUnit, 
+	CompilationResult compilationResult,
+	int start,
+	int end) {
+	// parses a compilation unit and manages error handling (even bugs....)
+
+	CompilationUnitDeclaration unit;
+	try {
+		/* automaton initialization */
+		initialize();
+		goForCompilationUnit();
+
+		/* scanners initialization */
+		char[] contents = sourceUnit.getContents();
+		this.scanner.setSource(contents);
+		if (end != -1) this.scanner.resetTo(start, end);
+		if (this.javadocParser != null && this.javadocParser.checkDocComment) {
+			this.javadocParser.scanner.setSource(contents);
+			if (end != -1) {
+				this.javadocParser.scanner.resetTo(start, end);
+			}
+		}
+		/* unit creation */
+		this.referenceContext = 
+			this.compilationUnit = 
+				new CompilationUnitDeclaration(
+					this.problemReporter, 
+					compilationResult, 
+					this.scanner.source.length);
+		/* run automaton */
+		parse();
+	} finally {
+		unit = this.compilationUnit;
+		this.compilationUnit = null; // reset parser
+		// tag unit has having read bodies
+		if (!this.diet) unit.bits |= ASTNode.HasAllMethodBodies;		
+	}
+	return unit;
+}
+// A P I
+
 public void parse(
 	Initializer initializer, 
 	TypeDeclaration type, 
@@ -5657,57 +8760,6 @@
 		}
 	}
 }
-// A P I
-
-public CompilationUnitDeclaration parse(
-	ICompilationUnit sourceUnit, 
-	CompilationResult compilationResult) {
-	// parses a compilation unit and manages error handling (even bugs....)
-
-	return parse(sourceUnit, compilationResult, -1, -1/*parse without reseting the scanner*/);
-}
-// A P I
-
-public CompilationUnitDeclaration parse(
-	ICompilationUnit sourceUnit, 
-	CompilationResult compilationResult,
-	int start,
-	int end) {
-	// parses a compilation unit and manages error handling (even bugs....)
-
-	CompilationUnitDeclaration unit;
-	try {
-		/* automaton initialization */
-		initialize();
-		goForCompilationUnit();
-
-		/* scanners initialization */
-		char[] contents = sourceUnit.getContents();
-		this.scanner.setSource(contents);
-		if (end != -1) this.scanner.resetTo(start, end);
-		if (this.javadocParser != null && this.javadocParser.checkDocComment) {
-			this.javadocParser.scanner.setSource(contents);
-			if (end != -1) {
-				this.javadocParser.scanner.resetTo(start, end);
-			}
-		}
-		/* unit creation */
-		this.referenceContext = 
-			this.compilationUnit = 
-				new CompilationUnitDeclaration(
-					this.problemReporter, 
-					compilationResult, 
-					this.scanner.source.length);
-		/* run automaton */
-		parse();
-	} finally {
-		unit = this.compilationUnit;
-		this.compilationUnit = null; // reset parser
-		// tag unit has having read bodies
-		if (!this.diet) unit.bits |= ASTNode.HasAllMethodBodies;		
-	}
-	return unit;
-}
 public ASTNode[] parseClassBodyDeclarations(char[] source, int offset, int length, CompilationUnitDeclaration unit) {
 	/* automaton initialization */
 	initialize();
@@ -5771,6 +8823,31 @@
 
 	return this.expressionStack[this.expressionPtr];
 }
+public Expression parseMemberValue(char[] source, int offset, int length, CompilationUnitDeclaration unit) {
+
+	initialize();
+	goForMemberValue();
+	this.nestedMethod[this.nestedType]++;
+
+	this.referenceContext = unit;
+	this.compilationUnit = unit;
+
+	this.scanner.setSource(source);
+	this.scanner.resetTo(offset, offset + length - 1);
+	try {
+		parse();
+	} catch (AbortCompilation ex) {
+		this.lastAct = ERROR_ACTION;
+	} finally {
+		this.nestedMethod[this.nestedType]--;
+	}
+
+	if (this.lastAct == ERROR_ACTION) {
+		return null;
+	}
+
+	return this.expressionStack[this.expressionPtr];
+}
 public void persistLineSeparatorPositions() {
 	if (this.scanner.recordLineSeparator) {
 		this.compilationUnit.compilationResult.lineSeparatorPositions = this.scanner.getLineEnds();
@@ -5899,6 +8976,48 @@
 	}
 	this.expressionLengthStack[this.expressionLengthPtr] = pos;
 }
+protected void pushOnGenericsStack(ASTNode node) {
+	/*add a new obj on top of the generics stack
+	genericsPtr points on the top*/
+
+	int stackLength = this.genericsStack.length;
+	if (++this.genericsPtr >= stackLength) {
+		System.arraycopy(
+			this.genericsStack, 0,
+			this.genericsStack = new ASTNode[stackLength + GenericsStackIncrement], 0,
+			stackLength);
+	}
+	this.genericsStack[this.genericsPtr] = node;
+
+	stackLength = this.genericsLengthStack.length;
+	if (++this.genericsLengthPtr >= stackLength) {
+		System.arraycopy(
+			this.genericsLengthStack, 0,
+			this.genericsLengthStack = new int[stackLength + GenericsStackIncrement], 0,
+			stackLength);
+	}
+	this.genericsLengthStack[this.genericsLengthPtr] = 1;
+}
+protected void pushOnGenericsIdentifiersLengthStack(int pos) {
+	int stackLength = this.genericsIdentifiersLengthStack.length;
+	if (++this.genericsIdentifiersLengthPtr >= stackLength) {
+		System.arraycopy(
+			this.genericsIdentifiersLengthStack, 0,
+			this.genericsIdentifiersLengthStack = new int[stackLength + GenericsStackIncrement], 0,
+			stackLength);
+	}
+	this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr] = pos;
+}
+protected void pushOnGenericsLengthStack(int pos) {
+	int stackLength = this.genericsLengthStack.length;
+	if (++this.genericsLengthPtr >= stackLength) {
+		System.arraycopy(
+			this.genericsLengthStack, 0,
+			this.genericsLengthStack = new int[stackLength + GenericsStackIncrement], 0,
+			stackLength);
+	}
+	this.genericsLengthStack[this.genericsLengthPtr] = pos;
+}
 protected void pushOnIntStack(int pos) {
 
 	int stackLength = this.intStack.length;
@@ -5921,104 +9040,6 @@
 	}
 	this.realBlockStack[this.realBlockPtr] = i;
 }
-protected static char[] readTable(String filename) throws java.io.IOException {
-
-	//files are located at Parser.class directory
-
-	InputStream stream = Parser.class.getResourceAsStream(filename);
-	if (stream == null) {
-		throw new java.io.IOException(Util.bind("parser.missingFile",filename)); //$NON-NLS-1$
-	}
-	byte[] bytes = null;
-	try {
-		stream = new BufferedInputStream(stream);
-		bytes = Util.getInputStreamAsByteArray(stream, -1);
-	} finally {
-		try {
-			stream.close();
-		} catch (IOException e) {
-			// ignore
-		}
-	}
-
-	//minimal integrity check (even size expected)
-	int length = bytes.length;
-	if (length % 2 != 0)
-		throw new java.io.IOException(Util.bind("parser.corruptedFile",filename)); //$NON-NLS-1$
-
-	// convert bytes into chars
-	char[] chars = new char[length / 2];
-	int i = 0;
-	int charIndex = 0;
-
-	while (true) {
-		chars[charIndex++] = (char) (((bytes[i++] & 0xFF) << 8) + (bytes[i++] & 0xFF));
-		if (i == length)
-			break;
-	}
-	return chars;
-}
-protected static byte[] readByteTable(String filename) throws java.io.IOException {
-
-	//files are located at Parser.class directory
-
-	InputStream stream = Parser.class.getResourceAsStream(filename);
-	if (stream == null) {
-		throw new java.io.IOException(Util.bind("parser.missingFile",filename)); //$NON-NLS-1$
-	}
-	byte[] bytes = null;
-	try {
-		stream = new BufferedInputStream(stream);
-		bytes = Util.getInputStreamAsByteArray(stream, -1);
-	} finally {
-		try {
-			stream.close();
-		} catch (IOException e) {
-			// ignore
-		}
-	}
-	return bytes;
-}
-protected static String[] readReadableNameTable(String filename) {
-	String[] result = new String[name.length];
-
-	ResourceBundle bundle;
-	try {
-		bundle = ResourceBundle.getBundle(filename, Locale.getDefault());
-	} catch(MissingResourceException e) {
-		System.out.println("Missing resource : " + filename.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
-		throw e;
-	}
-	for (int i = 0; i < NT_OFFSET + 1; i++) {
-		result[i] = name[i];
-	}
-	for (int i = NT_OFFSET; i < name.length; i++) {
-		try {
-			String n = bundle.getString(name[i]);
-			if(n != null && n.length() > 0) {
-				result[i] = n;
-			} else {
-				result[i] = name[i];
-			}
-		} catch(MissingResourceException e) {
-			result[i] = name[i];
-		}
-	}
-	return result;
-}
-	
-protected static String[] readNameTable(String filename) throws java.io.IOException {
-	char[] contents = readTable(filename);
-	char[][] nameAsChar = CharOperation.splitOn('\n', contents);
-
-	String[] result = new String[nameAsChar.length + 1];
-	result[0] = null;
-	for (int i = 0; i < nameAsChar.length; i++) {
-		result[i + 1] = new String(nameAsChar[i]);
-	}
-	
-	return result;
-}
 public void recoveryExitFromVariable() {
 	if(this.currentElement != null && this.currentElement.parent != null) {
 		if(this.currentElement instanceof RecoveredLocalVariable) {
@@ -6061,11 +9082,20 @@
 				this.lastCheckPoint = this.scanner.currentPosition;
 			if (newElement != this.currentElement){
 				this.currentElement = newElement;
+//				if (newElement instanceof RecoveredField && this.dietInt <= 0) {
+//					if (((RecoveredField)newElement).fieldDeclaration.type == null) { // enum constant
+//						this.isInsideEnumConstantPart = true; // restore status
+//					}
+//				}
 			}
 			break;
 		case TokenNameSEMICOLON :
 			this.endStatementPosition = this.scanner.currentPosition - 1;
 			this.endPosition = this.scanner.startPosition - 1; 
+			RecoveredType currentType = this.currentRecoveryType();
+			if(currentType != null) {
+				currentType.insideEnumConstantPart = false;
+			}
 			// fall through
 		default : {
 			if (this.rBraceEnd > this.rBraceSuccessorStart && this.scanner.currentPosition != this.scanner.startPosition){
@@ -6076,6 +9106,74 @@
 	}
 	this.ignoreNextOpeningBrace = false;
 }
+// A P I
+protected void reportSyntaxErrors(boolean isDietParse, int oldFirstToken) {
+	if(this.referenceContext instanceof MethodDeclaration) {
+		MethodDeclaration methodDeclaration = (MethodDeclaration) this.referenceContext;
+		if(methodDeclaration.errorInSignature){
+			return;
+		}
+	}
+	this.compilationUnit.compilationResult.lineSeparatorPositions = this.scanner.getLineEnds();
+	this.scanner.recordLineSeparator = false;
+	
+	int start = this.scanner.initialPosition;
+	int end = this.scanner.eofPosition <= Integer.MAX_VALUE ? this.scanner.eofPosition - 1 : this.scanner.eofPosition;
+	if(isDietParse) {
+		TypeDeclaration[] types = this.compilationUnit.types;
+		
+		int[][] intervalToSkip = org.eclipse.jdt.internal.compiler.parser.diagnose.RangeUtil.computeDietRange(types);
+		DiagnoseParser diagnoseParser = new DiagnoseParser(this, oldFirstToken, start, end, intervalToSkip[0], intervalToSkip[1], intervalToSkip[2], this.options);
+		diagnoseParser.diagnoseParse();
+		
+		reportSyntaxErrorsForSkippedMethod(types);
+		this.scanner.resetTo(start, end);
+	} else {
+		DiagnoseParser diagnoseParser = new DiagnoseParser(this, oldFirstToken, start, end, this.options);
+		diagnoseParser.diagnoseParse();
+	}
+}
+private void reportSyntaxErrorsForSkippedMethod(TypeDeclaration[] types){
+	if(types != null) {
+		for (int i = 0; i < types.length; i++) {
+			TypeDeclaration[] memberTypes = types[i].memberTypes;
+			if(memberTypes != null) {
+				reportSyntaxErrorsForSkippedMethod(memberTypes);
+			}
+			
+			AbstractMethodDeclaration[] methods = types[i].methods;
+			if(methods != null) {
+				for (int j = 0; j < methods.length; j++) {
+					AbstractMethodDeclaration method = methods[j];
+					if(method.errorInSignature) {
+						if(method.isAnnotationMethod()) {
+							DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameQUESTION, method.declarationSourceStart, method.declarationSourceEnd, this.options);
+							diagnoseParser.diagnoseParse();
+						} else {
+							DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameDIVIDE, method.declarationSourceStart, method.declarationSourceEnd, this.options);
+							diagnoseParser.diagnoseParse();
+						}
+						
+					}
+				}
+			}
+			
+			FieldDeclaration[] fields = types[i].fields;
+			if (fields != null) {
+				int length = fields.length;
+				for (int j = 0; j < length; j++) {
+					if (fields[j] instanceof Initializer) {
+						Initializer initializer = (Initializer)fields[j];
+						if(initializer.errorInSignature){
+							DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameRIGHT_SHIFT, initializer.declarationSourceStart, initializer.declarationSourceEnd, this.options);
+							diagnoseParser.diagnoseParse();
+						}
+					}
+				}
+			}
+		}
+	}
+}
 protected void resetModifiers() {
 	this.modifiers = AccDefault;
 	this.modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int)
@@ -6099,8 +9197,13 @@
 	this.realBlockStack[this.realBlockPtr = 0] = 0;
 	this.recoveredStaticInitializerStart = 0;
 	this.listLength = 0;
+	this.listTypeParameterLength = 0;
 	// Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=29365
 	if (this.scanner != null) this.scanner.currentLine = null;
+	
+	this.genericsIdentifiersLengthPtr = -1;
+	this.genericsLengthPtr = -1;
+	this.genericsPtr = -1;
 }
 /*
  * Reset context so as to resume to regular parse loop
@@ -6111,11 +9214,9 @@
  */
 protected boolean resumeAfterRecovery() {
 
-	// Reset javadoc before restart parsing after recovery
-	this.javadoc = null;
-
 	// reset internal stacks 
 	this.resetStacks();
+	this.resetModifiers();
 	
 	/* attempt to move checkpoint location */
 	if (!this.moveRecoveryCheckpoint()) {
@@ -6131,16 +9232,15 @@
 	// does not know how to restart
 	return false;
 }
-/*
- * Syntax error was detected. Will attempt to perform some recovery action in order
- * to resume to the regular parse loop.
- */
 protected boolean resumeOnSyntaxError() {
 
 	/* request recovery initialization */
 	if (this.currentElement == null){
-		this.currentElement = 
-			this.buildInitialRecoveryState(); // build some recovered elements
+		// Reset javadoc before restart parsing after recovery
+		this.javadoc = null;
+
+		// build some recovered elements
+		this.currentElement = buildInitialRecoveryState(); 
 	}
 	/* do not investigate deeper in recovery when no recovered element */
 	if (this.currentElement == null) return false;
@@ -6155,43 +9255,56 @@
 	/* attempt to reset state in order to resume to parse loop */
 	return this.resumeAfterRecovery();
 }
-public static int tAction(int state, int sym) {
-	return term_action[term_check[base_action[state]+sym] == sym ? base_action[state] + sym : base_action[state]];
-}
 public String toString() {
 
-	String s = "identifierStack : char[][] = {"; //$NON-NLS-1$
+
+	String s = "lastCheckpoint : int = " + String.valueOf(this.lastCheckPoint) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+	s = s + "identifierStack : char["+(this.identifierPtr + 1)+"][] = {"; //$NON-NLS-1$ //$NON-NLS-2$
 	for (int i = 0; i <= this.identifierPtr; i++) {
 		s = s + "\"" + String.valueOf(this.identifierStack[i]) + "\","; //$NON-NLS-1$ //$NON-NLS-2$
 	}
 	s = s + "}\n"; //$NON-NLS-1$
 
-	s = s + "identierLengthStack : int[] = {"; //$NON-NLS-1$
+	s = s + "identifierLengthStack : int["+(this.identifierLengthPtr + 1)+"] = {"; //$NON-NLS-1$ //$NON-NLS-2$
 	for (int i = 0; i <= this.identifierLengthPtr; i++) {
 		s = s + this.identifierLengthStack[i] + ","; //$NON-NLS-1$
 	}
 	s = s + "}\n"; //$NON-NLS-1$
 
-	s = s + "astLengthStack : int[] = {"; //$NON-NLS-1$
+	s = s + "astLengthStack : int["+(this.astLengthPtr + 1)+"] = {"; //$NON-NLS-1$ //$NON-NLS-2$
 	for (int i = 0; i <= this.astLengthPtr; i++) {
 		s = s + this.astLengthStack[i] + ","; //$NON-NLS-1$
 	}
 	s = s + "}\n"; //$NON-NLS-1$
 	s = s + "astPtr : int = " + String.valueOf(this.astPtr) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
 
-	s = s + "intStack : int[] = {"; //$NON-NLS-1$
+	s = s + "intStack : int["+(this.intPtr + 1)+"] = {"; //$NON-NLS-1$ //$NON-NLS-2$
 	for (int i = 0; i <= this.intPtr; i++) {
 		s = s + this.intStack[i] + ","; //$NON-NLS-1$
 	}
 	s = s + "}\n"; //$NON-NLS-1$
 
-	s = s + "expressionLengthStack : int[] = {"; //$NON-NLS-1$
+	s = s + "expressionLengthStack : int["+(this.expressionLengthPtr + 1)+"] = {"; //$NON-NLS-1$ //$NON-NLS-2$
 	for (int i = 0; i <= this.expressionLengthPtr; i++) {
 		s = s + this.expressionLengthStack[i] + ","; //$NON-NLS-1$
 	}
 	s = s + "}\n"; //$NON-NLS-1$
 
 	s = s + "expressionPtr : int = " + String.valueOf(this.expressionPtr) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+	
+	s = s + "genericsIdentifiersLengthStack : int["+(this.genericsIdentifiersLengthPtr + 1)+"] = {"; //$NON-NLS-1$ //$NON-NLS-2$
+	for (int i = 0; i <= this.genericsIdentifiersLengthPtr; i++) {
+		s = s + this.genericsIdentifiersLengthStack[i] + ","; //$NON-NLS-1$
+	}
+	s = s + "}\n"; //$NON-NLS-1$
+	
+	s = s + "genericsLengthStack : int["+(this.genericsLengthPtr + 1)+"] = {"; //$NON-NLS-1$ //$NON-NLS-2$
+	for (int i = 0; i <= this.genericsLengthPtr; i++) {
+		s = s + this.genericsLengthStack[i] + ","; //$NON-NLS-1$
+	}
+	s = s + "}\n"; //$NON-NLS-1$
+
+	s = s + "genericsPtr : int = " + String.valueOf(this.genericsPtr) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
 
 	s = s + "\n\n\n----------------Scanner--------------\n" + this.scanner.toString(); //$NON-NLS-1$
 	return s;
@@ -6234,11 +9347,11 @@
 protected void updateSourcePosition(Expression exp) {
 	//update the source Position of the expression
 
-	//intStack : int int
+	//this.intStack : int int
 	//-->
-	//intStack : 
+	//this.intStack : 
 
 	exp.sourceEnd = this.intStack[this.intPtr--];
 	exp.sourceStart = this.intStack[this.intPtr--];
 }
-}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
index bdb077b..6360b0f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
@@ -12,25 +12,24 @@
 
 /*An interface that contains static declarations for some basic information
  about the parser such as the number of rules in the grammar, the starting state, etc...*/
-
 public interface ParserBasicInformation {
 
-	public final static int
-      ERROR_SYMBOL      = 105,
-      MAX_NAME_LENGTH   = 36,
-      NUM_STATES        = 597,
-      NT_OFFSET         = 105,
-      SCOPE_UBOUND      = 63,
-      SCOPE_SIZE        = 64,
-      LA_STATE_OFFSET   = 5981,
-      MAX_LA            = 1,
-      NUM_RULES         = 433,
-      NUM_TERMINALS     = 105,
-      NUM_NON_TERMINALS = 203,
-      NUM_SYMBOLS       = 308,
-      START_STATE       = 529,
-      EOFT_SYMBOL       = 54,
-      EOLT_SYMBOL       = 54,
-      ACCEPT_ACTION     = 5980,
-      ERROR_ACTION      = 5981;
-}
+	int ERROR_SYMBOL = 108,
+		MAX_NAME_LENGTH = 41,
+		NUM_STATES = 953,
+
+		NT_OFFSET = 108,
+		SCOPE_UBOUND = 132,
+		SCOPE_SIZE = 133,
+		LA_STATE_OFFSET = 12548,
+		MAX_LA = 1,
+		NUM_RULES = 691,
+		NUM_TERMINALS = 108,
+		NUM_NON_TERMINALS = 307,
+		NUM_SYMBOLS = 415,
+		START_STATE = 1129,
+		EOFT_SYMBOL = 67,
+		EOLT_SYMBOL = 67,
+		ACCEPT_ACTION = 12547,
+		ERROR_ACTION = 12548;
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java
index 4133b61..a3849d4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java
@@ -13,6 +13,7 @@
 /**
  * Internal field structure for parsing recovery 
  */
+import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.Expression;
@@ -109,13 +110,22 @@
 }
 public FieldDeclaration updatedFieldDeclaration(){
 
-	if (this.anonymousTypes != null && fieldDeclaration.initialization == null) {
-		for (int i = 0; i < this.anonymousTypeCount; i++){
-			if (anonymousTypes[i].preserveContent){
-				fieldDeclaration.initialization = this.anonymousTypes[i].updatedTypeDeclaration().allocation;
+	if (this.anonymousTypes != null) {
+		if(fieldDeclaration.initialization == null) {
+			for (int i = 0; i < this.anonymousTypeCount; i++){
+				if (anonymousTypes[i].preserveContent){
+					fieldDeclaration.initialization = this.anonymousTypes[i].updatedTypeDeclaration().allocation;
+				}
+			}
+			if (this.anonymousTypeCount > 0) fieldDeclaration.bits |= ASTNode.HasLocalTypeMASK;
+		} else if(fieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+			// fieldDeclaration is an enum constant
+			for (int i = 0; i < this.anonymousTypeCount; i++){
+				if (anonymousTypes[i].preserveContent){
+					this.anonymousTypes[i].updatedTypeDeclaration();
+				}
 			}
 		}
-		if (this.anonymousTypeCount > 0) fieldDeclaration.bits |= ASTNode.HasLocalTypeMASK;
 	}
 	return fieldDeclaration;
 }
@@ -128,7 +138,14 @@
 public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
 	if (bracketBalance > 0){ // was an array initializer
 		bracketBalance--;
-		if (bracketBalance == 0) alreadyCompletedFieldInitialization = true;
+		if (bracketBalance == 0) {
+			if(fieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+				updateSourceEndIfNecessary(braceEnd - 1);
+				return parent;
+			} else {
+				alreadyCompletedFieldInitialization = true;
+			}
+		}
 		return this;
 	} else if (bracketBalance == 0) {
 		alreadyCompletedFieldInitialization = true;
@@ -150,6 +167,11 @@
 		bracketBalance++;
 		return null; // no update is necessary	(array initializer)
 	}
+	if (fieldDeclaration.declarationSourceEnd == 0 
+		&& fieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT){
+		bracketBalance++;
+		return null; // no update is necessary	(enum constant)
+	}
 	// might be an array initializer
 	this.updateSourceEndIfNecessary(braceStart - 1, braceEnd - 1);	
 	return this.parent.updateOnOpeningBrace(braceStart, braceEnd);	
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java
index 66d1aae..ed9d6c3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java
@@ -156,7 +156,7 @@
 	}
 	RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
 	localTypes[localTypeCount++] = element;
-
+	
 	/* consider that if the opening brace was not found, it is there */
 	if (!foundOpeningBrace){
 		foundOpeningBrace = true;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java
index b76bf04..64e38f5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java
@@ -23,6 +23,7 @@
 import org.eclipse.jdt.internal.compiler.ast.SuperReference;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.lookup.BaseTypes;
 import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
 
@@ -212,7 +213,7 @@
 		}
 		return methodBody.add(typeDeclaration, bracketBalanceValue, true);	
 	}
-	if (typeDeclaration.isInterface()) {
+	if (typeDeclaration.kind() == IGenericType.INTERFACE_DECL) {
 		this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(typeDeclaration.declarationSourceStart - 1));
 		if (this.parent == null) {
 			return this; // ignore
@@ -391,7 +392,7 @@
 						}
 					}
 					if(canConsume) {
-						parser.consumeMethodHeaderParameters();
+						parser.consumeMethodHeaderRightParen();
 						/* fix-up positions, given they were updated against rParenPos, which did not get set */
 						if (parser.currentElement == this){ // parameter addition might have added an awaiting (no return type) method - see 1FVXQZ4 */
 							methodDeclaration.sourceEnd = methodDeclaration.arguments[methodDeclaration.arguments.length-1].sourceEnd;
@@ -404,6 +405,16 @@
 		}
 	}
 }
+public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
+	if(this.methodDeclaration.isAnnotationMethod()) {
+		this.updateSourceEndIfNecessary(braceStart, braceEnd);
+		if(!this.foundOpeningBrace && this.parent != null) {
+			return this.parent.updateOnClosingBrace(braceStart, braceEnd);
+		}
+		return this;
+	}
+	return super.updateOnClosingBrace(braceStart, braceEnd);
+}
 /*
  * An opening brace got consumed, might be the expected opening one of the current element,
  * in which case the bodyStart is updated.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java
index 9ac355e..c93242e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java
@@ -12,12 +12,15 @@
 
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Block;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Initializer;
 import org.eclipse.jdt.internal.compiler.ast.Statement;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
 
 /**
@@ -37,10 +40,13 @@
 	public boolean preserveContent = false;	// only used for anonymous types
 	public int bodyEnd;
 	
+	public boolean insideEnumConstantPart = false;
+	
 public RecoveredType(TypeDeclaration typeDeclaration, RecoveredElement parent, int bracketBalance){
 	super(typeDeclaration, parent, bracketBalance);
 	this.typeDeclaration = typeDeclaration;
 	this.foundOpeningBrace = !bodyStartsAtHeaderEnd();
+	this.insideEnumConstantPart = typeDeclaration.kind() == IGenericType.ENUM_DECL;
 	if(this.foundOpeningBrace) {
 		this.bracketBalance++;
 	}
@@ -69,6 +75,8 @@
 	}
 	RecoveredMethod element = new RecoveredMethod(methodDeclaration, this, bracketBalanceValue, this.recoveringParser);
 	methods[methodCount++] = element;
+	
+	this.insideEnumConstantPart = false;
 
 	/* consider that if the opening brace was not found, it is there */
 	if (!foundOpeningBrace){
@@ -107,9 +115,19 @@
 				fieldCount); 
 		}
 	}
-	RecoveredField element = fieldDeclaration.isField() 
-								? new RecoveredField(fieldDeclaration, this, bracketBalanceValue)
-								: new RecoveredInitializer(fieldDeclaration, this, bracketBalanceValue);
+	RecoveredField element;
+	switch (fieldDeclaration.getKind()) {
+		case AbstractVariableDeclaration.FIELD:
+		case AbstractVariableDeclaration.ENUM_CONSTANT:
+			element = new RecoveredField(fieldDeclaration, this, bracketBalanceValue);
+			break;
+		case AbstractVariableDeclaration.INITIALIZER:
+			element = new RecoveredInitializer(fieldDeclaration, this, bracketBalanceValue);
+			break;
+		default:
+			// never happens, as field is always identified
+			return this;
+	}
 	fields[fieldCount++] = element;
 
 	/* consider that if the opening brace was not found, it is there */
@@ -130,6 +148,8 @@
 		return this.parent.add(memberTypeDeclaration, bracketBalanceValue);
 	}
 	
+	this.insideEnumConstantPart = false;
+	
 	if ((memberTypeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0){
 		if (this.methodCount > 0) {
 			// add it to the last method body
@@ -179,7 +199,11 @@
 public boolean bodyStartsAtHeaderEnd(){
 	if (typeDeclaration.superInterfaces == null){
 		if (typeDeclaration.superclass == null){
-			return typeDeclaration.bodyStart == typeDeclaration.sourceEnd+1;
+			if(typeDeclaration.typeParameters == null) {
+				return typeDeclaration.bodyStart == typeDeclaration.sourceEnd+1;
+			} else {
+				return typeDeclaration.bodyStart == typeDeclaration.typeParameters[typeDeclaration.typeParameters.length-1].sourceEnd+1;
+			}
 		} else {
 			return typeDeclaration.bodyStart == typeDeclaration.superclass.sourceEnd+1;
 		}
@@ -306,12 +330,14 @@
 	/* update methods */
 	int existingCount = typeDeclaration.methods == null ? 0 : typeDeclaration.methods.length;
 	boolean hasConstructor = false, hasRecoveredConstructor = false;
+	boolean hasAbstractMethods = false;
 	int defaultConstructorIndex = -1;
 	if (methodCount > 0){
 		AbstractMethodDeclaration[] methodDeclarations = new AbstractMethodDeclaration[existingCount + methodCount];
 		for (int i = 0; i < existingCount; i++){
 			AbstractMethodDeclaration m = typeDeclaration.methods[i];
 			if (m.isDefaultConstructor()) defaultConstructorIndex = i;
+			if (m.isAbstract()) hasAbstractMethods = true;
 			methodDeclarations[i] = m;
 		}
 		// may need to update the declarationSourceEnd of the last method
@@ -323,9 +349,11 @@
 		for (int i = 0; i < methodCount; i++){
 			AbstractMethodDeclaration updatedMethod = methods[i].updatedMethodDeclaration();			
 			if (updatedMethod.isConstructor()) hasRecoveredConstructor = true;
+			if (updatedMethod.isAbstract()) hasAbstractMethods = true;
 			methodDeclarations[existingCount + i] = updatedMethod;			
 		}
 		typeDeclaration.methods = methodDeclarations;
+		if (hasAbstractMethods) typeDeclaration.bits |= ASTNode.HasAbstractMethods;
 		hasConstructor = typeDeclaration.checkConstructors(this.parser());
 	} else {
 		for (int i = 0; i < existingCount; i++){
@@ -360,7 +388,7 @@
 		}
 		typeDeclaration.methods = methodDeclarations;
 	} else {
-		if (!hasConstructor && !typeDeclaration.isInterface()) {// if was already reduced, then constructor
+		if (!hasConstructor && typeDeclaration.kind() != IGenericType.INTERFACE_DECL && typeDeclaration.kind() != IGenericType.ANNOTATION_TYPE_DECL) {// if was already reduced, then constructor
 			boolean insideFieldInitializer = false;
 			RecoveredElement parentElement = this.parent; 
 			while (parentElement != null){
@@ -370,7 +398,7 @@
 				}
 				parentElement = parentElement.parent;
 			}
-			typeDeclaration.createsInternalConstructor(!parser().diet || insideFieldInitializer, true);
+			typeDeclaration.createDefaultConstructor(!parser().diet || insideFieldInitializer, true);
 		} 
 	}
 	if (parent instanceof RecoveredType){
@@ -409,6 +437,30 @@
 				// will reset typeListLength to zero
 				// thus this check will only be performed on first errorCheck after class X implements Y,Z,
 			}
+		} else if (parser.listTypeParameterLength > 0) {
+			int length = parser.listTypeParameterLength;
+			int genericsPtr = parser.genericsPtr;
+			boolean canConsume = genericsPtr + 1 >= length && parser.astPtr > -1;
+			if(canConsume) {
+				if (!(parser.astStack[parser.astPtr] instanceof TypeDeclaration)) {
+					canConsume = false;
+				}
+				while(genericsPtr + 1 > length && !(parser.genericsStack[genericsPtr] instanceof TypeParameter)) {
+					genericsPtr--;
+				}
+				for (int i = 0; i < length; i++) {
+					if(!(parser.genericsStack[genericsPtr - i] instanceof TypeParameter)) {
+						canConsume = false;
+					}
+				}
+			}
+			if(canConsume) {
+				TypeDeclaration typeDecl = (TypeDeclaration)parser.astStack[parser.astPtr];
+				System.arraycopy(parser.genericsStack, genericsPtr - length + 1, typeDecl.typeParameters = new TypeParameter[length], 0, length);
+				typeDecl.bodyStart = typeDecl.typeParameters[length-1].declarationSourceEnd + 1;
+				parser.listTypeParameterLength = 0;
+				parser.lastCheckPoint = typeDecl.bodyStart;
+			}
 		}
 	}
 }
@@ -440,6 +492,9 @@
 			case -1 :
 			case TokenNameextends :
 			case TokenNameimplements :
+			case TokenNameGREATER :
+			case TokenNameRIGHT_SHIFT :
+			case TokenNameUNSIGNED_RIGHT_SHIFT :
 				if (parser.recoveredStaticInitializerStart == 0) break;
 			default:
 				this.foundOpeningBrace = true;				
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java
index 61b1f53..73a9e49 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java
@@ -15,9 +15,11 @@
  */
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Block;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+import org.eclipse.jdt.internal.compiler.ast.Initializer;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 
 public class RecoveredUnit extends RecoveredElement {
@@ -40,9 +42,21 @@
 	/* attach it to last type - if any */
 	if (this.typeCount > 0){
 		RecoveredType type = this.types[this.typeCount -1];
+		int start = type.bodyEnd;
+		int end = type.typeDeclaration.bodyEnd;
 		type.bodyEnd = 0; // reset position
 		type.typeDeclaration.declarationSourceEnd = 0; // reset position
 		type.typeDeclaration.bodyEnd = 0;
+		
+		if(start > 0 && start < end) {
+			Initializer initializer = new Initializer(new Block(0), 0);
+			initializer.bodyStart = end;
+			initializer.bodyEnd = end;
+			initializer.declarationSourceStart = end;
+			initializer.declarationSourceEnd = end;
+			type.add(initializer, bracketBalanceValue);
+		}
+		
 		return type.add(methodDeclaration, bracketBalanceValue);
 	}
 	return this; // ignore
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
index ecd2e33..6ec4cf4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
@@ -14,6 +14,7 @@
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 
@@ -34,13 +35,15 @@
 	 - sourceStart gives the position into the stream
 	 - currentPosition-1 gives the sourceEnd position into the stream 
 	*/
-
+	protected long sourceLevel;
 	// 1.4 feature 
-	private boolean assertMode = false;
 	public boolean useAssertAsAnIndentifier = false;
 	//flag indicating if processed source contains occurrences of keyword assert 
 	public boolean containsAssertKeyword = false; 
 	
+	// 1.5 feature
+	public boolean useEnumAsAnIndentifier = false;
+	
 	public boolean recordLineSeparator = false;
 	public char currentCharacter;
 	public int startPosition;
@@ -101,6 +104,7 @@
 	public static final String UNTERMINATED_STRING = "Unterminated_String"; //$NON-NLS-1$
 	public static final String UNTERMINATED_COMMENT = "Unterminated_Comment"; //$NON-NLS-1$
 	public static final String INVALID_CHAR_IN_STRING = "Invalid_Char_In_String"; //$NON-NLS-1$
+	public static final String INVALID_DIGIT = "Invalid_Digit"; //$NON-NLS-1$	
 
 	//----------------optimized identifier managment------------------
 	static final char[] charArray_a = new char[] {'a'}, 
@@ -137,7 +141,7 @@
 	public /*static*/ final char[][][][] charArray_length = 
 		new char[OptimizedLength][TableSize][InternalTableSize][]; 
 	// support for detecting non-externalized string literals
-	NLSLine currentLine= null;
+	public NLSLine currentLine= null;
 	public static final String TAG_PREFIX= "//$NON-NLS-"; //$NON-NLS-1$
 	public static final int TAG_PREFIX_LENGTH= TAG_PREFIX.length();
 	public static final String TAG_POSTFIX= "$"; //$NON-NLS-1$
@@ -146,6 +150,9 @@
 	public boolean checkNonExternalizedStringLiterals = false;
 	public boolean wasNonExternalizedStringLiteral = false;
 	
+	// generic support
+	public boolean returnOnlyGreater = false;
+	
 	/*static*/ {
 		for (int i = 0; i < 6; i++) {
 			for (int j = 0; j < TableSize; j++) {
@@ -183,7 +190,7 @@
 	this.tokenizeComments = tokenizeComments;
 	this.tokenizeWhiteSpace = tokenizeWhiteSpace;
 	this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
-	this.assertMode = sourceLevel >= ClassFileConstants.JDK1_4;
+	this.sourceLevel = sourceLevel;
 	this.taskTags = taskTags;
 	this.taskPriorities = taskPriorities;
 	this.isTaskCaseSensitive = isTaskCaseSensitive;
@@ -196,7 +203,7 @@
 	return this.source.length == this.currentPosition;
 }
 
-private void checkNonExternalizedString() {
+protected void checkNonExternalizedString() {
 	if (this.currentLine == null) 
 		return;
 	parseTags(this.currentLine);
@@ -666,7 +673,7 @@
 		return -1;
 	}
 }
-public final boolean getNextCharAsDigit() {
+public final boolean getNextCharAsDigit() throws InvalidInputException {
 	//BOOLEAN
 	//handle the case of unicode.
 	//when a unicode appears then we must use a buffer that holds char internal values
@@ -702,7 +709,7 @@
 			}
 
 			this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
-			if (!Character.isDigit(this.currentCharacter)) {
+			if (!isDigit(this.currentCharacter)) {
 				this.currentPosition = temp;
 				return false;
 			}
@@ -717,7 +724,7 @@
 			return true;
 		} //-------------end unicode traitement--------------
 		else {
-			if (!Character.isDigit(this.currentCharacter)) {
+			if (!isDigit(this.currentCharacter)) {
 				this.currentPosition = temp;
 				return false;
 			}
@@ -925,6 +932,13 @@
 			// ---------Identify the next token-------------
 
 			switch (this.currentCharacter) {
+				case '@' :
+/*					if (this.sourceLevel >= ClassFileConstants.JDK1_5) {
+						return TokenNameAT;
+					} else {
+						return TokenNameERROR;
+					}*/
+					return TokenNameAT;
 				case '(' :
 					return TokenNameLPAREN;
 				case ')' :
@@ -942,9 +956,37 @@
 				case ',' :
 					return TokenNameCOMMA;
 				case '.' :
-					if (getNextCharAsDigit())
+					if (getNextCharAsDigit()) {
 						return scanNumber(true);
-					return TokenNameDOT;
+					}
+/*					if (this.sourceLevel >= ClassFileConstants.JDK1_5) {
+						int temp = this.currentPosition;
+						if (getNextChar('.')) {
+							if (getNextChar('.')) {
+								return TokenNameELLIPSIS;
+							} else {
+								this.currentPosition = temp;
+								return TokenNameDOT;
+							}
+						} else {
+							this.currentPosition = temp;
+							return TokenNameDOT;
+						}
+					} else {
+						return TokenNameDOT;
+					}*/
+					int temp = this.currentPosition;
+					if (getNextChar('.')) {
+						if (getNextChar('.')) {
+							return TokenNameELLIPSIS;
+						} else {
+							this.currentPosition = temp;
+							return TokenNameDOT;
+						}
+					} else {
+						this.currentPosition = temp;
+						return TokenNameDOT;
+					}
 				case '+' :
 					{
 						int test;
@@ -992,6 +1034,9 @@
 				case '>' :
 					{
 						int test;
+						if (this.returnOnlyGreater) {
+							return TokenNameGREATER;
+						}
 						if ((test = getNextChar('=', '>')) == 0)
 							return TokenNameGREATER_EQUAL;
 						if (test > 0) {
@@ -1367,7 +1412,9 @@
 								if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
 									checkNonExternalizedString();
 									if (this.recordLineSeparator) {
-										if (!isUnicode) {
+										if (isUnicode) {
+											pushUnicodeLineSeparator();
+										} else {
 											pushLineSeparator();
 										}
 									} else {
@@ -1397,7 +1444,9 @@
 									if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
 										checkNonExternalizedString();
 										if (this.recordLineSeparator) {
-											if (!isUnicode) {
+											if (isUnicode) {
+												pushUnicodeLineSeparator();
+											} else {
 												pushLineSeparator();
 											}
 										} else {
@@ -1450,8 +1499,9 @@
 				default :
 					if (Character.isJavaIdentifierStart(this.currentCharacter))
 						return scanIdentifierOrKeyword();
-					if (Character.isDigit(this.currentCharacter))
+					if (isDigit(this.currentCharacter)) {
 						return scanNumber(false);
+					}						
 					return TokenNameERROR;
 			}
 		}
@@ -1513,7 +1563,26 @@
 public char[] getSource(){
 	return this.source;
 }
-
+protected boolean isDigit(char c) throws InvalidInputException {
+	if (Character.isDigit(c)) {
+		switch(c) {
+			case '0' :
+			case '1' :
+			case '2' :
+			case '3' :
+			case '4' :
+			case '5' :
+			case '6' :
+			case '7' :
+			case '8' :
+			case '9' :
+				return true;
+		}
+		throw new InvalidInputException(Scanner.INVALID_DIGIT);
+	} else {
+		return false;
+	}
+}
 /* Tokenize a method body, assuming that curly brackets are properly balanced.
  */
 public final void jumpOverMethodBody() {
@@ -1841,7 +1910,7 @@
 						scanIdentifierOrKeyword();
 						break;
 					}
-					if (Character.isDigit(this.currentCharacter)) {
+					if (isDigit(this.currentCharacter)) {
 						try {
 							scanNumber(false);
 						} catch (InvalidInputException ex) {
@@ -2145,7 +2214,7 @@
 	newEntry6 = max;
 	return r;	
 }
-private void parseTags(NLSLine line) {
+protected void parseTags(NLSLine line) {
 	String s = new String(getCurrentTokenSource());
 	int pos = s.indexOf(TAG_PREFIX);
 	int lineLength = line.size();
@@ -2355,11 +2424,11 @@
 			int number = Character.getNumericValue(this.currentCharacter);
 			if (number >= 0 && number <= 7) {
 				boolean zeroToThreeNot = number > 3;
-				if (Character.isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
+				if (isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
 					int digit = Character.getNumericValue(this.currentCharacter);
 					if (digit >= 0 && digit <= 7) {
 						number = (number * 8) + digit;
-						if (Character.isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
+						if (isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
 							if (zeroToThreeNot) {// has read \NotZeroToThree OctalDigit Digit --> ignore last character
 								this.currentPosition--;
 							} else {
@@ -2394,6 +2463,7 @@
 	//keywors with the same length AND the same first char, then do another
 	//dispatch on the second char 
 	this.useAssertAsAnIndentifier = false;
+	this.useEnumAsAnIndentifier = false;
 	while (getNextCharAsJavaIdentifierPart()){/*empty*/}
 
 	int index, length;
@@ -2440,7 +2510,7 @@
 						&& (data[++index] == 'e')
 						&& (data[++index] == 'r')
 						&& (data[++index] == 't')) {
-							if (this.assertMode) {
+							if (this.sourceLevel >= ClassFileConstants.JDK1_4) {
 								this.containsAssertKeyword = true;
 								return TokenNameassert;
 							} else {
@@ -2565,8 +2635,18 @@
 				case 4 :
 					if ((data[++index] == 'l') && (data[++index] == 's') && (data[++index] == 'e'))
 						return TokenNameelse;
-					else
-						return TokenNameIdentifier;
+					else if ((data[index] == 'n')
+						&& (data[++index] == 'u')
+						&& (data[++index] == 'm')) {
+							if (this.sourceLevel >= ClassFileConstants.JDK1_5) {
+								return TokenNameenum;
+							} else {
+								this.useEnumAsAnIndentifier = true;
+								return TokenNameIdentifier;								
+							}
+						} else {
+							return TokenNameIdentifier;
+						}
 				case 7 :
 					if ((data[++index] == 'x')
 						&& (data[++index] == 't')
@@ -2966,25 +3046,114 @@
 	boolean floating = dotPrefix;
 	if ((!dotPrefix) && (this.currentCharacter == '0')) {
 		if (getNextChar('x', 'X') >= 0) { //----------hexa-----------------
-			//force the first char of the hexa number do exist...
-			// consume next character
-			this.unicodeAsBackSlash = false;
-			if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
-				&& (this.source[this.currentPosition] == 'u')) {
-				getNextUnicodeChar();
-			} else {
-				if (this.withoutUnicodePtr != 0) {
-					unicodeStoreAt(++this.withoutUnicodePtr);
-				}
-			}
-			if (Character.digit(this.currentCharacter, 16) == -1)
-				throw new InvalidInputException(INVALID_HEXA);
-			//---end forcing--
+			int start = this.currentPosition;
 			while (getNextCharAsDigit(16)){/*empty*/}
-			if (getNextChar('l', 'L') >= 0)
+			int end = this.currentPosition;
+			if (getNextChar('l', 'L') >= 0) {
+				if (end == start) {
+					throw new InvalidInputException(INVALID_HEXA);
+				}
 				return TokenNameLongLiteral;
-			else
+			} else if (getNextChar('.')) {
+				if (this.sourceLevel < ClassFileConstants.JDK1_5) {
+					// if we are in source level < 1.5, we report an integer literal
+					this.currentPosition = end;
+					return TokenNameIntegerLiteral;
+				}
+				// hexadeciman floating point literal
+				// read decimal part
+				boolean hasNoDigitsBeforeDot = end == start;
+				start = this.currentPosition;
+				while (getNextCharAsDigit(16)){/*empty*/}
+				end = this.currentPosition;
+				if (hasNoDigitsBeforeDot && end == start) {
+					throw new InvalidInputException(INVALID_HEXA);
+				}
+				
+				if (getNextChar('p', 'P') >= 0) { // consume next character
+					this.unicodeAsBackSlash = false;
+					if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+						&& (this.source[this.currentPosition] == 'u')) {
+						getNextUnicodeChar();
+					} else {
+						if (this.withoutUnicodePtr != 0) {
+							unicodeStoreAt(++this.withoutUnicodePtr);
+						}
+					}
+
+					if ((this.currentCharacter == '-')
+						|| (this.currentCharacter == '+')) { // consume next character
+						this.unicodeAsBackSlash = false;
+						if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+							&& (this.source[this.currentPosition] == 'u')) {
+							getNextUnicodeChar();
+						} else {
+							if (this.withoutUnicodePtr != 0) {
+								unicodeStoreAt(++this.withoutUnicodePtr);
+							}
+						}
+					}
+					if (!isDigit(this.currentCharacter)) {
+						throw new InvalidInputException(INVALID_HEXA);
+					}
+					while (getNextCharAsDigit()){/*empty*/}
+					if (getNextChar('f', 'F') >= 0) {
+						return TokenNameFloatingPointLiteral;
+					}
+					if (getNextChar('d', 'D') >= 0) {
+						return TokenNameDoubleLiteral;
+					}
+					if (getNextChar('l', 'L') >= 0) {
+						throw new InvalidInputException(INVALID_HEXA);
+					}					
+					return TokenNameDoubleLiteral;
+				} else {
+					throw new InvalidInputException(INVALID_HEXA);
+				}
+			} else if (getNextChar('p', 'P') >= 0) { // consume next character
+				if (this.sourceLevel < ClassFileConstants.JDK1_5) {
+					// if we are in source level < 1.5 we report an integer literal
+					this.currentPosition = end;
+					return TokenNameIntegerLiteral;
+				}
+				this.unicodeAsBackSlash = false;
+				if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+					&& (this.source[this.currentPosition] == 'u')) {
+					getNextUnicodeChar();
+				} else {
+					if (this.withoutUnicodePtr != 0) {
+						unicodeStoreAt(++this.withoutUnicodePtr);
+					}
+				}
+
+				if ((this.currentCharacter == '-')
+					|| (this.currentCharacter == '+')) { // consume next character
+					this.unicodeAsBackSlash = false;
+					if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+						&& (this.source[this.currentPosition] == 'u')) {
+						getNextUnicodeChar();
+					} else {
+						if (this.withoutUnicodePtr != 0) {
+							unicodeStoreAt(++this.withoutUnicodePtr);
+						}
+					}
+				}
+				if (!isDigit(this.currentCharacter))
+					throw new InvalidInputException(INVALID_FLOAT);
+				while (getNextCharAsDigit()){/*empty*/}
+				if (getNextChar('f', 'F') >= 0)
+					return TokenNameFloatingPointLiteral;
+				if (getNextChar('d', 'D') >= 0)
+					return TokenNameDoubleLiteral;
+				if (getNextChar('l', 'L') >= 0) {
+					throw new InvalidInputException(INVALID_HEXA);
+				}
+				return TokenNameDoubleLiteral;
+			} else {
+				if (end == start)
+					throw new InvalidInputException(INVALID_HEXA);
 				return TokenNameIntegerLiteral;
+			}
 		}
 
 		//there is x or X in the number
@@ -3032,7 +3201,7 @@
 							}
 						}
 					}
-					if (!Character.isDigit(this.currentCharacter))
+					if (!isDigit(this.currentCharacter))
 						throw new InvalidInputException(INVALID_FLOAT);
 					while (getNextCharAsDigit()){/*empty*/}
 				}
@@ -3084,7 +3253,7 @@
 				}
 			}
 		}
-		if (!Character.isDigit(this.currentCharacter))
+		if (!isDigit(this.currentCharacter))
 			throw new InvalidInputException(INVALID_FLOAT);
 		while (getNextCharAsDigit()){/*empty*/}
 	}
@@ -3142,6 +3311,21 @@
 	this.eofPosition = sourceLength;
 	this.initialPosition = this.currentPosition = 0;
 	this.containsAssertKeyword = false;
+	this.linePtr = -1;	
+}
+
+/*
+ * Should be used if a parse (usually a diet parse) has already been performed on the unit, 
+ * so as to get the already computed line end positions.
+ */
+public final void setSource(CompilationResult compilationResult) {
+	char[] contents = compilationResult.compilationUnit.getContents();
+	setSource(contents);
+	int[] lineSeparatorPositions = compilationResult.lineSeparatorPositions;
+	if (lineSeparatorPositions != null) {
+		this.lineEnds = lineSeparatorPositions;
+		this.linePtr = lineSeparatorPositions.length - 1;
+	}
 }
 
 public String toString() {
@@ -3181,7 +3365,7 @@
 		+ "<-- Ends here\n===============================\n" //$NON-NLS-1$
 		+ new String(end); 
 }
-public final String toStringAction(int act) {
+public String toStringAction(int act) {
 	switch (act) {
 		case TokenNameIdentifier :
 			return "Identifier(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
index c05ff33..45ea344 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
@@ -8,9 +8,8 @@
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
-
 package org.eclipse.jdt.internal.compiler.parser;
- 
+
 /**
  * IMPORTANT NOTE: These constants are dedicated to the internal Scanner implementation. 
  * It is mirrored in org.eclipse.jdt.core.compiler public package where it is API. 
@@ -18,7 +17,6 @@
  * definitions (stable with 2.0), whereas the internal implementation uses TerminalTokens 
  * which constant values reflect the latest parser generation state.
  */
- 
 /**
  * Maps each terminal symbol in the java-grammar into a unique integer. 
  * This integer is used to represent the terminal when computing a parsing action. 
@@ -30,116 +28,117 @@
 public interface TerminalTokens {
 
 	// special tokens not part of grammar - not autogenerated
-	int 
-		TokenNameWHITESPACE = 1000,
+	int TokenNameWHITESPACE = 1000,
 		TokenNameCOMMENT_LINE = 1001,
 		TokenNameCOMMENT_BLOCK = 1002,
 		TokenNameCOMMENT_JAVADOC = 1003;
-	
-	int
-      TokenNameIdentifier = 28,
-      TokenNameabstract = 60,
-      TokenNameassert = 71,
-      TokenNameboolean = 31,
-      TokenNamebreak = 72,
-      TokenNamebyte = 32,
-      TokenNamecase = 83,
-      TokenNamecatch = 86,
-      TokenNamechar = 33,
-      TokenNameclass = 81,
-      TokenNamecontinue = 73,
-      TokenNamedefault = 84,
-      TokenNamedo = 74,
-      TokenNamedouble = 34,
-      TokenNameelse = 87,
-      TokenNameextends = 91,
-      TokenNamefalse = 44,
-      TokenNamefinal = 61,
-      TokenNamefinally = 88,
-      TokenNamefloat = 35,
-      TokenNamefor = 75,
-      TokenNameif = 76,
-      TokenNameimplements = 103,
-      TokenNameimport = 82,
-      TokenNameinstanceof = 13,
-      TokenNameint = 36,
-      TokenNameinterface = 89,
-      TokenNamelong = 37,
-      TokenNamenative = 62,
-      TokenNamenew = 41,
-      TokenNamenull = 45,
-      TokenNamepackage = 85,
-      TokenNameprivate = 63,
-      TokenNameprotected = 64,
-      TokenNamepublic = 65,
-      TokenNamereturn = 77,
-      TokenNameshort = 38,
-      TokenNamestatic = 57,
-      TokenNamestrictfp = 66,
-      TokenNamesuper = 42,
-      TokenNameswitch = 78,
-      TokenNamesynchronized = 55,
-      TokenNamethis = 43,
-      TokenNamethrow = 79,
-      TokenNamethrows = 104,
-      TokenNametransient = 67,
-      TokenNametrue = 46,
-      TokenNametry = 80,
-      TokenNamevoid = 39,
-      TokenNamevolatile = 68,
-      TokenNamewhile = 70,
-      TokenNameIntegerLiteral = 47,
-      TokenNameLongLiteral = 48,
-      TokenNameFloatingPointLiteral = 49,
-      TokenNameDoubleLiteral = 50,
-      TokenNameCharacterLiteral = 51,
-      TokenNameStringLiteral = 52,
-      TokenNamePLUS_PLUS = 7,
-      TokenNameMINUS_MINUS = 8,
-      TokenNameEQUAL_EQUAL = 18,
-      TokenNameLESS_EQUAL = 14,
-      TokenNameGREATER_EQUAL = 15,
-      TokenNameNOT_EQUAL = 19,
-      TokenNameLEFT_SHIFT = 11,
-      TokenNameRIGHT_SHIFT = 9,
-      TokenNameUNSIGNED_RIGHT_SHIFT = 10,
-      TokenNamePLUS_EQUAL = 92,
-      TokenNameMINUS_EQUAL = 93,
-      TokenNameMULTIPLY_EQUAL = 94,
-      TokenNameDIVIDE_EQUAL = 95,
-      TokenNameAND_EQUAL = 96,
-      TokenNameOR_EQUAL = 97,
-      TokenNameXOR_EQUAL = 98,
-      TokenNameREMAINDER_EQUAL = 99,
-      TokenNameLEFT_SHIFT_EQUAL = 100,
-      TokenNameRIGHT_SHIFT_EQUAL = 101,
-      TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL = 102,
-      TokenNameOR_OR = 24,
-      TokenNameAND_AND = 25,
-      TokenNamePLUS = 1,
-      TokenNameMINUS = 2,
-      TokenNameNOT = 58,
-      TokenNameREMAINDER = 5,
-      TokenNameXOR = 21,
-      TokenNameAND = 20,
-      TokenNameMULTIPLY = 4,
-      TokenNameOR = 22,
-      TokenNameTWIDDLE = 56,
-      TokenNameDIVIDE = 6,
-      TokenNameGREATER = 16,
-      TokenNameLESS = 17,
-      TokenNameLPAREN = 27,
-      TokenNameRPAREN = 29,
-      TokenNameLBRACE = 59,
-      TokenNameRBRACE = 40,
-      TokenNameLBRACKET = 12,
-      TokenNameRBRACKET = 69,
-      TokenNameSEMICOLON = 23,
-      TokenNameQUESTION = 26,
-      TokenNameCOLON = 53,
-      TokenNameCOMMA = 30,
-      TokenNameDOT = 3,
-      TokenNameEQUAL = 90,
-      TokenNameEOF = 54,
-      TokenNameERROR = 105;
-}
+
+	int TokenNameIdentifier = 26,
+		TokenNameabstract = 56,
+		TokenNameassert = 74,
+		TokenNameboolean = 32,
+		TokenNamebreak = 75,
+		TokenNamebyte = 33,
+		TokenNamecase = 100,
+		TokenNamecatch = 101,
+		TokenNamechar = 34,
+		TokenNameclass = 72,
+		TokenNamecontinue = 76,
+		TokenNamedefault = 96,
+		TokenNamedo = 77,
+		TokenNamedouble = 35,
+		TokenNameelse = 102,
+		TokenNameenum = 103,
+		TokenNameextends = 97,
+		TokenNamefalse = 45,
+		TokenNamefinal = 57,
+		TokenNamefinally = 104,
+		TokenNamefloat = 36,
+		TokenNamefor = 78,
+		TokenNameif = 79,
+		TokenNameimplements = 106,
+		TokenNameimport = 99,
+		TokenNameinstanceof = 15,
+		TokenNameint = 37,
+		TokenNameinterface = 80,
+		TokenNamelong = 38,
+		TokenNamenative = 58,
+		TokenNamenew = 43,
+		TokenNamenull = 46,
+		TokenNamepackage = 98,
+		TokenNameprivate = 59,
+		TokenNameprotected = 60,
+		TokenNamepublic = 61,
+		TokenNamereturn = 81,
+		TokenNameshort = 39,
+		TokenNamestatic = 54,
+		TokenNamestrictfp = 62,
+		TokenNamesuper = 41,
+		TokenNameswitch = 82,
+		TokenNamesynchronized = 55,
+		TokenNamethis = 42,
+		TokenNamethrow = 83,
+		TokenNamethrows = 105,
+		TokenNametransient = 63,
+		TokenNametrue = 47,
+		TokenNametry = 84,
+		TokenNamevoid = 40,
+		TokenNamevolatile = 64,
+		TokenNamewhile = 73,
+		TokenNameIntegerLiteral = 48,
+		TokenNameLongLiteral = 49,
+		TokenNameFloatingPointLiteral = 50,
+		TokenNameDoubleLiteral = 51,
+		TokenNameCharacterLiteral = 52,
+		TokenNameStringLiteral = 53,
+		TokenNamePLUS_PLUS = 10,
+		TokenNameMINUS_MINUS = 11,
+		TokenNameEQUAL_EQUAL = 18,
+		TokenNameLESS_EQUAL = 16,
+		TokenNameGREATER_EQUAL = 17,
+		TokenNameNOT_EQUAL = 19,
+		TokenNameLEFT_SHIFT = 13,
+		TokenNameRIGHT_SHIFT = 8,
+		TokenNameUNSIGNED_RIGHT_SHIFT = 9,
+		TokenNamePLUS_EQUAL = 85,
+		TokenNameMINUS_EQUAL = 86,
+		TokenNameMULTIPLY_EQUAL = 87,
+		TokenNameDIVIDE_EQUAL = 88,
+		TokenNameAND_EQUAL = 89,
+		TokenNameOR_EQUAL = 90,
+		TokenNameXOR_EQUAL = 91,
+		TokenNameREMAINDER_EQUAL = 92,
+		TokenNameLEFT_SHIFT_EQUAL = 93,
+		TokenNameRIGHT_SHIFT_EQUAL = 94,
+		TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL = 95,
+		TokenNameOR_OR = 25,
+		TokenNameAND_AND = 24,
+		TokenNamePLUS = 1,
+		TokenNameMINUS = 2,
+		TokenNameNOT = 68,
+		TokenNameREMAINDER = 5,
+		TokenNameXOR = 21,
+		TokenNameAND = 20,
+		TokenNameMULTIPLY = 4,
+		TokenNameOR = 22,
+		TokenNameTWIDDLE = 69,
+		TokenNameDIVIDE = 6,
+		TokenNameGREATER = 12,
+		TokenNameLESS = 7,
+		TokenNameLPAREN = 28,
+		TokenNameRPAREN = 29,
+		TokenNameLBRACE = 66,
+		TokenNameRBRACE = 31,
+		TokenNameLBRACKET = 14,
+		TokenNameRBRACKET = 70,
+		TokenNameSEMICOLON = 27,
+		TokenNameQUESTION = 23,
+		TokenNameCOLON = 65,
+		TokenNameCOMMA = 30,
+		TokenNameDOT = 3,
+		TokenNameEQUAL = 71,
+		TokenNameAT = 44,
+		TokenNameELLIPSIS = 107,
+		TokenNameEOF = 67,
+		TokenNameERROR = 108;
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java
index 58e0506..6c53f6a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.compiler.parser.diagnose;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.parser.Parser;
 import org.eclipse.jdt.internal.compiler.parser.ParserBasicInformation;
 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
@@ -18,6 +19,7 @@
 
 public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
 	private static final boolean DEBUG = false;
+	private boolean DEBUG_PARSECHECK = false;
 	
 	private static final String EMPTY_STRING = ""; //$NON-NLS-1$
 	private static final int STACK_INCREMENT = 256;
@@ -39,6 +41,8 @@
 	private static final int MAX_DISTANCE = 30;
 	private static final int MIN_DISTANCE = 3;
 	
+	private CompilerOptions options;
+	
 	private LexStream lexStream;
 	private int errorToken;
 	private int errorTokenStart;
@@ -133,12 +137,13 @@
 	    }
 	}
 
-	public DiagnoseParser(Parser parser, int firstToken, int start, int end) {
-		this(parser, firstToken, start, end, new int[0], new int[0], new int[0]);
+	public DiagnoseParser(Parser parser, int firstToken, int start, int end, CompilerOptions options) {
+		this(parser, firstToken, start, end, new int[0], new int[0], new int[0], options);
 	}
 
-	public DiagnoseParser(Parser parser, int firstToken, int start, int end, int[] intervalStartToSkip, int[] intervalEndToSkip, int[] intervalFlagsToSkip) {
+	public DiagnoseParser(Parser parser, int firstToken, int start, int end, int[] intervalStartToSkip, int[] intervalEndToSkip, int[] intervalFlagsToSkip, CompilerOptions options) {
 		this.parser = parser;
+		this.options = options;
 		this.lexStream = new LexStream(BUFF_SIZE, parser.scanner, intervalStartToSkip, intervalEndToSkip, intervalFlagsToSkip, firstToken, start, end);
 	}
 	
@@ -1912,6 +1917,9 @@
 		act = stck[stack_top];
 		if (first_token > NT_OFFSET) {
 			tempStackTop = stack_top;
+			if(DEBUG_PARSECHECK) {
+				System.out.println(tempStackTop);
+			}
 			max_pos = stack_top;
 			indx = buffer_position;
 			ct = lexStream.kind(buffer[indx]);
@@ -1919,8 +1927,26 @@
 			int lhs_symbol = first_token - NT_OFFSET;
 			act = Parser.ntAction(act, lhs_symbol);
 			if (act <= NUM_RULES) {
+				// same loop as 'process_non_terminal'
 				do {
 					tempStackTop -= (Parser.rhs[act]-1);
+					
+					if(DEBUG_PARSECHECK) {
+						System.out.print(tempStackTop);
+						System.out.print(" ("); //$NON-NLS-1$
+						System.out.print(-(Parser.rhs[act]-1));
+						System.out.print(") [max:"); //$NON-NLS-1$
+						System.out.print(max_pos);
+						System.out.print("]\tprocess_non_terminal\t"); //$NON-NLS-1$
+						System.out.print(act);
+						System.out.print("\t"); //$NON-NLS-1$
+						System.out.print(Parser.name[Parser.non_terminal_index[Parser.lhs[act]]]);
+						System.out.println();
+					}
+					
+					if(Parser.rules_compliance[act] > this.options.sourceLevel) {
+					 	return 0;
+					}
 					lhs_symbol = Parser.lhs[act];
 					act = (tempStackTop > max_pos
 										  ? tempStack[tempStackTop]
@@ -1932,6 +1958,11 @@
 			}
 		} else {
 			tempStackTop = stack_top - 1;
+			
+			if(DEBUG_PARSECHECK) {
+				System.out.println(tempStackTop);
+			}
+			
 			max_pos = tempStackTop;
 			indx = buffer_position - 1;
 			ct = first_token;
@@ -1939,6 +1970,17 @@
 		}
 
 		process_terminal: for (;;) {
+			if(DEBUG_PARSECHECK) {
+				System.out.print(tempStackTop + 1);
+				System.out.print(" (+1) [max:"); //$NON-NLS-1$
+				System.out.print(max_pos);
+				System.out.print("]\tprocess_terminal    \t"); //$NON-NLS-1$
+				System.out.print(ct);
+				System.out.print("\t"); //$NON-NLS-1$
+				System.out.print(Parser.name[Parser.terminal_index[ct]]);
+				System.out.println();
+			}
+			
 			if (++tempStackTop >= stackLength)  // Stack overflow!!!
 				return indx;
 			tempStack[tempStackTop] = act;
@@ -1947,6 +1989,14 @@
 
 			if (act <= NUM_RULES) {               // reduce action
 				tempStackTop--;
+				
+				if(DEBUG_PARSECHECK) {
+					System.out.print(tempStackTop);
+					System.out.print(" (-1) [max:"); //$NON-NLS-1$
+					System.out.print(max_pos);
+					System.out.print("]\treduce"); //$NON-NLS-1$
+					System.out.println();
+				}
 			} else if (act < ACCEPT_ACTION ||     // shift action
 					 act > ERROR_ACTION) {        // shift-reduce action
 				if (indx == MAX_DISTANCE)
@@ -1955,8 +2005,17 @@
 				ct = lexStream.kind(buffer[indx]);
 				lexStream.reset(lexStream.next(buffer[indx]));
 				if (act > ERROR_ACTION) {
-					 act -= ERROR_ACTION;
+					act -= ERROR_ACTION;
+					
+					if(DEBUG_PARSECHECK) {
+						System.out.print(tempStackTop);
+						System.out.print("\tshift reduce"); //$NON-NLS-1$
+						System.out.println();
+					}
 				} else {
+					if(DEBUG_PARSECHECK) {
+						System.out.println("\tshift"); //$NON-NLS-1$
+					}
 					continue process_terminal;
 				}
 			} else if (act == ACCEPT_ACTION) {           // accept action
@@ -1965,9 +2024,29 @@
 				return indx;                         // error action
 			}
 
+			// same loop as first token initialization
 			process_non_terminal:
 			do {
 				tempStackTop -= (Parser.rhs[act]-1);
+				
+				if(DEBUG_PARSECHECK) {
+					System.out.print(tempStackTop);
+					System.out.print(" ("); //$NON-NLS-1$
+					System.out.print(-(Parser.rhs[act]-1));
+					System.out.print(") [max:"); //$NON-NLS-1$
+					System.out.print(max_pos);
+					System.out.print("]\tprocess_non_terminal\t"); //$NON-NLS-1$
+					System.out.print(act);
+					System.out.print("\t"); //$NON-NLS-1$
+					System.out.print(Parser.name[Parser.non_terminal_index[Parser.lhs[act]]]);
+					System.out.println();
+				}
+				
+				if(act <= NUM_RULES) {
+					if(Parser.rules_compliance[act] > this.options.sourceLevel) {
+					 	return 0;
+					}
+				}
 				int lhs_symbol = Parser.lhs[act];
 				act = (tempStackTop > max_pos
 									  ? tempStack[tempStackTop]
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/RangeUtil.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/RangeUtil.java
index 4c53fa2..00b8d97 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/RangeUtil.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/RangeUtil.java
@@ -158,7 +158,7 @@
 				for (int i = 0; i < length; i++) {
 					if (fields[i] instanceof Initializer) {
 						Initializer initializer = (Initializer)fields[i];
-						if(initializer.declarationSourceEnd == initializer.bodyEnd){
+						if(initializer.declarationSourceEnd == initializer.bodyEnd && initializer.declarationSourceStart != initializer.declarationSourceEnd){
 							initializer.errorInSignature = true;
 							result.addInterval(initializer.declarationSourceStart, initializer.declarationSourceEnd, IGNORE);
 						} else {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
index a35d6d8..8d6c3d9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser10.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser10.rsc
index 57084e8..082965a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser10.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser10.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser11.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser11.rsc
index 4ed7d3b..d1a5283 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser11.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser11.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc
index a114c91..955f911 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser13.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser13.rsc
index 6b56156..9dc419e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser13.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser13.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc
index e701a9e..ecfa021 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc
index 4497913..d7836e5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc
index 0046bb9..64e337c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc
index ca3af17..6f199d2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc
index 66f0156..cd31f71 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser19.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser19.rsc
index 0f1c471..3b7856e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser19.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser19.rsc
@@ -1 +1 @@
-WWEEE;;X(((5EV5(((((S5F ZZ
\ No newline at end of file
+ffFFFBBhAAA!FeAdAIB	JJB!BBBgGGP!H!!!!!,
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
index 3d7327b..3f73142 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc
index 8dc5ace..c371c1c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc
new file mode 100644
index 0000000..3a223d8
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
index 81f96e1..8f173bd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
index 2842e17..6246280 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
index 26aa971..f45b140 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc
index 69c1580..188784f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser7.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser7.rsc
index a4e445a..77673a0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser7.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser7.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser8.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser8.rsc
index 8ce79a7..fcb83ba 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser8.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser8.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc
index 6f68468..f8ca6a7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/readableNames.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/readableNames.properties
index ecc98bf..6ddd4ae 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/readableNames.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/readableNames.properties
@@ -1,19 +1,41 @@
 ,opt=,
-AbstractMethodDeclaration=AbstractMethodDeclaration
+AbstractMethodDeclaration=MethodDeclaration
+AdditionalBound1=AdditionalBound1
+AdditionalBound=AdditionalBound
+AdditionalBoundList1=AdditionalBoundList1
+AdditionalBoundList=AdditionalBoundList
 AdditiveExpression=Expression
+AdditiveExpression_NotName=Expression
 AllocationHeader=AllocationHeader
 AndExpression=Expression
+AndExpression_NotName=Expression
+Annotation=Annotation
+AnnotationMethodHeader=AnnotationMethodHeader
+AnnotationMethodHeaderDefaultValueopt=MethodHeaderDefaultValue
+AnnotationMethodHeaderName=MethodHeaderName
+AnnotationName=AnnotationName
+AnnotationTypeBody=AnnotationTypeBody
+AnnotationTypeDeclaration=AnnotationTypeDeclaration
+AnnotationTypeDeclarationHeader=AnnotationTypeDeclarationHeader
+AnnotationTypeDeclarationHeaderName=AnnotationTypeDeclarationHeaderName
+AnnotationTypeMemberDeclaration=AnnotationTypeMemberDeclaration
+AnnotationTypeMemberDeclarations=AnnotationTypeMemberDeclarations
+AnnotationTypeMemberDeclarationsopt=AnnotationTypeMemberDeclarations
 ArgumentList=ArgumentList
 ArgumentListopt=ArgumentList
+Arguments=Arguments
+Argumentsopt=Argumentsopt
 ArrayAccess=ArrayAccess
 ArrayCreationHeader=ArrayCreationHeader
 ArrayCreationWithArrayInitializer=ArrayCreationWithArrayInitializer
 ArrayCreationWithoutArrayInitializer=ArrayCreationWithoutArrayInitializer
 ArrayInitializer=ArrayInitializer
 ArrayType=ArrayType
+ArrayTypeWithTypeArgumentsName=ArrayTypeWithTypeArgumentsName
 AssertStatement=AssertStatement
 Assignment=Assignment
 AssignmentExpression=Expression
+AssignmentExpression_NotName=Expression
 AssignmentOperator=AssignmentOperator
 Block=Block
 BlockStatement=BlockStatement
@@ -30,6 +52,7 @@
 ClassBodyDeclaration=ClassBodyDeclaration
 ClassBodyDeclarations=ClassBodyDeclarations
 ClassBodyDeclarationsopt=ClassBodyDeclarations
+ClassBodySimpleNameopt=ClassBody
 ClassBodyopt=ClassBody
 ClassDeclaration=ClassDeclaration
 ClassHeader=ClassHeader
@@ -37,24 +60,30 @@
 ClassHeaderExtendsopt=ClassHeaderExtends
 ClassHeaderImplements=ClassHeaderImplements
 ClassHeaderImplementsopt=ClassHeaderImplements
+ClassHeaderName1=ClassHeaderName
 ClassHeaderName=ClassHeaderName
 ClassInstanceCreationExpression=ClassInstanceCreationExpression
 ClassInstanceCreationExpressionName=ClassInstanceCreationExpressionName
 ClassMemberDeclaration=ClassMemberDeclaration
+ClassOrInterface=Type
 ClassOrInterfaceType=Type
 ClassType=ClassType
 ClassTypeElt=ClassType
 ClassTypeList=ClassTypeList
 CompilationUnit=CompilationUnit
 ConditionalAndExpression=Expression
+ConditionalAndExpression_NotName=Expression
 ConditionalExpression=Expression
+ConditionalExpression_NotName=Expression
 ConditionalOrExpression=Expression
+ConditionalOrExpression_NotName=Expression
 ConstantDeclaration=ConstantDeclaration
 ConstantExpression=ConstantExpression
 ConstructorDeclaration=ConstructorDeclaration
-ConstructorHeader=ConstructorHeader
+ConstructorHeader=ConstructorDeclaration
 ConstructorHeaderName=ConstructorHeaderName
 ContinueStatement=ContinueStatement
+DefaultValue=DefaultValue
 Diet=Diet
 DimWithOrWithOutExpr=Dimension
 DimWithOrWithOutExprs=Dimensions
@@ -63,17 +92,34 @@
 Dimsopt=Dimensions
 DoStatement=DoStatement
 EmptyStatement=EmptyStatement
+EnhancedForStatement=EnhancedForStatement
+EnhancedForStatementHeader=EnhancedForStatementHeader
+EnhancedForStatementNoShortIf=EnhancedForStatementNoShortIf
 EnterAnonymousClassBody=EnterAnonymousClassBody
+EnterAnonymousClassBodySimpleName=EnterAnonymousClassBodySimpleName
 EnterCompilationUnit=EnterCompilationUnit
 EnterVariable=EnterVariable
+EnumBody=EnumBody
+EnumBodyDeclarationsopt=EnumBodyDeclarationsopt
+EnumConstant=EnumConstant
+EnumConstantHeader=EnumConstantHeader
+EnumConstantHeaderName=EnumConstantHeaderName
+EnumConstants=EnumConstants
+EnumDeclaration=EnumDeclaration
+EnumDeclarations=EnumDeclarations
+EnumHeader=EnumHeader
+EnumHeaderName=EnumHeaderName
 EqualityExpression=Expression
+EqualityExpression_NotName=Expression
 ExclusiveOrExpression=Expression
+ExclusiveOrExpression_NotName=Expression
 ExitTryBlock=ExitTryBlock
 ExitVariableWithInitialization=ExitVariableWithInitialization
 ExitVariableWithoutInitialization=ExitVariableWithoutInitialization
 ExplicitConstructorInvocation=ExplicitConstructorInvocation
 Expression=Expression
 ExpressionStatement=Statement
+Expression_NotName=Expression
 Expressionopt=Expression
 FieldAccess=FieldAccess
 FieldDeclaration=FieldDeclaration
@@ -90,31 +136,38 @@
 FormalParameterList=FormalParameterList
 FormalParameterListopt=FormalParameterList
 GenericMethodDeclaration=GenericMethodDeclaration
+GenericType=GenericType
 Goal=Goal
+Header1=Header1
+Header2=Header2
 Header=Header
-Headers=Headers
 IfThenElseStatement=IfStatement
 IfThenElseStatementNoShortIf=IfStatement
 IfThenStatement=IfStatement
 ImportDeclaration=ImportDeclaration
 ImportDeclarations=ImportDeclarations
-ImportDeclarationsopt=ImportDeclarations
 InclusiveOrExpression=Expression
+InclusiveOrExpression_NotName=Expression
 Initializer=Initializer
 InsideCastExpression=InsideCastExpression
 InsideCastExpressionLL1=InsideCastExpression
+InsideCastExpressionWithQualifiedGenerics=InsideCastExpression
+InstanceofExpression=Expression
+InstanceofExpression_NotName=Expression
 IntegralType=IntegralType
 InterfaceBody=InterfaceBody
 InterfaceDeclaration=InterfaceDeclaration
 InterfaceHeader=InterfaceHeader
 InterfaceHeaderExtends=InterfaceHeaderExtends
 InterfaceHeaderExtendsopt=InterfaceHeaderExtends
+InterfaceHeaderName1=InterfaceHeaderName
 InterfaceHeaderName=InterfaceHeaderName
 InterfaceMemberDeclaration=InterfaceMemberDeclaration
 InterfaceMemberDeclarations=InterfaceMemberDeclarations
 InterfaceMemberDeclarationsopt=InterfaceMemberDeclarations
 InterfaceType=InterfaceType
 InterfaceTypeList=InterfaceTypeList
+InternalCompilationUnit=CompilationUnit
 InvalidArrayInitializerAssignement=ArrayInitializerAssignement
 InvalidConstructorDeclaration=InvalidConstructorDeclaration
 InvalidInterfaceDeclaration=InvalidInterfaceDeclaration
@@ -124,12 +177,19 @@
 Literal=Literal
 LocalVariableDeclaration=LocalVariableDeclaration
 LocalVariableDeclarationStatement=LocalVariableDeclarationStatement
+MarkerAnnotation=MarkerAnnotation
+MemberValue=MemberValue
+MemberValueArrayInitializer=MemberValueArrayInitializer
+MemberValuePair=MemberValuePair
+MemberValuePairs=MemberValuePairs
+MemberValuePairsopt=MemberValuePairsopt
+MemberValues=MemberValues
 MethodBody=MethodBody
 MethodDeclaration=MethodDeclaration
-MethodHeader=MethodHeader
+MethodHeader=MethodDeclaration
 MethodHeaderExtendedDims=MethodHeaderExtendedDims
 MethodHeaderName=MethodHeaderName
-MethodHeaderParameters=MethodHeaderParameters
+MethodHeaderRightParen=)
 MethodHeaderThrowsClause=MethodHeaderThrowsClause
 MethodHeaderThrowsClauseopt=MethodHeaderThrowsClause
 MethodInvocation=MethodInvocation
@@ -137,35 +197,53 @@
 Modifiers=Modifiers
 Modifiersopt=Modifiers
 MultiplicativeExpression=Expression
+MultiplicativeExpression_NotName=Expression
 Name=Name
 NestedMethod=NestedMethod
 NestedType=NestedType
+NormalAnnotation=NormalAnnotation
 NumericType=NumericType
 OneDimLoop=Dimension
 OnlySynchronized=OnlySynchronized
+OnlyTypeArguments=TypeArguments
+OnlyTypeArgumentsForCastExpression=TypeArguments
 OpenBlock=OpenBlock
 PackageDeclaration=PackageDeclaration
 PackageDeclarationName=PackageDeclarationName
-PackageDeclarationopt=PackageDeclaration
 PostDecrementExpression=PostDecrementExpression
 PostIncrementExpression=PostIncrementExpression
 PostfixExpression=Expression
+PostfixExpression_NotName=Expression
 PreDecrementExpression=PreDecrementExpression
 PreIncrementExpression=PreIncrementExpression
 Primary=Expression
 PrimaryNoNewArray=Expression
 PrimitiveType=PrimitiveType
 PushLPAREN=(
+PushLeftBrace=PushLeftBrace
 PushModifiers=PushModifiers
+PushModifiersForHeader=PushModifiersForHeader
 PushPosition=PushPosition
 PushRPAREN=)
+PushRealModifiers=PushRealModifiers
 QualifiedName=QualifiedName
+RecoveryMethodHeader=MethodHeader
+RecoveryMethodHeaderName=MethodHeaderName
+ReduceImports=ReduceImports
+ReferenceType1=ReferenceType1
+ReferenceType2=ReferenceType2
+ReferenceType3=ReferenceType3
 ReferenceType=ReferenceType
 RelationalExpression=Expression
+RelationalExpression_NotName=Expression
 RestoreDiet=RestoreDiet
 ReturnStatement=ReturnStatement
 ShiftExpression=Expression
+ShiftExpression_NotName=Expression
 SimpleName=SimpleName
+SingleMemberAnnotation=SingleMemberAnnotation
+SingleStaticImportDeclaration=SingleStaticImportDeclaration
+SingleStaticImportDeclarationName=SingleStaticImportDeclarationName
 SingleTypeImportDeclaration=SingleTypeImportDeclaration
 SingleTypeImportDeclarationName=SingleTypeImportDeclarationName
 Statement=Statement
@@ -173,6 +251,8 @@
 StatementExpressionList=StatementExpressionList
 StatementNoShortIf=Statement
 StatementWithoutTrailingSubstatement=Statement
+StaticImportOnDemandDeclaration=StaticImportOnDemandDeclaration
+StaticImportOnDemandDeclarationName=StaticImportOnDemandDeclarationName
 StaticInitializer=StaticInitializer
 StaticOnly=StaticOnly
 SwitchBlock=SwitchBlock
@@ -186,13 +266,29 @@
 TryBlock=Block
 TryStatement=TryStatement
 Type=Type
+TypeArgument1=TypeArgument1
+TypeArgument2=TypeArgument2
+TypeArgument3=TypeArgument3
+TypeArgument=TypeArgument
+TypeArgumentList1=TypeArgumentList1
+TypeArgumentList2=TypeArgumentList2
+TypeArgumentList3=TypeArgumentList3
+TypeArgumentList=TypeArgumentList
+TypeArguments=TypeArguments
 TypeDeclaration=TypeDeclaration
 TypeDeclarations=TypeDeclarations
-TypeDeclarationsopt=TypeDeclarations
 TypeImportOnDemandDeclaration=TypeImportOnDemandDeclaration
 TypeImportOnDemandDeclarationName=TypeImportOnDemandDeclarationName
+TypeParameter1=TypeParameter1
+TypeParameter=TypeParameter
+TypeParameterHeader=TypeParameter
+TypeParameterList1=TypeParameterList1
+TypeParameterList=TypeParameterList
+TypeParameters=TypeParameters
 UnaryExpression=Expression
 UnaryExpressionNotPlusMinus=Expression
+UnaryExpressionNotPlusMinus_NotName=Expression
+UnaryExpression_NotName=Expression
 VariableDeclarator=VariableDeclarator
 VariableDeclaratorId=VariableDeclaratorId
 VariableDeclarators=VariableDeclarators
@@ -200,3 +296,11 @@
 VariableInitializers=VariableInitializers
 WhileStatement=WhileStatement
 WhileStatementNoShortIf=WhileStatement
+Wildcard1=Wildcard1
+Wildcard2=Wildcard2
+Wildcard3=Wildcard3
+Wildcard=Wildcard
+WildcardBounds1=WildcardBounds1
+WildcardBounds2=WildcardBounds2
+WildcardBounds3=WildcardBound3
+WildcardBounds=WildcardBounds
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortCompilation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortCompilation.java
index a462f23..88e143d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortCompilation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortCompilation.java
@@ -31,6 +31,8 @@
 	public boolean isSilent;
 	public RuntimeException silentException;
 
+	private static final long serialVersionUID = -2047226595083244852L; // backward compatible
+	
 	public AbortCompilation() {
 		// empty
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortCompilationUnit.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortCompilationUnit.java
index 203807a..7ab9b07 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortCompilationUnit.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortCompilationUnit.java
@@ -20,6 +20,9 @@
  * should only be thrown from within problem handlers.
  */
 public class AbortCompilationUnit extends AbortCompilation {
+
+	private static final long serialVersionUID = -4253893529982226734L; // backward compatible
+	
 public AbortCompilationUnit(CompilationResult compilationResult, IProblem problem) {
 	super(compilationResult, problem);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortMethod.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortMethod.java
index 6728056..7d8a3c9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortMethod.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortMethod.java
@@ -20,6 +20,9 @@
  * should only be thrown from within problem handlers.
  */
 public class AbortMethod extends AbortType {
+	
+	private static final long serialVersionUID = -1480267398969840003L; // backward compatible	
+	
 public AbortMethod(CompilationResult compilationResult, IProblem problem) {
 	super(compilationResult, problem);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortType.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortType.java
index 99546e6..77e7a0f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortType.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortType.java
@@ -20,6 +20,9 @@
  * should only be thrown from within problem handlers.
  */
 public class AbortType extends AbortCompilationUnit {
+	
+	private static final long serialVersionUID = -5882417089349134385L; // backward compatible
+	
 public AbortType(CompilationResult compilationResult, IProblem problem) {
 	super(compilationResult, problem);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index 96b74f2..41b4d5f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -85,18 +85,18 @@
 		// Must implement the inherited abstract method %1
 		// 8.4.3 - Every non-abstract subclass of an abstract type, A, must provide a concrete implementation of all of A's methods.
 		IProblem.AbstractMethodMustBeImplemented,
-		new String[] {
-			new String(
-				CharOperation.concat(
-					abstractMethod.declaringClass.readableName(),
-					abstractMethod.readableName(),
-					'.'))},
-		new String[] {
-			new String(
-				CharOperation.concat(
-					abstractMethod.declaringClass.shortReadableName(),
-					abstractMethod.shortReadableName(),
-					'.'))},
+		new String[] { 
+		        new String(abstractMethod.selector),
+		        typesAsString(abstractMethod.isVarargs(), abstractMethod.parameters, false), 
+		        new String(abstractMethod.declaringClass.readableName()), 
+		        new String(type.readableName()), 
+		},
+		new String[] { 
+		        new String(abstractMethod.selector),
+		        typesAsString(abstractMethod.isVarargs(), abstractMethod.parameters, true), 
+		        new String(abstractMethod.declaringClass.shortReadableName()), 
+		        new String(type.shortReadableName()), 
+		},
 		type.sourceStart(),
 		type.sourceEnd());
 }
@@ -119,6 +119,106 @@
 		location.sourceStart,
 		location.sourceEnd);
 }
+public void annotationCircularity(TypeBinding sourceType, TypeBinding otherType, TypeReference reference) {
+	if (sourceType == otherType)
+		this.handle(
+			IProblem.AnnotationCircularitySelfReference,
+			new String[] {new String(sourceType.readableName())},
+			new String[] {new String(sourceType.shortReadableName())},
+			reference.sourceStart,
+			reference.sourceEnd);
+	else
+		this.handle(
+			IProblem.AnnotationCircularity,
+			new String[] {new String(sourceType.readableName()), new String(otherType.readableName())},
+			new String[] {new String(sourceType.shortReadableName()), new String(otherType.shortReadableName())},
+			reference.sourceStart,
+			reference.sourceEnd);
+}
+public void annotationCannotOverrideMethod(MethodBinding overrideMethod, MethodBinding inheritedMethod) {
+	ASTNode location = overrideMethod.sourceMethod();
+	this.handle(
+		IProblem.AnnotationCannotOverrideMethod,
+		new String[] {
+				new String(overrideMethod.declaringClass.readableName()),
+				new String(inheritedMethod.declaringClass.readableName()),
+				new String(inheritedMethod.selector), 
+				typesAsString(inheritedMethod.isVarargs(), inheritedMethod.parameters, false)},
+		new String[] {
+				new String(overrideMethod.declaringClass.shortReadableName()),
+				new String(inheritedMethod.declaringClass.shortReadableName()),
+				new String(inheritedMethod.selector), 
+				typesAsString(inheritedMethod.isVarargs(), inheritedMethod.parameters, true)},
+		location.sourceStart,
+		location.sourceEnd);	
+}
+public void annotationFieldNeedConstantInitialization(FieldDeclaration fieldDecl) {
+	String str = new String(fieldDecl.name);
+	this.handle(
+		IProblem.AnnotationFieldNeedConstantInitialization,
+		new String[] { new String(fieldDecl.binding.declaringClass.readableName()), str },
+		new String[] { new String(fieldDecl.binding.declaringClass.shortReadableName()), str},
+		fieldDecl.sourceStart,
+		fieldDecl.sourceEnd);
+}
+public void annotationMembersCannotHaveParameters(AnnotationMethodDeclaration annotationMethodDeclaration) {
+	this.handle(
+		IProblem.AnnotationMembersCannotHaveParameters,
+		NoArgument,
+		NoArgument,
+		annotationMethodDeclaration.sourceStart,
+		annotationMethodDeclaration.sourceEnd);
+}
+public void annotationMembersCannotHaveTypeParameters(AnnotationMethodDeclaration annotationMethodDeclaration) {
+	this.handle(
+		IProblem.AnnotationMembersCannotHaveTypeParameters,
+		NoArgument,
+		NoArgument,
+		annotationMethodDeclaration.sourceStart,
+		annotationMethodDeclaration.sourceEnd);
+}
+public void annotationTypeDeclarationCannotHaveConstructor(ConstructorDeclaration constructorDeclaration) {
+	this.handle(
+		IProblem.AnnotationTypeDeclarationCannotHaveConstructor,
+		NoArgument,
+		NoArgument,
+		constructorDeclaration.sourceStart,
+		constructorDeclaration.sourceEnd);
+}
+public void annotationTypeDeclarationCannotHaveSuperclass(TypeDeclaration typeDeclaration) {
+	this.handle(
+		IProblem.AnnotationTypeDeclarationCannotHaveSuperclass,
+		NoArgument,
+		NoArgument,
+		typeDeclaration.sourceStart,
+		typeDeclaration.sourceEnd);
+}
+public void annotationTypeDeclarationCannotHaveSuperinterfaces(TypeDeclaration typeDeclaration) {
+	this.handle(
+		IProblem.AnnotationTypeDeclarationCannotHaveSuperinterfaces,
+		NoArgument,
+		NoArgument,
+		typeDeclaration.sourceStart,
+		typeDeclaration.sourceEnd);
+}
+public void annotationValueMustBeClassLiteral(TypeBinding annotationType, char[] name, Expression value) {
+	String str = new String(name);
+	this.handle(
+		IProblem.AnnotationValueMustBeClassLiteral,
+		new String[] { new String(annotationType.readableName()), str },
+		new String[] { new String(annotationType.shortReadableName()), str},
+		value.sourceStart,
+		value.sourceEnd);
+}
+public void annotationValueMustBeConstant(TypeBinding annotationType, char[] name, Expression value) {
+	String str = 	new String(name);
+	this.handle(
+		IProblem.AnnotationValueMustBeConstant,
+		new String[] { new String(annotationType.readableName()), str },
+		new String[] { new String(annotationType.shortReadableName()), str},
+		value.sourceStart,
+		value.sourceEnd);
+}
 public void anonymousClassCannotExtendFinalClass(Expression expression, TypeBinding type) {
 	this.handle(
 		IProblem.AnonymousClassCannotExtendFinalClass,
@@ -145,37 +245,6 @@
 		methodDecl.sourceStart,
 		methodDecl.sourceEnd);
 }
-public void argumentTypeProblem(SourceTypeBinding type, AbstractMethodDeclaration methodDecl, Argument arg, TypeBinding expectedType) {
-	int problemId = expectedType.problemId();
-	int id;
-	switch (problemId) {
-		case NotFound : // 1
-			id = IProblem.ArgumentTypeNotFound;
-			break;
-		case NotVisible : // 2
-			id = IProblem.ArgumentTypeNotVisible;
-			break;
-		case Ambiguous : // 3
-			id = IProblem.ArgumentTypeAmbiguous;
-			break;
-		case InternalNameProvided : // 4
-			id = IProblem.ArgumentTypeInternalNameProvided;
-			break;
-		case InheritedNameHidesEnclosingName : // 5
-			id = IProblem.ArgumentTypeInheritedNameHidesEnclosingName;
-			break;
-		case NoError : // 0
-		default :
-			needImplementation(); // want to fail to see why we were here...
-			return;
-	}
-	this.handle(
-		id,
-		new String[] {new String(methodDecl.selector), new String(arg.name), new String(expectedType.readableName())},
-		new String[] {new String(methodDecl.selector), new String(arg.name), new String(expectedType.shortReadableName())},
-		arg.type.sourceStart,
-		arg.type.sourceEnd);
-}
 public void arrayConstantsOnlyInArrayInitializers(int sourceStart, int sourceEnd) {
 	this.handle(
 		IProblem.ArrayConstantsOnlyInArrayInitializers,
@@ -209,21 +278,45 @@
 		returnStatement.sourceStart,
 		returnStatement.sourceEnd);
 }
+public void autoboxing(Expression expression, TypeBinding originalType, TypeBinding convertedType) {
+	this.handle(
+		originalType.isBaseType() ? IProblem.BoxingConversion : IProblem.UnboxingConversion,
+		new String[] { new String(originalType.readableName()), new String(convertedType.readableName()), },
+		new String[] { new String(originalType.shortReadableName()), new String(convertedType.shortReadableName()), },
+		expression.sourceStart,
+		expression.sourceEnd);
+}
+public void boundHasConflictingArguments(ASTNode location, TypeBinding type) {
+	this.handle(
+		IProblem.BoundHasConflictingArguments,
+		new String[] {new String(type.readableName())},
+		new String[] {new String(type.shortReadableName())},
+		location.sourceStart,
+		location.sourceEnd);
+}
+public void boundsMustBeAnInterface(ASTNode location, TypeBinding type) {
+	this.handle(
+		IProblem.BoundsMustBeAnInterface,
+		new String[] {new String(type.readableName())},
+		new String[] {new String(type.shortReadableName())},
+		location.sourceStart,
+		location.sourceEnd);
+}
 public void bytecodeExceeds64KLimit(AbstractMethodDeclaration location) {
-	String[] arguments = new String[] {new String(location.selector), parametersAsString(location.binding)};
+	MethodBinding method = location.binding;
 	if (location.isConstructor()) {
 		this.handle(
 			IProblem.BytecodeExceeds64KLimitForConstructor,
-			arguments,
-			arguments,
+			new String[] {new String(location.selector), typesAsString(method.isVarargs(), method.parameters, false)},
+			new String[] {new String(location.selector), typesAsString(method.isVarargs(), method.parameters, true)},
 			Error | Abort,
 			location.sourceStart,
 			location.sourceEnd);
 	} else {
 		this.handle(
 			IProblem.BytecodeExceeds64KLimit,
-			arguments,
-			arguments,
+			new String[] {new String(location.selector), typesAsString(method.isVarargs(), method.parameters, false)},
+			new String[] {new String(location.selector), typesAsString(method.isVarargs(), method.parameters, true)},
 			Error | Abort,
 			location.sourceStart,
 			location.sourceEnd);
@@ -296,11 +389,23 @@
 public void cannotDireclyInvokeAbstractMethod(MessageSend messageSend, MethodBinding method) {
 	this.handle(
 		IProblem.DirectInvocationOfAbstractMethod,
-		new String[] {new String(method.declaringClass.readableName()), new String(method.selector), parametersAsString(method)},
-		new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), parametersAsShortString(method)},
+		new String[] {new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method.isVarargs(), method.parameters, false)},
+		new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method.isVarargs(), method.parameters, true)},
 		messageSend.sourceStart,
 		messageSend.sourceEnd);
 }
+public void cannotExtendEnum(SourceTypeBinding type, TypeReference superclass, TypeBinding superTypeBinding) {
+	String name = new String(type.sourceName());
+	String superTypeFullName = new String(superTypeBinding.readableName());
+	String superTypeShortName = new String(superTypeBinding.shortReadableName());
+	if (superTypeShortName.equals(name)) superTypeShortName = superTypeFullName;
+	this.handle(
+		IProblem.CannotExtendEnum,
+		new String[] {superTypeFullName, name},
+		new String[] {superTypeShortName, name},
+		superclass.sourceStart,
+		superclass.sourceEnd);
+}
 public void cannotImportPackage(ImportReference importRef) {
 	String[] arguments = new String[] {CharOperation.toString(importRef.tokens)};
 	this.handle(
@@ -351,14 +456,6 @@
 		exceptionType.sourceStart,
 		exceptionType.sourceEnd);
 }
-public void cannotUseSuperInJavaLangObject(ASTNode reference) {
-	this.handle(
-		IProblem.ObjectHasNoSuperclass,
-		NoArgument,
-		NoArgument,
-		reference.sourceStart,
-		reference.sourceEnd);
-}
 public void cannotUseSuperInCodeSnippet(int start, int end) {
 	this.handle(
 		IProblem.CannotUseSuperInCodeSnippet,
@@ -368,6 +465,23 @@
 		start,
 		end);
 }
+public void cannotUseSuperInJavaLangObject(ASTNode reference) {
+	this.handle(
+		IProblem.ObjectHasNoSuperclass,
+		NoArgument,
+		NoArgument,
+		reference.sourceStart,
+		reference.sourceEnd);
+}
+public void cannotUseQualifiedEnumConstantInCaseLabel(QualifiedNameReference reference) {
+	String[] arguments = new String[]{ String.valueOf(reference.fieldBinding().name) };
+	this.handle(
+			IProblem.IllegalQualifiedEnumConstantLabel,
+			arguments,
+			arguments,
+			reference.sourceStart,
+			reference.sourceEnd);	
+}
 public void caseExpressionMustBeConstant(Expression expression) {
 	this.handle(
 		IProblem.NonConstantExpression,
@@ -376,15 +490,15 @@
 		expression.sourceStart,
 		expression.sourceEnd);
 }
-public void classExtendFinalClass(SourceTypeBinding type, TypeReference superclass, TypeBinding expectedType) {
+public void classExtendFinalClass(SourceTypeBinding type, TypeReference superclass, TypeBinding superTypeBinding) {
 	String name = new String(type.sourceName());
-	String expectedFullName = new String(expectedType.readableName());
-	String expectedShortName = new String(expectedType.shortReadableName());
-	if (expectedShortName.equals(name)) expectedShortName = expectedFullName;
+	String superTypeFullName = new String(superTypeBinding.readableName());
+	String superTypeShortName = new String(superTypeBinding.shortReadableName());
+	if (superTypeShortName.equals(name)) superTypeShortName = superTypeFullName;
 	this.handle(
 		IProblem.ClassExtendFinalClass,
-		new String[] {expectedFullName, name},
-		new String[] {expectedShortName, name},
+		new String[] {superTypeFullName, name},
+		new String[] {superTypeShortName, name},
 		superclass.sourceStart,
 		superclass.sourceEnd);
 }
@@ -466,6 +580,8 @@
 
 		case IProblem.UseAssertAsAnIdentifier :
 			return this.options.getSeverity(CompilerOptions.AssertUsedAsAnIdentifier);
+		case IProblem.UseEnumAsAnIdentifier :
+			return this.options.getSeverity(CompilerOptions.EnumUsedAsAnIdentifier);
 
 		case IProblem.NonStaticAccessToStaticMethod :
 		case IProblem.NonStaticAccessToStaticField :
@@ -526,19 +642,52 @@
 		case IProblem.UnnecessaryElse:
 			return this.options.getSeverity(CompilerOptions.UnnecessaryElse);
 
+		case IProblem.UnsafeRawConstructorInvocation:
+		case IProblem.UnsafeRawMethodInvocation:
+		case IProblem.UnsafeRawConversion:
+		case IProblem.UnsafeRawFieldAssignment:
+		case IProblem.UnsafeGenericCast:
+		case IProblem.UnsafeReturnTypeOverride:
+			return this.options.getSeverity(CompilerOptions.UncheckedTypeOperation);
+
+		case IProblem.FinalBoundForTypeVariable:
+		    return this.options.getSeverity(CompilerOptions.FinalParameterBound);
+
+		case IProblem.MissingSerialVersion:
+			return this.options.getSeverity(CompilerOptions.MissingSerialVersion);
+		
+		case IProblem.ForbiddenReference:
+			return this.options.getSeverity(CompilerOptions.ForbiddenReference);
+
+		case IProblem.MethodVarargsArgumentNeedCast :
+		case IProblem.ConstructorVarargsArgumentNeedCast :
+			return this.options.getSeverity(CompilerOptions.VarargsArgumentNeedCast);
+
+		case IProblem.LocalVariableCannotBeNull :
+		case IProblem.LocalVariableCanOnlyBeNull :
+			return this.options.getSeverity(CompilerOptions.NullReference);
+			
+		case IProblem.BoxingConversion :
+		case IProblem.UnboxingConversion :
+			return this.options.getSeverity(CompilerOptions.Autoboxing);
+
 		/*
 		 * Javadoc syntax errors
 		 */
-		// Javadoc explicit IDs
 		case IProblem.JavadocUnexpectedTag:
 		case IProblem.JavadocDuplicateReturnTag:
 		case IProblem.JavadocInvalidThrowsClass:
-		case IProblem.JavadocInvalidSeeReference:
+		case IProblem.JavadocInvalidReference:
+		case IProblem.JavadocInvalidParamTagName:
+		case IProblem.JavadocInvalidParamTagTypeParameter:
 		case IProblem.JavadocMalformedSeeReference:
 		case IProblem.JavadocInvalidSeeHref:
 		case IProblem.JavadocInvalidSeeArgs:
 		case IProblem.JavadocInvalidTag:
 		case IProblem.JavadocUnterminatedInlineTag:
+		case IProblem.JavadocMissingHashCharacter:
+		case IProblem.JavadocEmptyReturnTag:
+		case IProblem.JavadocUnexpectedText:
 			if (this.options.docCommentSupport) {
 				return this.options.getSeverity(CompilerOptions.InvalidJavadoc);
 			} else {
@@ -554,24 +703,17 @@
 		case IProblem.JavadocInvalidThrowsClassName:
 		case IProblem.JavadocDuplicateThrowsClassName:
 		case IProblem.JavadocMissingThrowsClassName:
-		case IProblem.JavadocMissingSeeReference:
-		case IProblem.JavadocUsingDeprecatedField:
-		case IProblem.JavadocUsingDeprecatedConstructor:
-		case IProblem.JavadocUsingDeprecatedMethod:
-		case IProblem.JavadocUsingDeprecatedType:
+		case IProblem.JavadocMissingReference:
+		case IProblem.JavadocInvalidValueReference:
 		case IProblem.JavadocUndefinedField:
-		case IProblem.JavadocNotVisibleField:
 		case IProblem.JavadocAmbiguousField:
 		case IProblem.JavadocUndefinedConstructor:
-		case IProblem.JavadocNotVisibleConstructor:
 		case IProblem.JavadocAmbiguousConstructor:
 		case IProblem.JavadocUndefinedMethod:
-		case IProblem.JavadocNotVisibleMethod:
 		case IProblem.JavadocAmbiguousMethod:
 		case IProblem.JavadocAmbiguousMethodReference:
 		case IProblem.JavadocParameterMismatch:
 		case IProblem.JavadocUndefinedType:
-		case IProblem.JavadocNotVisibleType:
 		case IProblem.JavadocAmbiguousType:
 		case IProblem.JavadocInternalTypeNameProvided:
 		case IProblem.JavadocNoMessageSendOnArrayType:
@@ -581,9 +723,32 @@
 		case IProblem.JavadocInheritedNameHidesEnclosingTypeName:
 			if (this.options.docCommentSupport && this.options.reportInvalidJavadocTags) {
 				return this.options.getSeverity(CompilerOptions.InvalidJavadoc);
-			} else {
-				return ProblemSeverities.Ignore;
 			}
+			return ProblemSeverities.Ignore;
+
+		/*
+		 * Javadoc invalid tags due to deprecated references
+		 */
+		case IProblem.JavadocUsingDeprecatedField:
+		case IProblem.JavadocUsingDeprecatedConstructor:
+		case IProblem.JavadocUsingDeprecatedMethod:
+		case IProblem.JavadocUsingDeprecatedType:
+			if (this.options.docCommentSupport && this.options.reportInvalidJavadocTags && this.options.reportInvalidJavadocTagsDeprecatedRef) {
+				return this.options.getSeverity(CompilerOptions.InvalidJavadoc);
+			}
+			return ProblemSeverities.Ignore;
+
+		/*
+		 * Javadoc invalid tags due to non-visible references
+		 */
+		case IProblem.JavadocNotVisibleField:
+		case IProblem.JavadocNotVisibleConstructor:
+		case IProblem.JavadocNotVisibleMethod:
+		case IProblem.JavadocNotVisibleType:
+			if (this.options.docCommentSupport && this.options.reportInvalidJavadocTags && this.options.reportInvalidJavadocTagsNotVisibleRef) {
+				return this.options.getSeverity(CompilerOptions.InvalidJavadoc);
+			}
+			return ProblemSeverities.Ignore;
 
 		/*
 		 * Javadoc missing tags errors
@@ -606,7 +771,7 @@
 			} else {
 				return ProblemSeverities.Ignore;
 			}
-
+			
 		// by default problems are errors.
 		default:
 			return Error;
@@ -683,6 +848,15 @@
 		literal.sourceStart,
 		literal.sourceEnd);
 }
+public void corruptedSignature(TypeBinding enclosingType, char[] signature, int position) {
+	this.handle(
+		IProblem.CorruptedSignature,
+		new String[] { new String(enclosingType.readableName()), new String(signature), String.valueOf(position) },
+		new String[] { new String(enclosingType.shortReadableName()), new String(signature), String.valueOf(position) },
+		Error | Abort,
+		0,
+		0);
+}
 public void deprecatedField(FieldBinding field, ASTNode location) {
 	this.handle(
 		IProblem.UsingDeprecatedField,
@@ -695,19 +869,28 @@
 	if (method.isConstructor()) {
 		this.handle(
 			IProblem.UsingDeprecatedConstructor,
-			new String[] {new String(method.declaringClass.readableName()), parametersAsString(method)},
-			new String[] {new String(method.declaringClass.shortReadableName()), parametersAsShortString(method)},
+			new String[] {new String(method.declaringClass.readableName()), typesAsString(method.isVarargs(), method.parameters, false)},
+			new String[] {new String(method.declaringClass.shortReadableName()), typesAsString(method.isVarargs(), method.parameters, true)},
 			location.sourceStart,
 			location.sourceEnd);
 	} else {
 		this.handle(
 			IProblem.UsingDeprecatedMethod,
-			new String[] {new String(method.declaringClass.readableName()), new String(method.selector), parametersAsString(method)},
-			new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), parametersAsShortString(method)},
+			new String[] {new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method.isVarargs(), method.parameters, false)},
+			new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method.isVarargs(), method.parameters, true)},
 			location.sourceStart,
 			location.sourceEnd);
 	}
 }
+public void methodMustOverride(AbstractMethodDeclaration method) {
+	MethodBinding binding = method.binding;
+	this.handle(
+		IProblem.MethodMustOverride,
+		new String[] {new String(binding.selector), typesAsString(binding.isVarargs(), binding.parameters, false), new String(binding.declaringClass.readableName()), },
+		new String[] {new String(binding.selector), typesAsString(binding.isVarargs(), binding.parameters, true), new String(binding.declaringClass.shortReadableName()),},
+		method.sourceStart,
+		method.sourceEnd);
+}
 public void deprecatedType(TypeBinding type, ASTNode location) {
 	if (location == null) return; // 1G828DN - no type ref for synthetic arguments
 	this.handle(
@@ -717,6 +900,32 @@
 		location.sourceStart,
 		location.sourceEnd);
 }
+public void duplicateAnnotation(Annotation annotation) {
+	this.handle(
+		IProblem.DuplicateAnnotation,
+		new String[] {new String(annotation.resolvedType.readableName())},
+		new String[] {new String(annotation.resolvedType.shortReadableName())},
+		annotation.sourceStart,
+		annotation.sourceEnd);
+}
+public void duplicateAnnotationValue(TypeBinding annotationType, MemberValuePair memberValuePair) {
+	String name = 	new String(memberValuePair.name);
+	this.handle(
+		IProblem.DuplicateAnnotationMember,
+		new String[] { name, new String(annotationType.readableName())},
+		new String[] {	name, new String(annotationType.shortReadableName())},
+		memberValuePair.sourceStart,
+		memberValuePair.sourceEnd);
+}
+public void duplicateTargetInTargetAnnotation(TypeBinding annotationType, NameReference reference) {
+	String name = 	new String(reference.fieldBinding().name);
+	this.handle(
+		IProblem.DuplicateTargetInTargetAnnotation,
+		new String[] { name, new String(annotationType.readableName())},
+		new String[] {	name, new String(annotationType.shortReadableName())},
+		reference.sourceStart,
+		reference.sourceEnd);
+}
 public void duplicateCase(CaseStatement caseStatement) {
 	this.handle(
 		IProblem.DuplicateCase,
@@ -741,6 +950,7 @@
 		fieldDecl.sourceStart,
 		fieldDecl.sourceEnd);
 }
+
 public void duplicateImport(ImportReference importRef) {
 	String[] arguments = new String[] {CharOperation.toString(importRef.tokens)};
 	this.handle(
@@ -750,6 +960,22 @@
 		importRef.sourceStart,
 		importRef.sourceEnd);
 }
+public void duplicateInheritedMethods(SourceTypeBinding type, MethodBinding inheritedMethod1, MethodBinding inheritedMethod2) {
+	this.handle(
+		IProblem.DuplicateParameterizedMethods,
+		new String[] {
+	        new String(inheritedMethod1.selector),
+			new String(inheritedMethod1.declaringClass.readableName()),
+			typesAsString(inheritedMethod1.isVarargs(), inheritedMethod1.original().parameters, false),	
+			typesAsString(inheritedMethod2.isVarargs(), inheritedMethod2.original().parameters, false)},
+		new String[] {
+			new String(inheritedMethod1.selector),
+			new String(inheritedMethod1.declaringClass.shortReadableName()),
+			typesAsString(inheritedMethod1.isVarargs(), inheritedMethod1.original().parameters, true),	
+			typesAsString(inheritedMethod2.isVarargs(), inheritedMethod2.original().parameters, true)},
+		type.sourceStart(),
+		type.sourceEnd());
+}
 public void duplicateInitializationOfBlankFinalField(FieldBinding field, Reference reference) {
 	String[] arguments = new String[]{ new String(field.readableName())};
 	this.handle(
@@ -768,15 +994,70 @@
 		location.sourceStart,
 		location.sourceEnd);
 }
-public void duplicateMethodInType(SourceTypeBinding type, AbstractMethodDeclaration methodDecl) {
-	String[] arguments = new String[] {new String(methodDecl.selector), new String(type.sourceName())};
+
+public void duplicateEnumSpecialMethod(SourceTypeBinding type, AbstractMethodDeclaration methodDecl) {
+    MethodBinding method = methodDecl.binding;
 	this.handle(
-		IProblem.DuplicateMethod,
-		arguments,
-		arguments,
+		IProblem.CannotDeclareEnumSpecialMethod,
+		new String[] {
+	        new String(methodDecl.selector),
+			new String(method.declaringClass.readableName()),
+			typesAsString(method.isVarargs(), method.parameters, false)},
+		new String[] {
+			new String(methodDecl.selector),
+			new String(method.declaringClass.shortReadableName()),
+			typesAsString(method.isVarargs(), method.parameters, true)},
 		methodDecl.sourceStart,
 		methodDecl.sourceEnd);
 }
+
+public void duplicateMethodInType(SourceTypeBinding type, AbstractMethodDeclaration methodDecl) {
+    MethodBinding method = methodDecl.binding;
+    boolean duplicateErasure = false;
+    if ((method.modifiers & CompilerModifiers.AccGenericSignature) != 0) {
+        // chech it occurs in parameters (the bit is set for return type | params | thrown exceptions
+        for (int i = 0, length = method.parameters.length; i < length; i++) {
+            if ((method.parameters[i].tagBits & TagBits.HasTypeVariable) != 0) {
+                duplicateErasure = true;
+                break;
+            }
+        }
+    }
+    if (duplicateErasure) {
+        int length = method.parameters.length;
+        TypeBinding[] erasures = new TypeBinding[length];
+        for (int i = 0; i < length; i++)  {
+            erasures[i] = method.parameters[i].erasure();
+        }
+		this.handle(
+			IProblem.DuplicateMethodErasure,
+			new String[] {
+		        new String(methodDecl.selector),
+				new String(method.declaringClass.readableName()),
+				typesAsString(method.isVarargs(), method.parameters, false),
+				typesAsString(method.isVarargs(), erasures, false) } ,
+			new String[] {
+				new String(methodDecl.selector),
+				new String(method.declaringClass.shortReadableName()),
+				typesAsString(method.isVarargs(), method.parameters, true),
+				typesAsString(method.isVarargs(), erasures, true) },
+			methodDecl.sourceStart,
+			methodDecl.sourceEnd);
+    } else {
+		this.handle(
+			IProblem.DuplicateMethod,
+			new String[] {
+		        new String(methodDecl.selector),
+				new String(method.declaringClass.readableName()),
+				typesAsString(method.isVarargs(), method.parameters, false)},
+			new String[] {
+				new String(methodDecl.selector),
+				new String(method.declaringClass.shortReadableName()),
+				typesAsString(method.isVarargs(), method.parameters, true)},
+			methodDecl.sourceStart,
+			methodDecl.sourceEnd);
+    }
+}
 public void duplicateModifierForField(ReferenceBinding type, FieldDeclaration fieldDecl) {
 /* to highlight modifiers use:
 	this.handle(
@@ -843,6 +1124,14 @@
 		typeDecl.sourceStart,
 		typeDecl.sourceEnd);
 }
+public void duplicateTypeParameterInType(TypeParameter typeParameter) {
+	this.handle(
+		IProblem.DuplicateTypeVariable,
+		new String[] { new String(typeParameter.name)},
+		new String[] { new String(typeParameter.name)},
+		typeParameter.sourceStart,
+		typeParameter.sourceEnd);
+}
 public void duplicateTypes(CompilationUnitDeclaration compUnitDecl, TypeDeclaration typeDecl) {
 	String[] arguments = new String[] {new String(compUnitDecl.getFileName()), new String(typeDecl.name)};
 	this.referenceContext = typeDecl; // report the problem against the type not the entire compilation unit
@@ -862,6 +1151,26 @@
 		sourceStart,
 		sourceEnd);	
 }
+public void enumAbstractMethodMustBeImplemented(AbstractMethodDeclaration method) {
+	MethodBinding abstractMethod = method.binding;
+	this.handle(
+		// Must implement the inherited abstract method %1
+		// 8.4.3 - Every non-abstract subclass of an abstract type, A, must provide a concrete implementation of all of A's methods.
+		IProblem.EnumAbstractMethodMustBeImplemented,
+		new String[] { 
+		        new String(abstractMethod.selector),
+		        typesAsString(abstractMethod.isVarargs(), abstractMethod.parameters, false), 
+		        new String(abstractMethod.declaringClass.readableName()), 
+		},
+		new String[] { 
+		        new String(abstractMethod.selector),
+		        typesAsString(abstractMethod.isVarargs(), abstractMethod.parameters, true), 
+		        new String(abstractMethod.declaringClass.shortReadableName()), 
+		},
+		method.sourceStart(),
+		method.sourceEnd());
+}
+
 public void errorNoMethodFor(MessageSend messageSend, TypeBinding recType, TypeBinding[] params) {
 	StringBuffer buffer = new StringBuffer();
 	StringBuffer shortBuffer = new StringBuffer();
@@ -897,36 +1206,19 @@
 		reference.sourceStart,
 		reference.sourceEnd);
 }
-public void exceptionTypeProblem(SourceTypeBinding type, AbstractMethodDeclaration methodDecl, TypeReference exceptionType, TypeBinding expectedType) {
-	int problemId = expectedType.problemId();
-	int id;
-	switch (problemId) {
-		case NotFound : // 1
-			id = IProblem.ExceptionTypeNotFound;
-			break;
-		case NotVisible : // 2
-			id = IProblem.ExceptionTypeNotVisible;
-			break;
-		case Ambiguous : // 3
-			id = IProblem.ExceptionTypeAmbiguous;
-			break;
-		case InternalNameProvided : // 4
-			id = IProblem.ExceptionTypeInternalNameProvided;
-			break;
-		case InheritedNameHidesEnclosingName : // 5
-			id = IProblem.ExceptionTypeInheritedNameHidesEnclosingName;
-			break;
-		case NoError : // 0
-		default :
-			needImplementation(); // want to fail to see why we were here...
-			return;
-	}
+public void cannotInvokeSuperConstructorInEnum(ExplicitConstructorCall constructorCall, MethodBinding enumConstructor) {
 	this.handle(
-		id,
-		new String[] {new String(methodDecl.selector), new String(expectedType.readableName())},
-		new String[] {new String(methodDecl.selector), new String(expectedType.shortReadableName())},
-		exceptionType.sourceStart,
-		exceptionType.sourceEnd);
+		IProblem.CannotInvokeSuperConstructorInEnum,
+		new String[] { 
+		        new String(enumConstructor.declaringClass.sourceName()),
+		        typesAsString(enumConstructor.isVarargs(), enumConstructor.parameters, false), 
+		 },
+		new String[] { 
+		        new String(enumConstructor.declaringClass.sourceName()),
+		        typesAsString(enumConstructor.isVarargs(), enumConstructor.parameters, true), 
+		 },
+		constructorCall.sourceStart,
+		constructorCall.sourceEnd);
 }
 public void expressionShouldBeAVariable(Expression expression) {
 	this.handle(
@@ -988,37 +1280,6 @@
 		reference.sourceStart,
 		reference.sourceEnd);
 }
-public void fieldTypeProblem(SourceTypeBinding type, FieldDeclaration fieldDecl, TypeBinding expectedType) {
-	int problemId = expectedType.problemId();
-	int id;
-	switch (problemId) {
-		case NotFound : // 1
-			id = IProblem.FieldTypeNotFound;
-			break;
-		case NotVisible : // 2
-			id = IProblem.FieldTypeNotVisible;
-			break;
-		case Ambiguous : // 3
-			id = IProblem.FieldTypeAmbiguous;
-			break;
-		case InternalNameProvided : // 4
-			id = IProblem.FieldTypeInternalNameProvided;
-			break;
-		case InheritedNameHidesEnclosingName : // 5
-			id = IProblem.FieldTypeInheritedNameHidesEnclosingName;
-			break;
-		case NoError : // 0
-		default :
-			needImplementation(); // want to fail to see why we were here...
-			return;
-	}
-	this.handle(
-		id,
-		new String[] {new String(fieldDecl.name), new String(type.sourceName()), new String(expectedType.readableName())},
-		new String[] {new String(fieldDecl.name), new String(type.sourceName()), new String(expectedType.shortReadableName())},
-		fieldDecl.type.sourceStart,
-		fieldDecl.type.sourceEnd);
-}
 public void finallyMustCompleteNormally(Block finallyBlock) {
 	this.handle(
 		IProblem.FinallyMustCompleteNormally,
@@ -1037,6 +1298,24 @@
 		currentMethod.sourceStart(),
 		currentMethod.sourceEnd());
 }
+public void finalVariableBound(TypeVariableBinding typeVariable, TypeReference typeRef) {
+	this.handle(
+		IProblem.FinalBoundForTypeVariable,
+		new String[] { new String(typeVariable.sourceName), new String(typeRef.resolvedType.readableName())},
+		new String[] { new String(typeVariable.sourceName), new String(typeRef.resolvedType.shortReadableName())},
+		typeRef.sourceStart,
+		typeRef.sourceEnd);
+}
+public void forbiddenReference(TypeBinding type, ASTNode location, String messageTemplate) {
+	if (location == null) return; 
+	// this problem has a message template extracted from the access restriction rule
+	this.handle(
+		IProblem.ForbiddenReference,
+		new String[] { new String(type.readableName()) }, // distinct from msg arg for quickfix purpose
+		new String[] { Util.bindMessage(messageTemplate, new String[]{ new String(type.shortReadableName()) } ) },
+		location.sourceStart,
+		location.sourceEnd);
+}
 public void forwardReference(Reference reference, int indexInQualification, TypeBinding type) {
 	this.handle(
 		IProblem.ReferenceToForwardField,
@@ -1045,25 +1324,21 @@
 		reference.sourceStart,
 		reference.sourceEnd);
 }
-// use this private API when the compilation unit result can be found through the
-// reference context. Otherwise, use the other API taking a problem and a compilation result
-// as arguments
-private void handle(
-	int problemId, 
-	String[] problemArguments,
-	String[] messageArguments,
-	int problemStartPosition, 
-	int problemEndPosition){
-
+public void forwardTypeVariableReference(ASTNode location, TypeVariableBinding type) {
 	this.handle(
-			problemId,
-			problemArguments,
-			messageArguments,
-			problemStartPosition,
-			problemEndPosition,
-			this.referenceContext, 
-			this.referenceContext == null ? null : this.referenceContext.compilationResult()); 
-	this.referenceContext = null;
+		IProblem.ReferenceToForwardTypeVariable,
+		new String[] {new String(type.readableName())},
+		new String[] {new String(type.shortReadableName())},
+		location.sourceStart,
+		location.sourceEnd);
+}
+public void genericTypeCannotExtendThrowable(TypeDeclaration typeDecl) {
+	this.handle(
+		IProblem.GenericTypeCannotExtendThrowable,
+		new String[]{ new String(typeDecl.binding.readableName()) },
+		new String[]{ new String(typeDecl.binding.shortReadableName()) },
+		typeDecl.superclass.sourceStart,
+		typeDecl.superclass.sourceEnd);
 }
 // use this private API when the compilation unit result can be found through the
 // reference context. Otherwise, use the other API taking a problem and a compilation result
@@ -1072,7 +1347,6 @@
 	int problemId, 
 	String[] problemArguments,
 	String[] messageArguments,
-	int severity,
 	int problemStartPosition, 
 	int problemEndPosition){
 
@@ -1080,7 +1354,6 @@
 			problemId,
 			problemArguments,
 			messageArguments,
-			severity,
 			problemStartPosition,
 			problemEndPosition,
 			this.referenceContext, 
@@ -1108,6 +1381,28 @@
 			unitResult); 
 	this.referenceContext = null;
 }
+// use this private API when the compilation unit result can be found through the
+// reference context. Otherwise, use the other API taking a problem and a compilation result
+// as arguments
+private void handle(
+	int problemId, 
+	String[] problemArguments,
+	String[] messageArguments,
+	int severity,
+	int problemStartPosition, 
+	int problemEndPosition){
+
+	this.handle(
+			problemId,
+			problemArguments,
+			messageArguments,
+			severity,
+			problemStartPosition,
+			problemEndPosition,
+			this.referenceContext, 
+			this.referenceContext == null ? null : this.referenceContext.compilationResult()); 
+	this.referenceContext = null;
+}
 public void hiddenCatchBlock(ReferenceBinding exceptionType, ASTNode location) {
 	this.handle(
 		IProblem.MaskedCatch,
@@ -1132,34 +1427,27 @@
 public void hierarchyCircularity(SourceTypeBinding sourceType, ReferenceBinding superType, TypeReference reference) {
 	int start = 0;
 	int end = 0;
-	String typeName = ""; //$NON-NLS-1$
-	String shortTypeName = ""; //$NON-NLS-1$
 
 	if (reference == null) {	// can only happen when java.lang.Object is busted
 		start = sourceType.sourceStart();
 		end = sourceType.sourceEnd();
-		typeName = new String(superType.readableName());
-		shortTypeName = new String(superType.sourceName());
 	} else {
 		start = reference.sourceStart;
 		end = reference.sourceEnd;
-		char[][] qName = reference.getTypeName();
-		typeName = CharOperation.toString(qName);
-		shortTypeName = new String(qName[qName.length-1]);
 	}
 
 	if (sourceType == superType)
 		this.handle(
 			IProblem.HierarchyCircularitySelfReference,
-			new String[] {new String(sourceType.sourceName()), typeName},
-			new String[] {new String(sourceType.sourceName()), shortTypeName},
+			new String[] {new String(sourceType.readableName()) },
+			new String[] {new String(sourceType.shortReadableName()) },
 			start,
 			end);
 	else
 		this.handle(
 			IProblem.HierarchyCircularity,
-			new String[] {new String(sourceType.sourceName()), typeName},
-			new String[] {new String(sourceType.sourceName()), shortTypeName},
+			new String[] {new String(sourceType.readableName()), new String(superType.readableName())},
+			new String[] {new String(sourceType.shortReadableName()), new String(superType.shortReadableName())},
 			start,
 			end);
 }
@@ -1181,6 +1469,56 @@
 		methodDecl.sourceStart,
 		methodDecl.sourceEnd);
 }
+public void illegalClassLiteralForTypeVariable(TypeVariableBinding variable, ASTNode location) {
+	String[] arguments = new String[] { new String(variable.sourceName) };
+	this.handle(
+		IProblem.IllegalClassLiteralForTypeVariable,
+		arguments, 
+		arguments,
+		location.sourceStart,
+		location.sourceEnd);
+}
+public void illegalExtendedDimensions(AnnotationMethodDeclaration annotationTypeMemberDeclaration) {
+	this.handle(
+		IProblem.IllegalExtendedDimensions,
+		NoArgument, 
+		NoArgument, 
+		annotationTypeMemberDeclaration.sourceStart,
+		annotationTypeMemberDeclaration.sourceEnd);
+}
+public void illegalExtendedDimensions(Argument argument) {
+	this.handle(
+		IProblem.IllegalExtendedDimensionsForVarArgs,
+		NoArgument, 
+		NoArgument, 
+		argument.sourceStart,
+		argument.sourceEnd);
+}
+public void illegalGenericArray(TypeBinding leadtComponentType, ASTNode location) {
+	this.handle(
+		IProblem.IllegalGenericArray,
+		new String[]{ new String(leadtComponentType.readableName())},
+		new String[]{ new String(leadtComponentType.shortReadableName())},
+		location.sourceStart,
+		location.sourceEnd);
+}
+public void illegalInstanceOfGenericType(TypeBinding checkedType, ASTNode location) {
+	if (checkedType.isTypeVariable()) {
+		this.handle(
+		IProblem.IllegalInstanceofTypeParameter,
+			new String[] { new String(checkedType.readableName()), new String(checkedType.erasure().readableName())},
+			new String[] { new String(checkedType.shortReadableName()), new String(checkedType.erasure().shortReadableName())},
+			location.sourceStart,
+			location.sourceEnd);
+		return;
+	}
+	this.handle(
+		IProblem.IllegalInstanceofParameterizedType,
+		new String[] { new String(checkedType.readableName()), new String(checkedType.erasure().sourceName())},
+		new String[] { new String(checkedType.shortReadableName()), new String(checkedType.erasure().sourceName())},
+		location.sourceStart,
+		location.sourceEnd);
+}
 public void illegalModifierCombinationFinalAbstractForClass(SourceTypeBinding type) {
 	String[] arguments = new String[] {new String(type.sourceName())};
 	this.handle(
@@ -1210,6 +1548,42 @@
 		type.sourceStart(),
 		type.sourceEnd());
 }
+public void illegalModifierForEnum(SourceTypeBinding type) {
+	String[] arguments = new String[] {new String(type.sourceName())};
+	this.handle(
+		IProblem.IllegalModifierForEnum,
+		arguments,
+		arguments,
+		type.sourceStart(),
+		type.sourceEnd());
+}
+public void illegalModifierForLocalEnum(SourceTypeBinding type) {
+	String[] arguments = new String[] {new String(type.sourceName())};
+	this.handle(
+		IProblem.IllegalModifierForLocalEnum,
+		arguments,
+		arguments,
+		type.sourceStart(),
+		type.sourceEnd());
+}
+public void illegalModifierForMemberEnum(SourceTypeBinding type) {
+	String[] arguments = new String[] {new String(type.sourceName())};
+	this.handle(
+		IProblem.IllegalModifierForMemberEnum,
+		arguments,
+		arguments,
+		type.sourceStart(),
+		type.sourceEnd());
+}
+public void illegalModifierForEnumConstant(ReferenceBinding type, FieldDeclaration fieldDecl) {
+	String[] arguments = new String[] {new String(fieldDecl.name)};
+	this.handle(
+		IProblem.IllegalModifierForEnumConstant,
+		arguments,
+		arguments,
+		fieldDecl.sourceStart,
+		fieldDecl.sourceEnd);
+}
 public void illegalModifierForField(ReferenceBinding type, FieldDeclaration fieldDecl) {
 	String[] arguments = new String[] {new String(fieldDecl.name)};
 	this.handle(
@@ -1228,21 +1602,34 @@
 		type.sourceStart(),
 		type.sourceEnd());
 }
-public void illegalModifierForInterfaceField(ReferenceBinding type, FieldDeclaration fieldDecl) {
-	String[] arguments = new String[] {new String(fieldDecl.name)};
+public void illegalModifierForInterfaceField(FieldDeclaration fieldDecl) {
+	String name = new String(fieldDecl.name);
 	this.handle(
 		IProblem.IllegalModifierForInterfaceField,
-		arguments,
-		arguments,
+		new String[] {
+			new String(fieldDecl.binding.declaringClass.readableName()),
+			name,
+		},		
+		new String[] {
+			new String(fieldDecl.binding.declaringClass.shortReadableName()),
+			name,
+		},		
 		fieldDecl.sourceStart,
 		fieldDecl.sourceEnd);
 }
-public void illegalModifierForInterfaceMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) {
-	String[] arguments = new String[] {new String(type.sourceName()), new String(methodDecl.selector)};
+public void illegalModifierForInterfaceMethod(AbstractMethodDeclaration methodDecl) {
 	this.handle(
 		IProblem.IllegalModifierForInterfaceMethod,
-		arguments,
-		arguments,
+		new String[] {
+			new String(methodDecl.binding.declaringClass.readableName()),
+			new String(methodDecl.selector),
+			typesAsString(methodDecl.binding.isVarargs(), methodDecl.binding.parameters, false),
+		},		
+		new String[] {
+			new String(methodDecl.binding.declaringClass.shortReadableName()),
+			new String(methodDecl.selector),
+			typesAsString(methodDecl.binding.isVarargs(), methodDecl.binding.parameters, true),
+		},	
 		methodDecl.sourceStart,
 		methodDecl.sourceEnd);
 }
@@ -1273,12 +1660,67 @@
 		type.sourceStart(),
 		type.sourceEnd());
 }
-public void illegalModifierForMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) {
-	String[] arguments = new String[] {new String(type.sourceName()), new String(methodDecl.selector)};
+public void illegalModifierForAnnotationType(SourceTypeBinding type) {
+	String[] arguments = new String[] {new String(type.sourceName())};
+	this.handle(
+		IProblem.IllegalModifierForAnnotationType,
+		arguments,
+		arguments,
+		type.sourceStart(),
+		type.sourceEnd());
+}
+public void illegalModifierForAnnotationMemberType(SourceTypeBinding type) {
+	String[] arguments = new String[] {new String(type.sourceName())};
+	this.handle(
+		IProblem.IllegalModifierForAnnotationMemberType,
+		arguments,
+		arguments,
+		type.sourceStart(),
+		type.sourceEnd());
+}
+public void illegalModifierForAnnotationField(FieldDeclaration fieldDecl) {
+	String name = new String(fieldDecl.name);
+	this.handle(
+		IProblem.IllegalModifierForAnnotationField,
+		new String[] {
+			new String(fieldDecl.binding.declaringClass.readableName()),
+			name,
+		},		
+		new String[] {
+			new String(fieldDecl.binding.declaringClass.shortReadableName()),
+			name,
+		},		
+		fieldDecl.sourceStart,
+		fieldDecl.sourceEnd);
+}
+
+public void illegalModifierForAnnotationMember(AbstractMethodDeclaration methodDecl) {
+	this.handle(
+		IProblem.IllegalModifierForAnnotationMethod,
+		new String[] {
+			new String(methodDecl.binding.declaringClass.readableName()),
+			new String(methodDecl.selector),
+		},		
+		new String[] {
+			new String(methodDecl.binding.declaringClass.shortReadableName()),
+			new String(methodDecl.selector),
+		},		
+		methodDecl.sourceStart,
+		methodDecl.sourceEnd);
+}
+public void illegalModifierForMethod(AbstractMethodDeclaration methodDecl) {
 	this.handle(
 		IProblem.IllegalModifierForMethod,
-		arguments,
-		arguments,
+		new String[] {
+			new String(methodDecl.selector),
+			typesAsString(methodDecl.binding.isVarargs(), methodDecl.binding.parameters, false),
+			new String(methodDecl.binding.declaringClass.readableName()),
+		},		
+		new String[] {
+			new String(methodDecl.selector),
+			typesAsString(methodDecl.binding.isVarargs(), methodDecl.binding.parameters, true),
+			new String(methodDecl.binding.declaringClass.shortReadableName()),
+		},	
 		methodDecl.sourceStart,
 		methodDecl.sourceEnd);
 }
@@ -1310,6 +1752,30 @@
 		type.sourceStart(),
 		type.sourceEnd());
 }
+public void illegalUsageOfQualifiedTypeReference(QualifiedTypeReference qualifiedTypeReference) {
+	StringBuffer buffer = new StringBuffer();
+	char[][] tokens = qualifiedTypeReference.tokens;
+	for (int i = 0; i < tokens.length; i++) {
+		if (i > 0) buffer.append('.');
+		buffer.append(tokens[i]);
+	}
+	String[] arguments = new String[] { String.valueOf(buffer)};
+	this.handle(
+		IProblem.IllegalUsageOfQualifiedTypeReference,
+		arguments,
+		arguments,
+		qualifiedTypeReference.sourceStart,
+		qualifiedTypeReference.sourceEnd);	
+}
+public void illegalVararg(Argument argType, AbstractMethodDeclaration methodDecl) {
+	String[] arguments = new String[] {CharOperation.toString(argType.type.getTypeName()), new String(methodDecl.selector)};
+	this.handle(
+		IProblem.IllegalVararg,
+		arguments,
+		arguments,
+		argType.sourceStart,
+		argType.sourceEnd);
+}
 public void illegalVisibilityModifierCombinationForField(ReferenceBinding type, FieldDeclaration fieldDecl) {
 	String[] arguments = new String[] {new String(fieldDecl.name)};
 	this.handle(
@@ -1355,34 +1821,31 @@
 		location.sourceEnd);
 }
 public void importProblem(ImportReference importRef, Binding expectedImport) {
-	int problemId = expectedImport.problemId();
-	int id;
-	switch (problemId) {
-		case NotFound : // 1
-			id = IProblem.ImportNotFound;
-			break;
-		case NotVisible : // 2
-			id = IProblem.ImportNotVisible;
-			break;
-		case Ambiguous : // 3
-			id = IProblem.ImportAmbiguous;
-			break;
-		case InternalNameProvided : // 4
-			id = IProblem.ImportInternalNameProvided;
-			break;
-		case InheritedNameHidesEnclosingName : // 5
-			id = IProblem.ImportInheritedNameHidesEnclosingName;
-			break;
-		case NoError : // 0
-		default :
-			needImplementation(); // want to fail to see why we were here...
-			return;
+	if (expectedImport.problemId() == NotFound) {
+		char[][] tokens = expectedImport instanceof ProblemReferenceBinding
+			? ((ProblemReferenceBinding) expectedImport).compoundName
+			: importRef.tokens;
+		String[] arguments = new String[]{CharOperation.toString(tokens)};
+		this.handle(
+		        IProblem.ImportNotFound, 
+		        arguments, 
+		        arguments, 
+		        importRef.sourceStart, 
+		        (int) importRef.sourcePositions[tokens.length - 1]);
+		return;
 	}
-	char[][] tokens = expectedImport instanceof ProblemReferenceBinding
-		? ((ProblemReferenceBinding) expectedImport).compoundName
-		: importRef.tokens;
-	String[] arguments = new String[]{CharOperation.toString(tokens)};
-	this.handle(id, arguments, arguments, importRef.sourceStart, (int) importRef.sourcePositions[tokens.length - 1]);
+	if (expectedImport.problemId() == InvalidTypeForStaticImport) {
+		char[][] tokens = importRef.tokens;
+		String[] arguments = new String[]{CharOperation.toString(tokens)};
+		this.handle(
+		        IProblem.InvalidTypeForStaticImport, 
+		        arguments, 
+		        arguments, 
+		        importRef.sourceStart, 
+		        (int) importRef.sourcePositions[tokens.length - 1]);
+		return;
+	}
+	invalidType(importRef, (TypeBinding)expectedImport);
 }
 public void incompatibleExceptionInThrowsClause(SourceTypeBinding type, MethodBinding currentMethod, MethodBinding inheritedMethod, ReferenceBinding exceptionType) {
 	if (type == currentMethod.declaringClass) {
@@ -1472,13 +1935,46 @@
 		currentMethod.sourceStart(),
 		currentMethod.sourceEnd());
 }
-public void incorrectLocationForEmptyDimension(ArrayAllocationExpression expression, int index) {
+public void disallowedTargetForAnnotation(Annotation annotation) {
+	this.handle(
+		IProblem.DisallowedTargetForAnnotation,
+		new String[] {new String(annotation.resolvedType.readableName())},
+		new String[] {new String(annotation.resolvedType.shortReadableName())},
+		annotation.sourceStart,
+		annotation.sourceEnd);
+}
+public void incorrectArityForParameterizedType(ASTNode location, TypeBinding type, TypeBinding[] argumentTypes) {
+    if (location == null) {
+		this.handle(
+			IProblem.IncorrectArityForParameterizedType,
+			new String[] {new String(type.readableName()), typesAsString(false, argumentTypes, false)},
+			new String[] {new String(type.shortReadableName()), typesAsString(false, argumentTypes, true)},
+			AbortCompilation | Error,
+			0,
+			1);        
+    }
+	this.handle(
+		IProblem.IncorrectArityForParameterizedType,
+		new String[] {new String(type.readableName()), typesAsString(false, argumentTypes, false)},
+		new String[] {new String(type.shortReadableName()), typesAsString(false, argumentTypes, true)},
+		location.sourceStart,
+		location.sourceEnd);
+}
+public void incorrectLocationForNonEmptyDimension(ArrayAllocationExpression expression, int index) {
 	this.handle(
 		IProblem.IllegalDimension,
 		NoArgument,
 		NoArgument,
-		expression.dimensions[index + 1].sourceStart,
-		expression.dimensions[index + 1].sourceEnd);
+		expression.dimensions[index].sourceStart,
+		expression.dimensions[index].sourceEnd);
+}
+public void incorrectSwitchType(Expression expression, TypeBinding testType) {
+	this.handle(
+		IProblem.IncorrectSwitchType,
+		new String[] {new String(testType.readableName())},
+		new String[] {new String(testType.shortReadableName())},
+		expression.sourceStart,
+		expression.sourceEnd);
 }
 public void indirectAccessToStaticField(ASTNode location, FieldBinding field){
 	this.handle(
@@ -1491,8 +1987,8 @@
 public void indirectAccessToStaticMethod(ASTNode location, MethodBinding method) {
 	this.handle(
 		IProblem.IndirectAccessToStaticMethod,
-		new String[] {new String(method.declaringClass.readableName()), new String(method.selector), parametersAsString(method)},
-		new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), parametersAsShortString(method)},
+		new String[] {new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method.isVarargs(), method.parameters, false)},
+		new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method.isVarargs(), method.parameters, true)},
 		location.sourceStart,
 		location.sourceEnd);
 }
@@ -1504,14 +2000,26 @@
 		location.sourceStart,
 		location.sourceEnd);
 }
-public void incorrectSwitchType(Expression expression, TypeBinding testType) {
+public void inheritedMethodsHaveNameClash(SourceTypeBinding type, MethodBinding oneMethod, MethodBinding twoMethod) {
 	this.handle(
-		IProblem.IncorrectSwitchType,
-		new String[] {new String(testType.readableName())},
-		new String[] {new String(testType.shortReadableName())},
-		expression.sourceStart,
-		expression.sourceEnd);
-}
+		IProblem.MethodNameClash,
+		new String[] {
+			new String(oneMethod.selector),
+			typesAsString(oneMethod.original().isVarargs(), oneMethod.original().parameters, false),
+			new String(oneMethod.declaringClass.readableName()),
+			typesAsString(twoMethod.original().isVarargs(), twoMethod.original().parameters, false),
+			new String(twoMethod.declaringClass.readableName()),
+		 }, 
+		new String[] {
+			new String(oneMethod.selector),
+			typesAsString(oneMethod.original().isVarargs(), oneMethod.original().parameters, true),
+			new String(oneMethod.declaringClass.shortReadableName()),
+			typesAsString(twoMethod.original().isVarargs(), twoMethod.original().parameters, true),
+			new String(twoMethod.declaringClass.shortReadableName()),
+		 }, 
+		 type.sourceStart(),
+		 type.sourceEnd());
+}	
 public void inheritedMethodReducesVisibility(SourceTypeBinding type, MethodBinding concreteMethod, MethodBinding[] abstractMethods) {
 	StringBuffer concreteSignature = new StringBuffer();
 	concreteSignature
@@ -1598,6 +2106,23 @@
 		fieldDecl.sourceStart,
 		fieldDecl.sourceEnd);
 }
+public void invalidAnnotationMemberType(MethodDeclaration methodDecl) {
+	this.handle(
+		IProblem.InvalidAnnotationMemberType,
+		new String[] {
+			new String(methodDecl.binding.returnType.readableName()),
+			new String(methodDecl.selector),
+			new String(methodDecl.binding.declaringClass.readableName()),
+		},
+		new String[] {
+			new String(methodDecl.binding.returnType.shortReadableName()),
+			new String(methodDecl.selector),
+			new String(methodDecl.binding.declaringClass.shortReadableName()),
+		},
+		methodDecl.returnType.sourceStart,
+		methodDecl.returnType.sourceEnd);
+	
+}
 public void invalidBreak(ASTNode location) {
 	this.handle(
 		IProblem.InvalidBreak,
@@ -1615,7 +2140,18 @@
 		(statement instanceof ExplicitConstructorCall)
 			&& (((ExplicitConstructorCall) statement).accessMode == ExplicitConstructorCall.ImplicitSuper);
 
+	int sourceStart = statement.sourceStart;
+	int sourceEnd = statement.sourceEnd;
+	if (statement instanceof AllocationExpression) {
+		AllocationExpression allocation = (AllocationExpression)statement;
+		if (allocation.enumConstant != null) {
+			sourceStart = allocation.enumConstant.sourceStart;
+			sourceEnd = allocation.enumConstant.sourceEnd;
+		}
+	}
+	
 	int id = IProblem.UndefinedConstructor; //default...
+    MethodBinding shownConstructor = targetConstructor;
 	switch (targetConstructor.problemId()) {
 		case NotFound :
 			if (insideDefaultConstructor){
@@ -1634,6 +2170,10 @@
 			} else {
 				id = IProblem.NotVisibleConstructor;
 			}
+			ProblemMethodBinding problemConstructor = (ProblemMethodBinding) targetConstructor;
+			if (problemConstructor.closestMatch != null) {
+			    shownConstructor = problemConstructor.closestMatch.original();
+		    }					
 			break;
 		case Ambiguous :
 			if (insideDefaultConstructor){
@@ -1644,6 +2184,109 @@
 				id = IProblem.AmbiguousConstructor;
 			}
 			break;
+		case ParameterBoundMismatch :
+			problemConstructor = (ProblemMethodBinding) targetConstructor;
+			ParameterizedGenericMethodBinding substitutedConstructor = (ParameterizedGenericMethodBinding) problemConstructor.closestMatch;
+			shownConstructor = substitutedConstructor.original();
+			TypeBinding typeArgument = targetConstructor.parameters[0];
+			TypeVariableBinding typeParameter = (TypeVariableBinding) targetConstructor.parameters[1];
+			this.handle(
+				IProblem.GenericConstructorTypeArgumentMismatch,
+				new String[] { 
+				        new String(shownConstructor.declaringClass.sourceName()),
+				        typesAsString(shownConstructor.isVarargs(), shownConstructor.parameters, false), 
+				        new String(shownConstructor.declaringClass.readableName()), 
+				        typesAsString(substitutedConstructor.isVarargs(), substitutedConstructor.parameters, false), 
+				        new String(typeArgument.readableName()), 
+				        new String(typeParameter.sourceName), 
+				        parameterBoundAsString(typeParameter, false) },
+				new String[] { 
+				        new String(shownConstructor.declaringClass.sourceName()),
+				        typesAsString(shownConstructor.isVarargs(), shownConstructor.parameters, true), 
+				        new String(shownConstructor.declaringClass.shortReadableName()), 
+				        typesAsString(substitutedConstructor.isVarargs(), substitutedConstructor.parameters, true), 
+				        new String(typeArgument.shortReadableName()), 
+				        new String(typeParameter.sourceName), 
+				        parameterBoundAsString(typeParameter, true) },
+				sourceStart,
+				sourceEnd);		    
+			return;		    
+			
+		case TypeParameterArityMismatch :
+			problemConstructor = (ProblemMethodBinding) targetConstructor;
+			shownConstructor = problemConstructor.closestMatch;
+			if (shownConstructor.typeVariables == TypeConstants.NoTypeVariables) {
+				this.handle(
+					IProblem.NonGenericConstructor,
+					new String[] { 
+					        new String(shownConstructor.declaringClass.sourceName()),
+					        typesAsString(shownConstructor.isVarargs(), shownConstructor.parameters, false), 
+					        new String(shownConstructor.declaringClass.readableName()), 
+					        typesAsString(targetConstructor.isVarargs(), targetConstructor.parameters, false) },
+					new String[] { 
+					        new String(shownConstructor.declaringClass.sourceName()),
+					        typesAsString(shownConstructor.isVarargs(), shownConstructor.parameters, true), 
+					        new String(shownConstructor.declaringClass.shortReadableName()), 
+					        typesAsString(targetConstructor.isVarargs(), targetConstructor.parameters, true) },
+					sourceStart,
+					sourceEnd);		    
+			} else {
+				this.handle(
+					IProblem.IncorrectArityForParameterizedConstructor  ,
+					new String[] { 
+					        new String(shownConstructor.declaringClass.sourceName()),
+					        typesAsString(shownConstructor.isVarargs(), shownConstructor.parameters, false), 
+					        new String(shownConstructor.declaringClass.readableName()), 
+							typesAsString(false, shownConstructor.typeVariables, false),
+					        typesAsString(targetConstructor.isVarargs(), targetConstructor.parameters, false) },
+					new String[] { 
+					        new String(shownConstructor.declaringClass.sourceName()),
+					        typesAsString(shownConstructor.isVarargs(), shownConstructor.parameters, true), 
+					        new String(shownConstructor.declaringClass.shortReadableName()), 
+							typesAsString(false, shownConstructor.typeVariables, true),
+					        typesAsString(targetConstructor.isVarargs(), targetConstructor.parameters, true) },
+					sourceStart,
+					sourceEnd);		    
+			}
+			return;
+		case ParameterizedMethodTypeMismatch :
+			problemConstructor = (ProblemMethodBinding) targetConstructor;
+			shownConstructor = problemConstructor.closestMatch;
+			this.handle(
+				IProblem.ParameterizedConstructorArgumentTypeMismatch,
+				new String[] { 
+				        new String(shownConstructor.declaringClass.sourceName()),
+				        typesAsString(shownConstructor.isVarargs(), shownConstructor.parameters, false), 
+				        new String(shownConstructor.declaringClass.readableName()), 
+						typesAsString(false, ((ParameterizedGenericMethodBinding)shownConstructor).typeArguments, false),
+				        typesAsString(targetConstructor.isVarargs(), targetConstructor.parameters, false) },
+				new String[] { 
+				        new String(shownConstructor.declaringClass.sourceName()),
+				        typesAsString(shownConstructor.isVarargs(), shownConstructor.parameters, true), 
+				        new String(shownConstructor.declaringClass.shortReadableName()), 
+						typesAsString(false, ((ParameterizedGenericMethodBinding)shownConstructor).typeArguments, true),
+				        typesAsString(targetConstructor.isVarargs(), targetConstructor.parameters, true) },
+				sourceStart,
+				sourceEnd);		    
+			return;
+		case TypeArgumentsForRawGenericMethod :
+			problemConstructor = (ProblemMethodBinding) targetConstructor;
+			shownConstructor = problemConstructor.closestMatch;
+			this.handle(
+				IProblem.TypeArgumentsForRawGenericConstructor,
+				new String[] { 
+				        new String(shownConstructor.declaringClass.sourceName()),
+				        typesAsString(shownConstructor.isVarargs(), shownConstructor.parameters, false), 
+				        new String(shownConstructor.declaringClass.readableName()), 
+				        typesAsString(targetConstructor.isVarargs(), targetConstructor.parameters, false) },
+				new String[] { 
+				        new String(shownConstructor.declaringClass.sourceName()),
+				        typesAsString(shownConstructor.isVarargs(), shownConstructor.parameters, true), 
+				        new String(shownConstructor.declaringClass.shortReadableName()), 
+				        typesAsString(targetConstructor.isVarargs(), targetConstructor.parameters, true) },
+				sourceStart,
+				sourceEnd);	
+			return;
 		case NoError : // 0
 		default :
 			needImplementation(); // want to fail to see why we were here...
@@ -1652,20 +2295,10 @@
 
 	this.handle(
 		id,
-		new String[] {new String(targetConstructor.declaringClass.readableName()), parametersAsString(targetConstructor)},
-		new String[] {new String(targetConstructor.declaringClass.shortReadableName()), parametersAsShortString(targetConstructor)},
-		statement.sourceStart,
-		statement.sourceEnd);
-}
-
-public void invalidExplicitConstructorCall(ASTNode location) {
-	
-	this.handle(
-		IProblem.InvalidExplicitConstructorCall,
-		NoArgument,
-		NoArgument,
-		location.sourceStart,
-		location.sourceEnd);
+		new String[] {new String(targetConstructor.declaringClass.readableName()), typesAsString(shownConstructor.isVarargs(), shownConstructor.parameters, false)},
+		new String[] {new String(targetConstructor.declaringClass.shortReadableName()), typesAsString(shownConstructor.isVarargs(), shownConstructor.parameters, true)},
+		sourceStart,
+		sourceEnd);
 }
 public void invalidContinue(ASTNode location) {
 	this.handle(
@@ -1705,6 +2338,17 @@
 		expression.sourceStart,
 		expression.sourceEnd);
 }
+
+public void invalidExplicitConstructorCall(ASTNode location) {
+	
+	this.handle(
+		IProblem.InvalidExplicitConstructorCall,
+		NoArgument,
+		NoArgument,
+		location.sourceStart,
+		location.sourceEnd);
+}
+
 public void invalidExpressionAsStatement(Expression expression){
 	this.handle(
 		IProblem.InvalidExpressionAsStatement,
@@ -1874,23 +2518,56 @@
 		nameRef.sourceStart, 
 		(int) nameRef.sourcePositions[index]);
 }
+public void invalidFileNameForPackageAnnotations(Annotation annotation) {
+	this.handle(
+			IProblem.InvalidFileNameForPackageAnnotations,
+			NoArgument,
+			NoArgument,
+			annotation.sourceStart,
+			annotation.sourceEnd);	
+}
 public void invalidMethod(MessageSend messageSend, MethodBinding method) {
-	// CODE should be UPDATED according to error coding in the different method binding errors
-	// The different targetted errors should be :
-	// 	UndefinedMethod
-	//	NotVisibleMethod
-	//	AmbiguousMethod
-	//  InheritedNameHidesEnclosingName
-	//	InstanceMethodDuringConstructorInvocation
-	// StaticMethodRequested
-
 	int id = IProblem.UndefinedMethod; //default...
+    MethodBinding shownMethod = method;
 	switch (method.problemId()) {
 		case NotFound :
 			id = IProblem.UndefinedMethod;
+			ProblemMethodBinding problemMethod = (ProblemMethodBinding) method;
+			if (problemMethod.closestMatch != null) {
+			    	shownMethod = problemMethod.closestMatch;
+					String closestParameterTypeNames = typesAsString(shownMethod.isVarargs(), shownMethod.parameters, false);
+					String parameterTypeNames = typesAsString(method.isVarargs(), method.parameters, false);
+					String closestParameterTypeShortNames = typesAsString(shownMethod.isVarargs(), shownMethod.parameters, true);
+					String parameterTypeShortNames = typesAsString(method.isVarargs(), method.parameters, true);
+					if (closestParameterTypeShortNames.equals(parameterTypeShortNames)){
+						closestParameterTypeShortNames = closestParameterTypeNames;
+						parameterTypeShortNames = parameterTypeNames;
+					}
+					this.handle(
+						IProblem.ParameterMismatch,
+						new String[] {
+							new String(shownMethod.declaringClass.readableName()),
+							new String(shownMethod.selector),
+							closestParameterTypeNames,
+							parameterTypeNames 
+						},
+						new String[] {
+							new String(shownMethod.declaringClass.shortReadableName()),
+							new String(shownMethod.selector),
+							closestParameterTypeShortNames,
+							parameterTypeShortNames
+						},
+						(int) (messageSend.nameSourcePosition >>> 32),
+						(int) messageSend.nameSourcePosition);
+					return;
+			}			
 			break;
 		case NotVisible :
 			id = IProblem.NotVisibleMethod;
+			problemMethod = (ProblemMethodBinding) method;
+			if (problemMethod.closestMatch != null) {
+			    shownMethod = problemMethod.closestMatch.original();
+		    }			
 			break;
 		case Ambiguous :
 			id = IProblem.AmbiguousMethod;
@@ -1912,53 +2589,122 @@
 				messageSend.receiver.sourceStart,
 				messageSend.receiver.sourceEnd);
 			return;
-		
+		case ParameterBoundMismatch :
+			problemMethod = (ProblemMethodBinding) method;
+			ParameterizedGenericMethodBinding substitutedMethod = (ParameterizedGenericMethodBinding) problemMethod.closestMatch;
+			shownMethod = substitutedMethod.original();
+			TypeBinding typeArgument = method.parameters[0];
+			TypeVariableBinding typeParameter = (TypeVariableBinding) method.parameters[1];
+			this.handle(
+				IProblem.GenericMethodTypeArgumentMismatch,
+				new String[] { 
+				        new String(shownMethod.selector),
+				        typesAsString(shownMethod.isVarargs(), shownMethod.parameters, false), 
+				        new String(shownMethod.declaringClass.readableName()), 
+				        typesAsString(substitutedMethod.isVarargs(), substitutedMethod.parameters, false), 
+				        new String(typeArgument.readableName()), 
+				        new String(typeParameter.sourceName), 
+				        parameterBoundAsString(typeParameter, false) },
+				new String[] { 
+				        new String(shownMethod.selector),
+				        typesAsString(shownMethod.isVarargs(), shownMethod.parameters, true), 
+				        new String(shownMethod.declaringClass.shortReadableName()), 
+				        typesAsString(substitutedMethod.isVarargs(), substitutedMethod.parameters, true), 
+				        new String(typeArgument.shortReadableName()), 
+				        new String(typeParameter.sourceName), 
+				        parameterBoundAsString(typeParameter, true) },
+				(int) (messageSend.nameSourcePosition >>> 32),
+				(int) messageSend.nameSourcePosition);		    
+			return;
+		case TypeParameterArityMismatch :
+			problemMethod = (ProblemMethodBinding) method;
+			shownMethod = problemMethod.closestMatch;
+			if (shownMethod.typeVariables == TypeConstants.NoTypeVariables) {
+				this.handle(
+					IProblem.NonGenericMethod ,
+					new String[] { 
+					        new String(shownMethod.selector),
+					        typesAsString(shownMethod.isVarargs(), shownMethod.parameters, false), 
+					        new String(shownMethod.declaringClass.readableName()), 
+					        typesAsString(method.isVarargs(), method.parameters, false) },
+					new String[] { 
+					        new String(shownMethod.selector),
+					        typesAsString(shownMethod.isVarargs(), shownMethod.parameters, true), 
+					        new String(shownMethod.declaringClass.shortReadableName()), 
+					        typesAsString(method.isVarargs(), method.parameters, true) },
+					(int) (messageSend.nameSourcePosition >>> 32),
+					(int) messageSend.nameSourcePosition);		    
+			} else {
+				this.handle(
+					IProblem.IncorrectArityForParameterizedMethod  ,
+					new String[] { 
+					        new String(shownMethod.selector),
+					        typesAsString(shownMethod.isVarargs(), shownMethod.parameters, false), 
+					        new String(shownMethod.declaringClass.readableName()), 
+							typesAsString(false, shownMethod.typeVariables, false),
+					        typesAsString(method.isVarargs(), method.parameters, false) },
+					new String[] { 
+					        new String(shownMethod.selector),
+					        typesAsString(shownMethod.isVarargs(), shownMethod.parameters, true), 
+					        new String(shownMethod.declaringClass.shortReadableName()), 
+							typesAsString(false, shownMethod.typeVariables, true),
+					        typesAsString(method.isVarargs(), method.parameters, true) },
+					(int) (messageSend.nameSourcePosition >>> 32),
+					(int) messageSend.nameSourcePosition);		    
+			}
+			return;
+		case ParameterizedMethodTypeMismatch :
+			problemMethod = (ProblemMethodBinding) method;
+			shownMethod = problemMethod.closestMatch;
+			this.handle(
+				IProblem.ParameterizedMethodArgumentTypeMismatch,
+				new String[] { 
+				        new String(shownMethod.selector),
+				        typesAsString(shownMethod.isVarargs(), shownMethod.parameters, false), 
+				        new String(shownMethod.declaringClass.readableName()), 
+						typesAsString(false, ((ParameterizedGenericMethodBinding)shownMethod).typeArguments, false),
+				        typesAsString(method.isVarargs(), method.parameters, false) },
+				new String[] { 
+				        new String(shownMethod.selector),
+				        typesAsString(shownMethod.isVarargs(), shownMethod.parameters, true), 
+				        new String(shownMethod.declaringClass.shortReadableName()), 
+						typesAsString(false, ((ParameterizedGenericMethodBinding)shownMethod).typeArguments, true),
+				        typesAsString(method.isVarargs(), method.parameters, true) },
+				(int) (messageSend.nameSourcePosition >>> 32),
+				(int) messageSend.nameSourcePosition);		    
+			return;
+		case TypeArgumentsForRawGenericMethod :
+			problemMethod = (ProblemMethodBinding) method;
+			shownMethod = problemMethod.closestMatch;
+			this.handle(
+				IProblem.TypeArgumentsForRawGenericMethod ,
+				new String[] { 
+				        new String(shownMethod.selector),
+				        typesAsString(shownMethod.isVarargs(), shownMethod.parameters, false), 
+				        new String(shownMethod.declaringClass.readableName()), 
+				        typesAsString(method.isVarargs(), method.parameters, false) },
+				new String[] { 
+				        new String(shownMethod.selector),
+				        typesAsString(shownMethod.isVarargs(), shownMethod.parameters, true), 
+				        new String(shownMethod.declaringClass.shortReadableName()), 
+				        typesAsString(method.isVarargs(), method.parameters, true) },
+				(int) (messageSend.nameSourcePosition >>> 32),
+				(int) messageSend.nameSourcePosition);		       
+			return;
 		case NoError : // 0
 		default :
 			needImplementation(); // want to fail to see why we were here...
 			break;
 	}
 
-	if (id == IProblem.UndefinedMethod) {
-		ProblemMethodBinding problemMethod = (ProblemMethodBinding) method;
-		if (problemMethod.closestMatch != null) {
-				String closestParameterTypeNames = parametersAsString(problemMethod.closestMatch);
-				String parameterTypeNames = parametersAsString(method);
-				String closestParameterTypeShortNames = parametersAsShortString(problemMethod.closestMatch);
-				String parameterTypeShortNames = parametersAsShortString(method);
-				if (closestParameterTypeShortNames.equals(parameterTypeShortNames)){
-					closestParameterTypeShortNames = closestParameterTypeNames;
-					parameterTypeShortNames = parameterTypeNames;
-				}
-				id = IProblem.ParameterMismatch;
-				this.handle(
-					id,
-					new String[] {
-						new String(problemMethod.closestMatch.declaringClass.readableName()),
-						new String(problemMethod.closestMatch.selector),
-						closestParameterTypeNames,
-						parameterTypeNames 
-					},
-					new String[] {
-						new String(problemMethod.closestMatch.declaringClass.shortReadableName()),
-						new String(problemMethod.closestMatch.selector),
-						closestParameterTypeShortNames,
-						parameterTypeShortNames
-					},
-					(int) (messageSend.nameSourcePosition >>> 32),
-					(int) messageSend.nameSourcePosition);
-				return;
-		}
-	}
-
 	this.handle(
 		id,
 		new String[] {
 			new String(method.declaringClass.readableName()),
-			new String(method.selector), parametersAsString(method)},
+			new String(shownMethod.selector), typesAsString(shownMethod.isVarargs(), shownMethod.parameters, false)},
 		new String[] {
 			new String(method.declaringClass.shortReadableName()),
-			new String(method.selector), parametersAsShortString(method)},
+			new String(shownMethod.selector), typesAsString(shownMethod.isVarargs(), shownMethod.parameters, true)},
 		(int) (messageSend.nameSourcePosition >>> 32),
 		(int) messageSend.nameSourcePosition);
 }
@@ -2018,6 +2764,14 @@
 		expression.sourceStart,
 		expression.sourceEnd);
 }
+public void invalidParameterizedExceptionType(TypeBinding exceptionType, ASTNode location) {
+	this.handle(
+		IProblem.InvalidParameterizedExceptionType,
+		new String[] {new String(exceptionType.readableName())},
+		new String[] {new String(exceptionType.shortReadableName())},
+		location.sourceStart,
+		location.sourceEnd);
+}
 public void invalidParenthesizedExpression(ASTNode reference) {
 	this.handle(
 		IProblem.InvalidParenthesizedExpression,
@@ -2026,68 +2780,6 @@
 		reference.sourceStart,
 		reference.sourceEnd);
 }
-public void invalidSuperclass(SourceTypeBinding type, TypeReference superclassRef, ReferenceBinding expectedType) {
-	int problemId = expectedType.problemId();
-	int id;
-	switch (problemId) {
-		case NotFound : // 1
-			id = IProblem.SuperclassNotFound;
-			break;
-		case NotVisible : // 2
-			id = IProblem.SuperclassNotVisible;
-			break;
-		case Ambiguous : // 3
-			id = IProblem.SuperclassAmbiguous;
-			break;
-		case InternalNameProvided : // 4
-			id = IProblem.SuperclassInternalNameProvided;
-			break;
-		case InheritedNameHidesEnclosingName : // 5
-			id = IProblem.SuperclassInheritedNameHidesEnclosingName;
-			break;
-		case NoError : // 0
-		default :
-			needImplementation(); // want to fail to see why we were here...
-			return;
-	}
-	this.handle(
-		id,
-		new String[] {new String(expectedType.readableName()), new String(type.sourceName())},
-		new String[] {new String(expectedType.shortReadableName()), new String(type.sourceName())},
-		superclassRef.sourceStart,
-		superclassRef.sourceEnd);
-}
-public void invalidSuperinterface(SourceTypeBinding type, TypeReference superinterfaceRef, ReferenceBinding expectedType) {
-	int problemId = expectedType.problemId();
-	int id;
-	switch (problemId) {
-		case NotFound : // 1
-			id = IProblem.InterfaceNotFound;
-			break;
-		case NotVisible : // 2
-			id = IProblem.InterfaceNotVisible;
-			break;
-		case Ambiguous : // 3
-			id = IProblem.InterfaceAmbiguous;
-			break;
-		case InternalNameProvided : // 4
-			id = IProblem.InterfaceInternalNameProvided;
-			break;
-		case InheritedNameHidesEnclosingName : // 5
-			id = IProblem.InterfaceInheritedNameHidesEnclosingName;
-			break;
-		case NoError : // 0
-		default :
-			needImplementation(); // want to fail to see why we were here...
-			return;
-	}
-		this.handle(
-			id,
-			new String[] {new String(expectedType.readableName()), new String(type.sourceName())},
-			new String[] {new String(expectedType.shortReadableName()), new String(type.sourceName())},
-			superinterfaceRef.sourceStart,
-			superinterfaceRef.sourceEnd);
-}
 public void invalidType(ASTNode location, TypeBinding type) {
 	int id = IProblem.UndefinedType; // default
 	switch (type.problemId()) {
@@ -2106,6 +2798,12 @@
 		case InheritedNameHidesEnclosingName :
 			id = IProblem.InheritedTypeHidesEnclosingName;
 			break;
+		case NonStaticReferenceInStaticContext :
+			id = IProblem.TypeVariableReferenceFromStaticContext;
+		    break;
+		case IllegalSuperTypeVariable : 
+		    id = IProblem.IllegalTypeVariableSuperReference;
+		    break;
 		case NoError : // 0
 		default :
 			needImplementation(); // want to fail to see why we were here...
@@ -2117,14 +2815,45 @@
 		QualifiedNameReference ref = (QualifiedNameReference) location;
 		if (ref.indexOfFirstFieldBinding >= 1)
 			end = (int) ref.sourcePositions[ref.indexOfFirstFieldBinding - 1];
+	} else if (location instanceof ArrayQualifiedTypeReference) {
+		if (!(location instanceof ParameterizedQualifiedTypeReference)) {
+			ArrayQualifiedTypeReference arrayQualifiedTypeReference = (ArrayQualifiedTypeReference) location;
+			long[] positions = arrayQualifiedTypeReference.sourcePositions;
+			end = (int) positions[positions.length - 1];
+		}
+	} else if (location instanceof QualifiedTypeReference) {
+		QualifiedTypeReference ref = (QualifiedTypeReference) location;
+		if (type instanceof ReferenceBinding) {
+			char[][] name = ((ReferenceBinding) type).compoundName;
+			end = (int) ref.sourcePositions[name.length - 1];
+		}
+	} else if (location instanceof ImportReference) {
+		ImportReference ref = (ImportReference) location;
+		if (type instanceof ReferenceBinding) {
+			char[][] name = ((ReferenceBinding) type).compoundName;
+			end = (int) ref.sourcePositions[name.length - 1];
+		}
+	} else if (location instanceof ArrayTypeReference) {
+		if (!(location instanceof ParameterizedSingleTypeReference)) {
+			ArrayTypeReference arrayTypeReference = (ArrayTypeReference) location;
+			end = arrayTypeReference.originalSourceEnd;
+		}
 	}
 	this.handle(
 		id,
-		new String[] {new String(type.readableName())},
-		new String[] {new String(type.shortReadableName())},
+		new String[] {new String(type.leafComponentType().readableName()) },	
+		new String[] {new String(type.leafComponentType().shortReadableName())},
 		location.sourceStart,
 		end);
 }
+public void invalidTypeForCollection(Expression expression) {
+	this.handle(
+			IProblem.InvalidTypeForCollection,
+			NoArgument,
+			NoArgument,
+			expression.sourceStart,
+			expression.sourceEnd);
+}
 public void invalidTypeReference(Expression expression) {
 	this.handle(
 		IProblem.InvalidTypeExpression,
@@ -2141,6 +2870,14 @@
 		expression.sourceStart,
 		expression.sourceEnd);
 }
+public void invalidTypeVariableAsException(TypeBinding exceptionType, ASTNode location) {
+	this.handle(
+		IProblem.InvalidTypeVariableExceptionType,
+		new String[] {new String(exceptionType.readableName())},
+		new String[] {new String(exceptionType.shortReadableName())},
+		location.sourceStart,
+		location.sourceEnd);
+}
 public void invalidUnaryExpression(Expression expression) {
 	this.handle(
 		IProblem.InvalidUnaryExpression,
@@ -2149,6 +2886,70 @@
 		expression.sourceStart,
 		expression.sourceEnd);
 }
+public void invalidUsageOfAnnotation(Annotation annotation) {
+	this.handle(
+		IProblem.InvalidUsageOfAnnotations,
+		NoArgument, 
+		NoArgument,
+		annotation.sourceStart,
+		annotation.sourceEnd);	
+}
+public void invalidUsageOfAnnotationDeclarations(TypeDeclaration annotationTypeDeclaration) {
+	this.handle(
+		IProblem.InvalidUsageOfAnnotationDeclarations,
+		NoArgument, 
+		NoArgument, 
+		annotationTypeDeclaration.sourceStart,
+		annotationTypeDeclaration.sourceEnd);
+}
+public void invalidUsageOfEnumDeclarations(TypeDeclaration enumDeclaration) {
+	this.handle(
+		IProblem.InvalidUsageOfEnumDeclarations,
+		NoArgument, 
+		NoArgument, 
+		enumDeclaration.sourceStart,
+		enumDeclaration.sourceEnd);
+}
+public void invalidUsageOfForeachStatements(LocalDeclaration elementVariable, Expression collection) {
+	this.handle(
+		IProblem.InvalidUsageOfForeachStatements,
+		NoArgument, 
+		NoArgument, 
+		elementVariable.declarationSourceStart,
+		collection.sourceEnd);
+}
+public void invalidUsageOfStaticImports(ImportReference staticImport) {
+	this.handle(
+		IProblem.InvalidUsageOfStaticImports,
+		NoArgument, 
+		NoArgument, 
+		staticImport.declarationSourceStart,
+		staticImport.declarationSourceEnd);
+}
+public void invalidUsageOfTypeArguments(TypeReference firstTypeReference, TypeReference lastTypeReference) {
+	this.handle(
+		IProblem.InvalidUsageOfTypeArguments,
+		NoArgument, 
+		NoArgument, 
+		firstTypeReference.sourceStart,
+		lastTypeReference.sourceEnd);
+}
+public void invalidUsageOfTypeParameters(TypeParameter firstTypeParameter, TypeParameter lastTypeParameter) {
+	this.handle(
+		IProblem.InvalidUsageOfTypeParameters,
+		NoArgument, 
+		NoArgument, 
+		firstTypeParameter.declarationSourceStart,
+		lastTypeParameter.declarationSourceEnd);
+}
+public void invalidUsageOfVarargs(Argument argument) {
+	this.handle(
+		IProblem.InvalidUsageOfVarargs,
+		NoArgument, 
+		NoArgument, 
+		argument.type.sourceStart,
+		argument.sourceEnd);
+}
 public void isClassPathCorrect(char[][] wellKnownTypeName, CompilationUnitDeclaration compUnitDecl) {
 	this.referenceContext = compUnitDecl;
 	String[] arguments = new String[] {CharOperation.toString(wellKnownTypeName)};
@@ -2160,8 +2961,88 @@
 		0,
 		0);
 }
-public void javadocDuplicatedReturnTag(int sourceStart, int sourceEnd){
-	this.handle(IProblem.JavadocDuplicateReturnTag, NoArgument, NoArgument, sourceStart, sourceEnd);
+
+private boolean isIdentifier(int token) {
+	return token == TerminalTokens.TokenNameIdentifier;
+}
+
+private boolean isKeyword(int token) {
+	switch(token) {
+		case TerminalTokens.TokenNameabstract:
+		case TerminalTokens.TokenNameassert:
+		case TerminalTokens.TokenNamebyte:
+		case TerminalTokens.TokenNamebreak:
+		case TerminalTokens.TokenNameboolean:
+		case TerminalTokens.TokenNamecase:
+		case TerminalTokens.TokenNamechar:
+		case TerminalTokens.TokenNamecatch:
+		case TerminalTokens.TokenNameclass:
+		case TerminalTokens.TokenNamecontinue:
+		case TerminalTokens.TokenNamedo:
+		case TerminalTokens.TokenNamedouble:
+		case TerminalTokens.TokenNamedefault:
+		case TerminalTokens.TokenNameelse:
+		case TerminalTokens.TokenNameextends:
+		case TerminalTokens.TokenNamefor:
+		case TerminalTokens.TokenNamefinal:
+		case TerminalTokens.TokenNamefloat:
+		case TerminalTokens.TokenNamefalse:
+		case TerminalTokens.TokenNamefinally:
+		case TerminalTokens.TokenNameif:
+		case TerminalTokens.TokenNameint:
+		case TerminalTokens.TokenNameimport:
+		case TerminalTokens.TokenNameinterface:
+		case TerminalTokens.TokenNameimplements:
+		case TerminalTokens.TokenNameinstanceof:
+		case TerminalTokens.TokenNamelong:
+		case TerminalTokens.TokenNamenew:
+		case TerminalTokens.TokenNamenull:
+		case TerminalTokens.TokenNamenative:
+		case TerminalTokens.TokenNamepublic:
+		case TerminalTokens.TokenNamepackage:
+		case TerminalTokens.TokenNameprivate:
+		case TerminalTokens.TokenNameprotected:
+		case TerminalTokens.TokenNamereturn:
+		case TerminalTokens.TokenNameshort:
+		case TerminalTokens.TokenNamesuper:
+		case TerminalTokens.TokenNamestatic:
+		case TerminalTokens.TokenNameswitch:
+		case TerminalTokens.TokenNamestrictfp:
+		case TerminalTokens.TokenNamesynchronized:
+		case TerminalTokens.TokenNametry:
+		case TerminalTokens.TokenNamethis:
+		case TerminalTokens.TokenNametrue:
+		case TerminalTokens.TokenNamethrow:
+		case TerminalTokens.TokenNamethrows:
+		case TerminalTokens.TokenNametransient:
+		case TerminalTokens.TokenNamevoid:
+		case TerminalTokens.TokenNamevolatile:
+		case TerminalTokens.TokenNamewhile:
+			return true;
+		default: 
+			return false;
+	}
+}
+
+private boolean isLiteral(int token) {
+	switch(token) {
+		case TerminalTokens.TokenNameIntegerLiteral:
+		case TerminalTokens.TokenNameLongLiteral:
+		case TerminalTokens.TokenNameFloatingPointLiteral:
+		case TerminalTokens.TokenNameDoubleLiteral:
+		case TerminalTokens.TokenNameStringLiteral:
+		case TerminalTokens.TokenNameCharacterLiteral:
+			return true;
+		default: 
+			return false;
+	}
+}
+public void javadocAmbiguousMethodReference(int sourceStart, int sourceEnd, Binding fieldBinding, int modifiers) {
+	int id = IProblem.JavadocAmbiguousMethodReference;
+	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+		String[] arguments = new String[] {new String(fieldBinding.readableName())};
+		handle(id, arguments, arguments, sourceStart, sourceEnd);
+	}
 }
 public void javadocDeprecatedField(FieldBinding field, ASTNode location, int modifiers) {
 	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
@@ -2178,15 +3059,15 @@
 		if (method.isConstructor()) {
 			this.handle(
 				IProblem.JavadocUsingDeprecatedConstructor,
-				new String[] {new String(method.declaringClass.readableName()), parametersAsString(method)},
-				new String[] {new String(method.declaringClass.shortReadableName()), parametersAsShortString(method)},
+				new String[] {new String(method.declaringClass.readableName()), typesAsString(method.isVarargs(), method.parameters, false)},
+				new String[] {new String(method.declaringClass.shortReadableName()), typesAsString(method.isVarargs(), method.parameters, true)},
 				location.sourceStart,
 				location.sourceEnd);
 		} else {
 			this.handle(
 				IProblem.JavadocUsingDeprecatedMethod,
-				new String[] {new String(method.declaringClass.readableName()), new String(method.selector), parametersAsString(method)},
-				new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), parametersAsShortString(method)},
+				new String[] {new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method.isVarargs(), method.parameters, false)},
+				new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method.isVarargs(), method.parameters, true)},
 				location.sourceStart,
 				location.sourceEnd);
 		}
@@ -2203,18 +3084,24 @@
 			location.sourceEnd);
 	}
 }
-public void javadocDuplicatedParamTag(JavadocSingleNameReference param, int modifiers) {
+public void javadocDuplicatedParamTag(char[] token, int sourceStart, int sourceEnd, int modifiers) {
 	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
-		String[] arguments = new String[] {String.valueOf(param.token)};
-		this.handle(IProblem.JavadocDuplicateParamName, arguments, arguments, param.sourceStart, param.sourceEnd);
+		String[] arguments = new String[] {String.valueOf(token)};
+		this.handle(IProblem.JavadocDuplicateParamName, arguments, arguments, sourceStart, sourceEnd);
 	}
 }
+public void javadocDuplicatedReturnTag(int sourceStart, int sourceEnd){
+	this.handle(IProblem.JavadocDuplicateReturnTag, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
 public void javadocDuplicatedThrowsClassName(TypeReference typeReference, int modifiers) {
 	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
 		String[] arguments = new String[] {String.valueOf(typeReference.resolvedType.sourceName())};
 		this.handle(IProblem.JavadocDuplicateThrowsClassName, arguments, arguments, typeReference.sourceStart, typeReference.sourceEnd);
 	}
 }
+public void javadocEmptyReturnTag(int sourceStart, int sourceEnd) {
+	this.handle(IProblem.JavadocEmptyReturnTag, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
 public void javadocErrorNoMethodFor(MessageSend messageSend, TypeBinding recType, TypeBinding[] params, int modifiers) {
 	StringBuffer buffer = new StringBuffer();
 	StringBuffer shortBuffer = new StringBuffer();
@@ -2239,65 +3126,30 @@
 }
 public void javadocInvalidConstructor(Statement statement, MethodBinding targetConstructor, int modifiers) {
 
-	if (!javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
-		return;
-	}
-//	boolean insideDefaultConstructor = 
-//		(this.referenceContext instanceof ConstructorDeclaration)
-//			&& ((ConstructorDeclaration)this.referenceContext).isDefaultConstructor();
-//	boolean insideImplicitConstructorCall =
-//		(statement instanceof ExplicitConstructorCall)
-//			&& (((ExplicitConstructorCall) statement).accessMode == ExplicitConstructorCall.ImplicitSuper);
-
+	if (!javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) return;
 	int id = IProblem.JavadocUndefinedConstructor; //default...
 	switch (targetConstructor.problemId()) {
 		case NotFound :
-//			if (insideDefaultConstructor){
-//				id = IProblem.JavadocUndefinedConstructorInDefaultConstructor;
-//			} else if (insideImplicitConstructorCall){
-//				id = IProblem.JavadocUndefinedConstructorInImplicitConstructorCall;
-//			} else {
-				id = IProblem.JavadocUndefinedConstructor;
-//			}
+			id = IProblem.JavadocUndefinedConstructor;
 			break;
 		case NotVisible :
-//			if (insideDefaultConstructor){
-//				id = IProblem.JavadocNotVisibleConstructorInDefaultConstructor;
-//			} else if (insideImplicitConstructorCall){
-//				id = IProblem.JavadocNotVisibleConstructorInImplicitConstructorCall;
-//			} else {
-				id = IProblem.JavadocNotVisibleConstructor;
-//			}
+			id = IProblem.JavadocNotVisibleConstructor;
 			break;
 		case Ambiguous :
-//			if (insideDefaultConstructor){
-//				id = IProblem.AmbiguousConstructorInDefaultConstructor;
-//			} else if (insideImplicitConstructorCall){
-//				id = IProblem.AmbiguousConstructorInImplicitConstructorCall;
-//			} else {
-				id = IProblem.JavadocAmbiguousConstructor;
-//			}
+			id = IProblem.JavadocAmbiguousConstructor;
 			break;
 		case NoError : // 0
 		default :
 			needImplementation(); // want to fail to see why we were here...
 			break;
 	}
-
 	this.handle(
 		id,
-		new String[] {new String(targetConstructor.declaringClass.readableName()), parametersAsString(targetConstructor)},
-		new String[] {new String(targetConstructor.declaringClass.shortReadableName()), parametersAsShortString(targetConstructor)},
+		new String[] {new String(targetConstructor.declaringClass.readableName()), typesAsString(targetConstructor.isVarargs(), targetConstructor.parameters, false)},
+		new String[] {new String(targetConstructor.declaringClass.shortReadableName()), typesAsString(targetConstructor.isVarargs(), targetConstructor.parameters, true)},
 		statement.sourceStart,
 		statement.sourceEnd);
 }
-public void javadocAmbiguousMethodReference(int sourceStart, int sourceEnd, Binding fieldBinding, int modifiers) {
-	int id = IProblem.JavadocAmbiguousMethodReference;
-	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
-		String[] arguments = new String[] {new String(fieldBinding.readableName())};
-		handle(id, arguments, arguments, sourceStart, sourceEnd);
-	}
-}
 /*
  * Similar implementation than invalidField(FieldReference...)
  * Note that following problem id cannot occur for Javadoc:
@@ -2325,7 +3177,7 @@
 			needImplementation(); // want to fail to see why we were here...
 			break;
 	}
-
+	// report issue
 	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
 		String[] arguments = new String[] {new String(fieldBinding.readableName())};
 		handle(id, arguments, arguments, sourceStart, sourceEnd);
@@ -2339,9 +3191,8 @@
  * 	- ReceiverTypeNotVisible :
  */
 public void javadocInvalidMethod(MessageSend messageSend, MethodBinding method, int modifiers) {
-	if (!javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
-		return;
-	}
+	if (!javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) return;
+	// set problem id
 	int id = IProblem.JavadocUndefinedMethod; //default...
 	switch (method.problemId()) {
 		case NotFound :
@@ -2361,14 +3212,13 @@
 			needImplementation(); // want to fail to see why we were here...
 			break;
 	}
-
 	if (id == IProblem.JavadocUndefinedMethod) {
 		ProblemMethodBinding problemMethod = (ProblemMethodBinding) method;
 		if (problemMethod.closestMatch != null) {
-				String closestParameterTypeNames = parametersAsString(problemMethod.closestMatch);
-				String parameterTypeNames = parametersAsString(method);
-				String closestParameterTypeShortNames = parametersAsShortString(problemMethod.closestMatch);
-				String parameterTypeShortNames = parametersAsShortString(method);
+				String closestParameterTypeNames = typesAsString(problemMethod.closestMatch.isVarargs(), problemMethod.closestMatch.parameters, false);
+				String parameterTypeNames = typesAsString(method.isVarargs(), method.parameters, false);
+				String closestParameterTypeShortNames = typesAsString(problemMethod.closestMatch.isVarargs(), problemMethod.closestMatch.parameters, true);
+				String parameterTypeShortNames = typesAsString(method.isVarargs(), method.parameters, true);
 				if (closestParameterTypeShortNames.equals(parameterTypeShortNames)){
 					closestParameterTypeShortNames = closestParameterTypeNames;
 					parameterTypeShortNames = parameterTypeNames;
@@ -2392,26 +3242,26 @@
 				return;
 		}
 	}
-
+	// report issue
 	this.handle(
 		id,
 		new String[] {
 			new String(method.declaringClass.readableName()),
-			new String(method.selector), parametersAsString(method)},
+			new String(method.selector), typesAsString(method.isVarargs(), method.parameters, false)},
 		new String[] {
 			new String(method.declaringClass.shortReadableName()),
-			new String(method.selector), parametersAsShortString(method)},
+			new String(method.selector), typesAsString(method.isVarargs(), method.parameters, true)},
 		(int) (messageSend.nameSourcePosition >>> 32),
 		(int) messageSend.nameSourcePosition);
 }
-public void javadocInvalidParamName(JavadocSingleNameReference param, int modifiers) {
-	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
-		String[] arguments = new String[] {String.valueOf(param.token)};
-		this.handle(IProblem.JavadocInvalidParamName, arguments, arguments, param.sourceStart, param.sourceEnd);
-	}
+public void javadocInvalidParamTagName(int sourceStart, int sourceEnd) {
+	this.handle(IProblem.JavadocInvalidParamTagName, NoArgument, NoArgument, sourceStart, sourceEnd);
 }
-public void javadocInvalidSeeReference(int sourceStart, int sourceEnd) {
-	this.handle(IProblem.JavadocInvalidSeeReference, NoArgument, NoArgument, sourceStart, sourceEnd);
+public void javadocInvalidParamTypeParameter(int sourceStart, int sourceEnd) {
+	this.handle(IProblem.JavadocInvalidParamTagTypeParameter, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocInvalidReference(int sourceStart, int sourceEnd) {
+	this.handle(IProblem.JavadocInvalidReference, NoArgument, NoArgument, sourceStart, sourceEnd);
 }
 public void javadocInvalidSeeReferenceArgs(int sourceStart, int sourceEnd) {
 	this.handle(IProblem.JavadocInvalidSeeArgs, NoArgument, NoArgument, sourceStart, sourceEnd);
@@ -2463,11 +3313,15 @@
 			location.sourceEnd);
 	}
 }
+public void javadocInvalidValueReference(int sourceStart, int sourceEnd, int modifiers) {
+	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers))
+		this.handle(IProblem.JavadocInvalidValueReference, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
 public void javadocMalformedSeeReference(int sourceStart, int sourceEnd) {
 	this.handle(IProblem.JavadocMalformedSeeReference, NoArgument, NoArgument, sourceStart, sourceEnd);
 }
 public void javadocMissing(int sourceStart, int sourceEnd, int modifiers){
-	boolean overriding = (modifiers & (CompilerModifiers.AccImplementing+CompilerModifiers.AccOverriding)) != 0;
+	boolean overriding = (modifiers & (CompilerModifiers.AccImplementing|CompilerModifiers.AccOverriding)) != 0;
 	boolean report = (this.options.getSeverity(CompilerOptions.MissingJavadocComments) != ProblemSeverities.Ignore)
 					&& (!overriding || this.options.reportMissingJavadocCommentsOverriding);
 	if (report) {
@@ -2478,34 +3332,41 @@
 		}
 	}
 }
-public void javadocMissingParamName(int sourceStart, int sourceEnd){
-	this.handle(IProblem.JavadocMissingParamName, NoArgument, NoArgument, sourceStart, sourceEnd);
+public void javadocMissingHashCharacter(int sourceStart, int sourceEnd, String ref){
+	String[] arguments = new String[] { ref };
+	this.handle(IProblem.JavadocMissingHashCharacter, arguments, arguments, sourceStart, sourceEnd);
 }
-public void javadocMissingParamTag(Argument param, int modifiers) {
-	boolean overriding = (modifiers & (CompilerModifiers.AccImplementing+CompilerModifiers.AccOverriding)) != 0;
+public void javadocMissingParamName(int sourceStart, int sourceEnd, int modifiers){
+	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers))
+		this.handle(IProblem.JavadocMissingParamName, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocMissingParamTag(char[] name, int sourceStart, int sourceEnd, int modifiers) {
+	boolean overriding = (modifiers & (CompilerModifiers.AccImplementing|CompilerModifiers.AccOverriding)) != 0;
 	boolean report = (this.options.getSeverity(CompilerOptions.MissingJavadocTags) != ProblemSeverities.Ignore)
 					&& (!overriding || this.options.reportMissingJavadocTagsOverriding);
 	if (report && javadocVisibility(this.options.reportMissingJavadocTagsVisibility, modifiers)) {
-		String[] arguments = new String[] { String.valueOf(param.name) };
-		this.handle(IProblem.JavadocMissingParamTag, arguments, arguments, param.sourceStart, param.sourceEnd);
+		String[] arguments = new String[] { String.valueOf(name) };
+		this.handle(IProblem.JavadocMissingParamTag, arguments, arguments, sourceStart, sourceEnd);
 	}
 }
+public void javadocMissingReference(int sourceStart, int sourceEnd, int modifiers){
+	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers))
+		this.handle(IProblem.JavadocMissingReference, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
 public void javadocMissingReturnTag(int sourceStart, int sourceEnd, int modifiers){
-	boolean overriding = (modifiers & (CompilerModifiers.AccImplementing+CompilerModifiers.AccOverriding)) != 0;
+	boolean overriding = (modifiers & (CompilerModifiers.AccImplementing|CompilerModifiers.AccOverriding)) != 0;
 	boolean report = (this.options.getSeverity(CompilerOptions.MissingJavadocTags) != ProblemSeverities.Ignore)
 					&& (!overriding || this.options.reportMissingJavadocTagsOverriding);
 	if (report && javadocVisibility(this.options.reportMissingJavadocTagsVisibility, modifiers)) {
 		this.handle(IProblem.JavadocMissingReturnTag, NoArgument, NoArgument, sourceStart, sourceEnd);
 	}
 }
-public void javadocMissingSeeReference(int sourceStart, int sourceEnd){
-	this.handle(IProblem.JavadocMissingSeeReference, NoArgument, NoArgument, sourceStart, sourceEnd);
-}
-public void javadocMissingThrowsClassName(int sourceStart, int sourceEnd){
-	this.handle(IProblem.JavadocMissingThrowsClassName, NoArgument, NoArgument, sourceStart, sourceEnd);
+public void javadocMissingThrowsClassName(int sourceStart, int sourceEnd, int modifiers){
+	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers))
+		this.handle(IProblem.JavadocMissingThrowsClassName, NoArgument, NoArgument, sourceStart, sourceEnd);
 }
 public void javadocMissingThrowsTag(TypeReference typeRef, int modifiers){
-	boolean overriding = (modifiers & (CompilerModifiers.AccImplementing+CompilerModifiers.AccOverriding)) != 0;
+	boolean overriding = (modifiers & (CompilerModifiers.AccImplementing|CompilerModifiers.AccOverriding)) != 0;
 	boolean report = (this.options.getSeverity(CompilerOptions.MissingJavadocTags) != ProblemSeverities.Ignore)
 					&& (!overriding || this.options.reportMissingJavadocTagsOverriding);
 	if (report && javadocVisibility(this.options.reportMissingJavadocTagsVisibility, modifiers)) {
@@ -2513,13 +3374,23 @@
 		this.handle(IProblem.JavadocMissingThrowsTag, arguments, arguments, typeRef.sourceStart, typeRef.sourceEnd);
 	}
 }
+public void javadocUndeclaredParamTagName(char[] token, int sourceStart, int sourceEnd, int modifiers) {
+	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+		String[] arguments = new String[] {String.valueOf(token)};
+		this.handle(IProblem.JavadocInvalidParamName, arguments, arguments, sourceStart, sourceEnd);
+	}
+}
 public void javadocUnexpectedTag(int sourceStart, int sourceEnd) {
 	this.handle(IProblem.JavadocUnexpectedTag, NoArgument, NoArgument, sourceStart, sourceEnd);
 }
+public void javadocUnexpectedText(int sourceStart, int sourceEnd) {
+	this.handle(IProblem.JavadocUnexpectedText, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
 public void javadocUnterminatedInlineTag(int sourceStart, int sourceEnd) {
 	this.handle(IProblem.JavadocUnterminatedInlineTag, NoArgument, NoArgument, sourceStart, sourceEnd);
 }
 private boolean javadocVisibility(int visibility, int modifiers) {
+	if (modifiers < 0) return true;
 	switch (modifiers & CompilerModifiers.AccVisibilityMASK) {
 		case IConstants.AccPublic :
 			return true;
@@ -2556,6 +3427,24 @@
 	}
 	return argument;
 }
+public void localVariableCannotBeNull(LocalVariableBinding local, ASTNode location) {
+	String[] arguments = new String[] {new String(local.name)  };
+	this.handle(
+		IProblem.LocalVariableCannotBeNull,
+		arguments,
+		arguments,
+		location.sourceStart,
+		location.sourceEnd);
+}
+public void localVariableCanOnlyBeNull(LocalVariableBinding local, ASTNode location) {
+	String[] arguments = new String[] {new String(local.name)  };
+	this.handle(
+		IProblem.LocalVariableCanOnlyBeNull,
+		arguments,
+		arguments,
+		location.sourceStart,
+		location.sourceEnd);
+}
 public void localVariableHiding(LocalDeclaration local, Binding hiddenVariable, boolean  isSpecialArgHidingField) {
 	if (hiddenVariable instanceof LocalVariableBinding) {
 		String[] arguments = new String[] {new String(local.name)  };
@@ -2582,6 +3471,27 @@
 			local.sourceEnd);
 	}
 }
+public void methodNameClash(MethodBinding currentMethod, MethodBinding inheritedMethod) {
+	this.handle(
+		IProblem.MethodNameClash,
+		new String[] {
+			new String(currentMethod.selector),
+			typesAsString(currentMethod.original().isVarargs(), currentMethod.original().parameters, false),
+			new String(currentMethod.declaringClass.readableName()),
+			typesAsString(inheritedMethod.original().isVarargs(), inheritedMethod.original().parameters, false),
+			new String(inheritedMethod.declaringClass.readableName()),
+		 }, 
+		new String[] {
+			new String(currentMethod.selector),
+			typesAsString(currentMethod.original().isVarargs(), currentMethod.original().parameters, true),
+			new String(currentMethod.declaringClass.shortReadableName()),
+			typesAsString(inheritedMethod.original().isVarargs(), inheritedMethod.original().parameters, true),
+			new String(inheritedMethod.declaringClass.shortReadableName()),
+		 }, 
+		currentMethod.sourceStart(),
+		currentMethod.sourceEnd());
+}	
+
 public void methodNeedBody(AbstractMethodDeclaration methodDecl) {
 	this.handle(
 		IProblem.MethodRequiresBody,
@@ -2606,6 +3516,24 @@
 		methodDecl.sourceStart,
 		methodDecl.sourceEnd);
 }
+public void parameterizedMemberTypeMissingArguments(ASTNode location, TypeBinding type) {
+	if (location == null) { // binary case
+	    this.handle(
+			IProblem.MissingArgumentsForParameterizedMemberType,
+			new String[] {new String(type.readableName())},
+			new String[] {new String(type.shortReadableName())},
+			AbortCompilation | Error,
+			0,
+			1);
+	    return;
+	}
+    this.handle(
+		IProblem.MissingArgumentsForParameterizedMemberType,
+		new String[] {new String(type.readableName())},
+		new String[] {new String(type.shortReadableName())},
+		location.sourceStart,
+		location.sourceEnd);
+}
 public void missingReturnType(AbstractMethodDeclaration methodDecl) {
 	this.handle(
 		IProblem.MissingReturnType,
@@ -2622,6 +3550,24 @@
 		expression.sourceStart,
 		expression.sourceEnd);
 }
+public void missingSerialVersion(TypeDeclaration typeDecl) {
+	String[] arguments = new String[] {new String(typeDecl.name)};
+	this.handle(
+		IProblem.MissingSerialVersion,
+		arguments,
+		arguments,
+		typeDecl.sourceStart,
+		typeDecl.sourceEnd);
+}
+public void missingValueForAnnotationMember(Annotation annotation, char[] memberName) {
+	String memberString = new String(memberName);
+	this.handle(
+		IProblem.MissingValueForAnnotationMember,
+		new String[] {new String(annotation.resolvedType.readableName()), memberString },
+		new String[] {new String(annotation.resolvedType.shortReadableName()), memberString},
+		annotation.sourceStart,
+		annotation.sourceEnd);
+}
 public void mustDefineDimensionsOrInitializer(ArrayAllocationExpression expression) {
 	this.handle(
 		IProblem.MustDefineEitherDimensionExpressionsOrInitializer,
@@ -2642,8 +3588,8 @@
 public void mustUseAStaticMethod(MessageSend messageSend, MethodBinding method) {
 	this.handle(
 		IProblem.StaticMethodRequested,
-		new String[] {new String(method.declaringClass.readableName()), new String(method.selector), parametersAsString(method)},
-		new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), parametersAsShortString(method)},
+		new String[] {new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method.isVarargs(), method.parameters, false)},
+		new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method.isVarargs(), method.parameters, true)},
 		messageSend.sourceStart,
 		messageSend.sourceEnd);
 }
@@ -2660,17 +3606,11 @@
 public void needImplementation() {
 	this.abortDueToInternalError(Util.bind("abort.missingCode")); //$NON-NLS-1$
 }
-public void needToEmulateFieldReadAccess(FieldBinding field, ASTNode location) {
+public void needToEmulateFieldAccess(FieldBinding field, ASTNode location, boolean isReadAccess) {
 	this.handle(
-		IProblem.NeedToEmulateFieldReadAccess,
-		new String[] {new String(field.declaringClass.readableName()), new String(field.name)},
-		new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)},
-		location.sourceStart,
-		location.sourceEnd);
-}
-public void needToEmulateFieldWriteAccess(FieldBinding field, ASTNode location) {
-	this.handle(
-		IProblem.NeedToEmulateFieldWriteAccess,
+		isReadAccess 
+			? IProblem.NeedToEmulateFieldReadAccess
+			: IProblem.NeedToEmulateFieldWriteAccess,
 		new String[] {new String(field.declaringClass.readableName()), new String(field.name)},
 		new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)},
 		location.sourceStart,
@@ -2685,11 +3625,11 @@
 			IProblem.NeedToEmulateConstructorAccess, 
 			new String[] {
 				new String(method.declaringClass.readableName()), 
-				parametersAsString(method)
+				typesAsString(method.isVarargs(), method.parameters, false)
 			 }, 
 			new String[] {
 				new String(method.declaringClass.shortReadableName()), 
-				parametersAsShortString(method)
+				typesAsString(method.isVarargs(), method.parameters, true)
 			 }, 
 			location.sourceStart, 
 			location.sourceEnd); 
@@ -2699,12 +3639,12 @@
 			new String[] {
 				new String(method.declaringClass.readableName()), 
 				new String(method.selector), 
-				parametersAsString(method)
+				typesAsString(method.isVarargs(), method.parameters, false)
 			 }, 
 			new String[] {
 				new String(method.declaringClass.shortReadableName()), 
 				new String(method.selector), 
-				parametersAsShortString(method)
+				typesAsString(method.isVarargs(), method.parameters, true)
 			 }, 
 			location.sourceStart, 
 			location.sourceEnd); 
@@ -2730,6 +3670,16 @@
 		location.sourceStart,
 		location.sourceEnd);
 }
+
+public void noMoreAvailableSpaceForConstant(TypeDeclaration typeDeclaration) {
+	this.handle(
+		IProblem.TooManyBytesForStringConstant,
+		new String[]{ new String(typeDeclaration.binding.readableName())},
+		new String[]{ new String(typeDeclaration.binding.shortReadableName())},
+		Abort | Error,
+		typeDeclaration.sourceStart,
+		typeDeclaration.sourceEnd);
+}
 public void noMoreAvailableSpaceForLocal(LocalVariableBinding local, ASTNode location) {
 	String[] arguments = new String[]{ new String(local.name) };
 	this.handle(
@@ -2740,11 +3690,39 @@
 		location.sourceStart,
 		location.sourceEnd);
 }
-public void nonStaticAccessToStaticMethod(ASTNode location, MethodBinding method) {
+
+public void noMoreAvailableSpaceInConstantPool(TypeDeclaration typeDeclaration) {
 	this.handle(
-		IProblem.NonStaticAccessToStaticMethod,
-		new String[] {new String(method.declaringClass.readableName()), new String(method.selector), parametersAsString(method)},
-		new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), parametersAsShortString(method)},
+		IProblem.TooManyConstantsInConstantPool,
+		new String[]{ new String(typeDeclaration.binding.readableName())},
+		new String[]{ new String(typeDeclaration.binding.shortReadableName())},
+		Abort | Error,
+		typeDeclaration.sourceStart,
+		typeDeclaration.sourceEnd);
+}
+public void nonExternalizedStringLiteral(ASTNode location) {
+	this.handle(
+		IProblem.NonExternalizedStringLiteral,
+		NoArgument,
+		NoArgument,
+		location.sourceStart,
+		location.sourceEnd);
+}
+public void nonGenericTypeCannotBeParameterized(ASTNode location, TypeBinding type, TypeBinding[] argumentTypes) {
+	if (location == null) { // binary case
+	    this.handle(
+			IProblem.NonGenericType,
+			new String[] {new String(type.readableName()), typesAsString(false, argumentTypes, false)},
+			new String[] {new String(type.shortReadableName()), typesAsString(false, argumentTypes, true)},
+			AbortCompilation | Error,
+			0,
+			1);
+	    return;
+	}
+    this.handle(
+		IProblem.NonGenericType,
+		new String[] {new String(type.readableName()), typesAsString(false, argumentTypes, false)},
+		new String[] {new String(type.shortReadableName()), typesAsString(false, argumentTypes, true)},
 		location.sourceStart,
 		location.sourceEnd);
 }
@@ -2756,6 +3734,14 @@
 		location.sourceStart,
 		fieldLocation(field, location));
 }
+public void nonStaticAccessToStaticMethod(ASTNode location, MethodBinding method) {
+	this.handle(
+		IProblem.NonStaticAccessToStaticMethod,
+		new String[] {new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method.isVarargs(), method.parameters, false)},
+		new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method.isVarargs(), method.parameters, true)},
+		location.sourceStart,
+		location.sourceEnd);
+}
 public void noSuchEnclosingInstance(TypeBinding targetType, ASTNode location, boolean isConstructorCall) {
 
 	int id;
@@ -2817,6 +3803,30 @@
 		expression.sourceStart,
 		expression.sourceEnd);
 }
+public void notCompatibleTypesErrorInForeach(Expression expression, TypeBinding leftType, TypeBinding rightType) {
+	String leftName = new String(leftType.readableName());
+	String rightName = new String(rightType.readableName());
+	String leftShortName = new String(leftType.shortReadableName());
+	String rightShortName = new String(rightType.shortReadableName());
+	if (leftShortName.equals(rightShortName)){
+		leftShortName = leftName;
+		rightShortName = rightName;
+	}
+	this.handle(
+		IProblem.IncompatibleTypesInForeach,
+		new String[] {leftName, rightName },
+		new String[] {leftShortName, rightShortName },
+		expression.sourceStart,
+		expression.sourceEnd);
+}
+public void objectCannotBeGeneric(TypeDeclaration typeDecl) {
+	this.handle(
+		IProblem.ObjectCannotBeGeneric,
+		NoArgument,
+		NoArgument,
+		typeDecl.typeParameters[0].sourceStart,
+		typeDecl.typeParameters[typeDecl.typeParameters.length-1].sourceEnd);
+}
 public void objectCannotHaveSuperTypes(SourceTypeBinding type) {
 	this.handle(
 		IProblem.ObjectCannotHaveSuperTypes,
@@ -2825,6 +3835,14 @@
 		type.sourceStart(),
 		type.sourceEnd());
 }
+public void objectMustBeClass(SourceTypeBinding type) {
+	this.handle(
+		IProblem.ObjectMustBeClass,
+		NoArgument,
+		NoArgument,
+		type.sourceStart(),
+		type.sourceEnd());
+}
 public void operatorOnlyValidOnNumericType(CompoundAssignment  assignment, TypeBinding leftType, TypeBinding rightType) {
 	String leftName = new String(leftType.readableName());
 	String rightName = new String(rightType.readableName());
@@ -2899,26 +3917,21 @@
 		compUnitDecl.currentPackage == null ? 0 : compUnitDecl.currentPackage.sourceStart,
 		compUnitDecl.currentPackage == null ? 0 : compUnitDecl.currentPackage.sourceEnd);
 }
-private String parametersAsString(MethodBinding method) {
-	TypeBinding[] params = method.parameters;
-	StringBuffer buffer = new StringBuffer();
-	for (int i = 0, length = params.length; i < length; i++) {
-		if (i != 0)
-			buffer.append(", "); //$NON-NLS-1$
-		buffer.append(new String(params[i].readableName()));
+private String parameterBoundAsString(TypeVariableBinding typeVariable, boolean makeShort) {
+    StringBuffer nameBuffer = new StringBuffer(10);
+    if (typeVariable.firstBound == typeVariable.superclass) {
+        nameBuffer.append(makeShort ? typeVariable.superclass.shortReadableName() : typeVariable.superclass.readableName());
+    }
+    int length;
+    if ((length = typeVariable.superInterfaces.length) > 0) {
+	    for (int i = 0; i < length; i++) {
+	        if (i > 0 || typeVariable.firstBound == typeVariable.superclass) nameBuffer.append(" & "); //$NON-NLS-1$
+	        nameBuffer.append(makeShort ? typeVariable.superInterfaces[i].shortReadableName() : typeVariable.superInterfaces[i].readableName());
+	    }
 	}
-	return buffer.toString();
+	return nameBuffer.toString();
 }
-private String parametersAsShortString(MethodBinding method) {
-	TypeBinding[] params = method.parameters;
-	StringBuffer buffer = new StringBuffer();
-	for (int i = 0, length = params.length; i < length; i++) {
-		if (i != 0)
-			buffer.append(", "); //$NON-NLS-1$
-		buffer.append(new String(params[i].shortReadableName()));
-	}
-	return buffer.toString();
-}
+
 public void parseError(
 	int startPosition, 
 	int endPosition, 
@@ -2987,12 +4000,218 @@
 		startPosition,
 		endPosition);
 }
+public void parseErrorDeleteToken(
+	int start,
+	int end,
+	int currentKind,
+	char[] errorTokenSource,
+	String errorTokenName){
+	this.syntaxError(
+		IProblem.ParsingErrorDeleteToken,
+		start, 
+		end, 
+		currentKind,
+		errorTokenSource, 
+		errorTokenName,
+		null); 
+}
+public void parseErrorDeleteTokens(
+	int start,
+	int end){
+	this.handle(
+		IProblem.ParsingErrorDeleteTokens,
+		NoArgument,
+		NoArgument,
+		start,
+		end);
+}
+public void parseErrorInsertAfterToken(
+	int start,
+	int end,
+	int currentKind,
+	char[] errorTokenSource,
+	String errorTokenName,
+	String expectedToken){
+	this.syntaxError(
+		IProblem.ParsingErrorInsertTokenAfter,
+		start, 
+		end, 
+		currentKind,
+		errorTokenSource, 
+		errorTokenName, 
+		expectedToken); 
+}
+
+public void parseErrorInsertBeforeToken(
+	int start,
+	int end,
+	int currentKind,
+	char[] errorTokenSource,
+	String errorTokenName,
+	String expectedToken){
+	this.syntaxError(
+		IProblem.ParsingErrorInsertTokenBefore,
+		start, 
+		end, 
+		currentKind,
+		errorTokenSource, 
+		errorTokenName, 
+		expectedToken); 
+}
+public void parseErrorInsertToComplete(
+	int start,
+	int end,
+	String inserted,
+	String completed){
+	String[] arguments = new String[] {inserted, completed};
+	this.handle(
+		IProblem.ParsingErrorInsertToComplete,
+		arguments,
+		arguments,
+		start,
+		end);
+}
+public void parseErrorInsertToCompletePhrase(
+	int start,
+	int end,
+	String inserted){
+	String[] arguments = new String[] {inserted};
+	this.handle(
+		IProblem.ParsingErrorInsertToCompletePhrase,
+		arguments,
+		arguments,
+		start,
+		end);
+}
+public void parseErrorInsertToCompleteScope(
+	int start,
+	int end,
+	String inserted){
+	String[] arguments = new String[] {inserted};
+	this.handle(
+		IProblem.ParsingErrorInsertToCompleteScope,
+		arguments,
+		arguments,
+		start,
+		end);
+}
+public void parseErrorInvalidToken(
+	int start,
+	int end,
+	int currentKind,
+	char[] errorTokenSource,
+	String errorTokenName,
+	String expectedToken){
+	this.syntaxError(
+		IProblem.ParsingErrorInvalidToken,
+		start, 
+		end, 
+		currentKind,
+		errorTokenSource, 
+		errorTokenName, 
+		expectedToken); 
+}
+public void parseErrorMergeTokens(
+	int start,
+	int end,
+	String expectedToken){
+	String[] arguments = new String[] {expectedToken};
+	this.handle(
+		IProblem.ParsingErrorMergeTokens,
+		arguments,
+		arguments,
+		start,
+		end);
+}
+public void parseErrorMisplacedConstruct(
+	int start,
+	int end){
+	this.handle(
+		IProblem.ParsingErrorMisplacedConstruct,
+		NoArgument,
+		NoArgument,
+		start,
+		end);
+}
+public void parseErrorNoSuggestion(
+	int start,
+	int end,
+	int currentKind,
+	char[] errorTokenSource,
+	String errorTokenName){
+	this.syntaxError(
+		IProblem.ParsingErrorNoSuggestion,
+		start, 
+		end, 
+		currentKind,
+		errorTokenSource, 
+		errorTokenName,
+		null); 
+}
+public void parseErrorNoSuggestionForTokens(
+	int start,
+	int end){
+	this.handle(
+		IProblem.ParsingErrorNoSuggestionForTokens,
+		NoArgument,
+		NoArgument,
+		start,
+		end);
+}
+public void parseErrorReplaceToken(
+	int start,
+	int end,
+	int currentKind,
+	char[] errorTokenSource,
+	String errorTokenName,
+	String expectedToken){
+	this.syntaxError(
+		IProblem.ParsingError,
+		start, 
+		end, 
+		currentKind,
+		errorTokenSource, 
+		errorTokenName, 
+		expectedToken); 
+}
+public void parseErrorReplaceTokens(
+	int start,
+	int end,
+	String expectedToken){
+	String[] arguments = new String[] {expectedToken};
+	this.handle(
+		IProblem.ParsingErrorReplaceTokens,
+		arguments,
+		arguments,
+		start,
+		end);
+}
+public void parseErrorUnexpectedEnd(
+	int start,
+	int end){
+		
+	String[] arguments;
+	if(this.referenceContext instanceof ConstructorDeclaration) {
+		arguments = new String[] {Util.bind("parser.endOfConstructor")}; //$NON-NLS-1$
+	} else if(this.referenceContext instanceof MethodDeclaration) {
+		arguments = new String[] {Util.bind("parser.endOfMethod")}; //$NON-NLS-1$
+	} else if(this.referenceContext instanceof TypeDeclaration) {
+		arguments = new String[] {Util.bind("parser.endOfInitializer")}; //$NON-NLS-1$
+	} else {
+		arguments = new String[] {Util.bind("parser.endOfFile")}; //$NON-NLS-1$
+	}
+	this.handle(
+		IProblem.ParsingErrorUnexpectedEOF,
+		arguments,
+		arguments,
+		start,
+		end);
+}
 public void possibleAccidentalBooleanAssignment(Assignment assignment) {
-	String[] arguments = new String[] {};
 	this.handle(
 		IProblem.PossibleAccidentalBooleanAssignment,
-		arguments,
-		arguments,
+		NoArgument,
+		NoArgument,
 		assignment.sourceStart,
 		assignment.sourceEnd);
 }
@@ -3007,17 +4226,35 @@
 		typeDecl.sourceEnd,
 		compUnitDecl.compilationResult);
 }
+public void rawMemberTypeCannotBeParameterized(ASTNode location, ReferenceBinding type, TypeBinding[] argumentTypes) {
+	if (location == null) { // binary case
+	    this.handle(
+			IProblem.RawMemberTypeCannotBeParameterized,
+			new String[] {new String(type.readableName()), typesAsString(false, argumentTypes, false), new String(type.enclosingType().readableName())},
+			new String[] {new String(type.shortReadableName()), typesAsString(false, argumentTypes, true), new String(type.enclosingType().shortReadableName())},
+			AbortCompilation | Error,
+			0,
+			1);
+	    return;
+	}
+    this.handle(
+		IProblem.RawMemberTypeCannotBeParameterized,
+		new String[] {new String(type.readableName()), typesAsString(false, argumentTypes, false), new String(type.enclosingType().readableName())},
+		new String[] {new String(type.shortReadableName()), typesAsString(false, argumentTypes, true), new String(type.enclosingType().shortReadableName())},
+		location.sourceStart,
+		location.sourceEnd);
+}
 public void recursiveConstructorInvocation(ExplicitConstructorCall constructorCall) {
 
 	this.handle(
 		IProblem.RecursiveConstructorInvocation,
 		new String[] {
 			new String(constructorCall.binding.declaringClass.readableName()), 
-			parametersAsString(constructorCall.binding)
+			typesAsString(constructorCall.binding.isVarargs(), constructorCall.binding.parameters, false)
 		},
 		new String[] {
 			new String(constructorCall.binding.declaringClass.shortReadableName()), 
-			parametersAsShortString(constructorCall.binding)
+			typesAsString(constructorCall.binding.isVarargs(), constructorCall.binding.parameters, true)
 		},
 		constructorCall.sourceStart,
 		constructorCall.sourceEnd);
@@ -3058,37 +4295,7 @@
 		methodDecl.sourceStart,
 		methodDecl.sourceEnd);
 }
-public void returnTypeProblem(SourceTypeBinding type, MethodDeclaration methodDecl, TypeBinding expectedType) {
-	int problemId = expectedType.problemId();
-	int id;
-	switch (problemId) {
-		case NotFound : // 1
-			id = IProblem.ReturnTypeNotFound;
-			break;
-		case NotVisible : // 2
-			id = IProblem.ReturnTypeNotVisible;
-			break;
-		case Ambiguous : // 3
-			id = IProblem.ReturnTypeAmbiguous;
-			break;
-		case InternalNameProvided : // 4
-			id = IProblem.ReturnTypeInternalNameProvided;
-			break;
-		case InheritedNameHidesEnclosingName : // 5
-			id = IProblem.ReturnTypeInheritedNameHidesEnclosingName;
-			break;
-		case NoError : // 0
-		default :
-			needImplementation(); // want to fail to see why we were here...
-			return;
-	}
-	this.handle(
-		id,
-		new String[] {new String(methodDecl.selector), new String(expectedType.readableName())},
-		new String[] {new String(methodDecl.selector), new String(expectedType.shortReadableName())},
-		methodDecl.returnType.sourceStart,
-		methodDecl.returnType.sourceEnd);
-}
+
 public void scannerError(Parser parser, String errorTokenName) {
 	Scanner scanner = parser.scanner;
 
@@ -3098,42 +4305,35 @@
 	//special treatment for recognized errors....
 	if (errorTokenName.equals(Scanner.END_OF_SOURCE))
 		flag = IProblem.EndOfSource;
-	else
-		if (errorTokenName.equals(Scanner.INVALID_HEXA))
-			flag = IProblem.InvalidHexa;
-		else
-			if (errorTokenName.equals(Scanner.INVALID_OCTAL))
-				flag = IProblem.InvalidOctal;
-			else
-				if (errorTokenName.equals(Scanner.INVALID_CHARACTER_CONSTANT))
-					flag = IProblem.InvalidCharacterConstant;
-				else
-					if (errorTokenName.equals(Scanner.INVALID_ESCAPE))
-						flag = IProblem.InvalidEscape;
-					else
-						if (errorTokenName.equals(Scanner.INVALID_UNICODE_ESCAPE)){
-							flag = IProblem.InvalidUnicodeEscape;
-							// better locate the error message
-							char[] source = scanner.source;
-							int checkPos = scanner.currentPosition - 1;
-							if (checkPos >= source.length) checkPos = source.length - 1;
-							while (checkPos >= startPos){
-								if (source[checkPos] == '\\') break;
-								checkPos --;
-							}
-							startPos = checkPos;
-						} else
-							if (errorTokenName.equals(Scanner.INVALID_FLOAT))
-								flag = IProblem.InvalidFloat;
-							else
-								if (errorTokenName.equals(Scanner.UNTERMINATED_STRING))
-									flag = IProblem.UnterminatedString;
-								else
-									if (errorTokenName.equals(Scanner.UNTERMINATED_COMMENT))
-										flag = IProblem.UnterminatedComment;
-									else
-										if (errorTokenName.equals(Scanner.INVALID_CHAR_IN_STRING))
-											flag = IProblem.UnterminatedString;
+	else if (errorTokenName.equals(Scanner.INVALID_HEXA))
+		flag = IProblem.InvalidHexa;
+	else if (errorTokenName.equals(Scanner.INVALID_OCTAL))
+		flag = IProblem.InvalidOctal;
+	else if (errorTokenName.equals(Scanner.INVALID_CHARACTER_CONSTANT))
+		flag = IProblem.InvalidCharacterConstant;
+	else if (errorTokenName.equals(Scanner.INVALID_ESCAPE))
+		flag = IProblem.InvalidEscape;
+	else if (errorTokenName.equals(Scanner.INVALID_UNICODE_ESCAPE)){
+		flag = IProblem.InvalidUnicodeEscape;
+		// better locate the error message
+		char[] source = scanner.source;
+		int checkPos = scanner.currentPosition - 1;
+		if (checkPos >= source.length) checkPos = source.length - 1;
+		while (checkPos >= startPos){
+			if (source[checkPos] == '\\') break;
+			checkPos --;
+		}
+		startPos = checkPos;
+	} else if (errorTokenName.equals(Scanner.INVALID_FLOAT))
+		flag = IProblem.InvalidFloat;
+	else if (errorTokenName.equals(Scanner.UNTERMINATED_STRING))
+		flag = IProblem.UnterminatedString;
+	else if (errorTokenName.equals(Scanner.UNTERMINATED_COMMENT))
+		flag = IProblem.UnterminatedComment;
+	else if (errorTokenName.equals(Scanner.INVALID_CHAR_IN_STRING))
+		flag = IProblem.UnterminatedString;
+	else if (errorTokenName.equals(Scanner.INVALID_DIGIT))
+		flag = IProblem.InvalidDigit;
 
 	String[] arguments = flag == IProblem.ParsingErrorNoSuggestion 
 			? new String[] {errorTokenName}
@@ -3206,6 +4406,24 @@
 		type.sourceStart(),
 		type.sourceEnd());
 }
+public void staticMemberOfParameterizedType(ASTNode location, ReferenceBinding type) {
+	if (location == null) { // binary case
+	    this.handle(
+			IProblem.StaticMemberOfParameterizedType,
+			new String[] {new String(type.readableName()), new String(type.enclosingType().readableName()), },
+			new String[] {new String(type.shortReadableName()), new String(type.enclosingType().shortReadableName()), },
+			AbortCompilation | Error,
+			0,
+			1);
+	    return;
+	}
+    this.handle(
+		IProblem.StaticMemberOfParameterizedType,
+		new String[] {new String(type.readableName()), new String(type.enclosingType().readableName()), },
+		new String[] {new String(type.shortReadableName()), new String(type.enclosingType().shortReadableName()), },
+		location.sourceStart,
+		location.sourceEnd);
+}
 public void stringConstantIsExceedingUtf8Limit(ASTNode location) {
 	this.handle(
 		IProblem.StringConstantIsExceedingUtf8Limit,
@@ -3230,14 +4448,67 @@
 		sourceStart,
 		sourceEnd);	
 }
-public void superinterfaceMustBeAnInterface(SourceTypeBinding type, TypeDeclaration typeDecl, ReferenceBinding superType) {
+public void superinterfaceMustBeAnInterface(SourceTypeBinding type, TypeReference superInterfaceRef, ReferenceBinding superType) {
 	this.handle(
 		IProblem.SuperInterfaceMustBeAnInterface,
 		new String[] {new String(superType.readableName()), new String(type.sourceName())},
 		new String[] {new String(superType.shortReadableName()), new String(type.sourceName())},
+		superInterfaceRef.sourceStart,
+		superInterfaceRef.sourceEnd);
+}
+public void superinterfacesCollide(ReferenceBinding type, TypeDeclaration typeDecl, ReferenceBinding superType, ReferenceBinding inheritedSuperType) {
+	this.handle(
+		IProblem.SuperInterfacesCollide,
+		new String[] {new String(superType.readableName()), new String(inheritedSuperType.readableName()), new String(type.sourceName())},
+		new String[] {new String(superType.shortReadableName()), new String(inheritedSuperType.shortReadableName()), new String(type.sourceName())},
 		typeDecl.sourceStart,
 		typeDecl.sourceEnd);
 }
+public void superTypeCannotUseWildcard(SourceTypeBinding type, TypeReference superclass, TypeBinding superTypeBinding) {
+	String name = new String(type.sourceName());
+	String superTypeFullName = new String(superTypeBinding.readableName());
+	String superTypeShortName = new String(superTypeBinding.shortReadableName());
+	if (superTypeShortName.equals(name)) superTypeShortName = superTypeFullName;
+	this.handle(
+		IProblem.SuperTypeUsingWildcard,
+		new String[] {superTypeFullName, name},
+		new String[] {superTypeShortName, name},
+		superclass.sourceStart,
+		superclass.sourceEnd);
+}
+
+private void syntaxError(
+	int id,
+	int startPosition, 
+	int endPosition, 
+	int currentKind,
+	char[] currentTokenSource, 
+	String errorTokenName, 
+	String expectedToken) {
+
+	String eTokenName;
+	if (isKeyword(currentKind) ||
+		isLiteral(currentKind) ||
+		isIdentifier(currentKind)) { //$NON-NLS-1$
+			eTokenName = new String(currentTokenSource);
+	} else {
+		eTokenName = errorTokenName;
+	}
+
+	String[] arguments;
+	if(expectedToken != null) {
+		arguments = new String[] {eTokenName, expectedToken};
+	} else {
+		arguments = new String[] {eTokenName};
+	}
+	this.handle(
+		id,
+		arguments,
+		arguments,
+		startPosition,
+		endPosition);
+}
+
 public void task(String tag, String message, String priority, int start, int end){
 	this.handle(
 		IProblem.Task,
@@ -3299,37 +4570,53 @@
 		typeDecl.sourceEnd,
 		compUnitDecl.compilationResult);
 }
-public void typeMismatchError(TypeBinding resultType, TypeBinding expectedType, ASTNode location) {
-	String resultTypeName = new String(resultType.readableName());
-	String expectedTypeName = new String(expectedType.readableName());
-	String resultTypeShortName = new String(resultType.shortReadableName());
-	String expectedTypeShortName = new String(expectedType.shortReadableName());
-	if (resultTypeShortName.equals(expectedTypeShortName)){
-		resultTypeShortName = resultTypeName;
-		expectedTypeShortName = expectedTypeName;
-	}
+public void typeMismatchError(TypeBinding actualType, TypeBinding expectedType, ASTNode location) {
 	this.handle(
 		IProblem.TypeMismatch,
-		new String[] {resultTypeName, expectedTypeName},
-		new String[] {resultTypeShortName, expectedTypeShortName},
+		new String[] {new String(actualType.readableName()), new String(expectedType.readableName())},
+		new String[] {new String(actualType.shortReadableName()), new String(expectedType.shortReadableName())},
 		location.sourceStart,
 		location.sourceEnd);
 }
-public void typeMismatchErrorActualTypeExpectedType(Expression expression, TypeBinding constantType, TypeBinding expectedType) {
-	String constantTypeName = new String(constantType.readableName());
-	String expectedTypeName = new String(expectedType.readableName());
-	String constantTypeShortName = new String(constantType.shortReadableName());
-	String expectedTypeShortName = new String(expectedType.shortReadableName());
-	if (constantTypeShortName.equals(expectedTypeShortName)){
-		constantTypeShortName = constantTypeName;
-		expectedTypeShortName = expectedTypeName;
-	}
+public void typeMismatchError(TypeBinding typeArgument, TypeVariableBinding typeParameter, ReferenceBinding genericType, ASTNode location) {
+    if (location == null) { // binary case
+		this.handle(
+			IProblem.TypeArgumentMismatch,
+			new String[] { new String(typeArgument.readableName()), new String(genericType.readableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, false) },
+			new String[] { new String(typeArgument.shortReadableName()), new String(genericType.shortReadableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, true) },
+			AbortCompilation | Error,
+			0,
+			1);
+        return;
+    }
 	this.handle(
-		IProblem.TypeMismatch,
-		new String[] {constantTypeName, expectedTypeName},
-		new String[] {constantTypeShortName, expectedTypeShortName},
-		expression.sourceStart,
-		expression.sourceEnd);
+		IProblem.TypeArgumentMismatch,
+		new String[] { new String(typeArgument.readableName()), new String(genericType.readableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, false) },
+		new String[] { new String(typeArgument.shortReadableName()), new String(genericType.shortReadableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, true) },
+		location.sourceStart,
+		location.sourceEnd);
+}
+private String typesAsString(boolean isVarargs, TypeBinding[] types, boolean makeShort) {
+	StringBuffer buffer = new StringBuffer(10);
+	for (int i = 0, length = types.length; i < length; i++) {
+		if (i != 0)
+			buffer.append(", "); //$NON-NLS-1$
+		TypeBinding type = types[i];
+		boolean isVarargType = isVarargs && i == length-1;
+		if (isVarargType) type = ((ArrayBinding)type).elementsType();
+		buffer.append(new String(makeShort ? type.shortReadableName() : type.readableName()));
+		if (isVarargType) buffer.append("..."); //$NON-NLS-1$
+	}
+	return buffer.toString();
+}
+public void undefinedAnnotationValue(TypeBinding annotationType, MemberValuePair memberValuePair) {
+	String name = 	new String(memberValuePair.name);
+	this.handle(
+		IProblem.UndefinedAnnotationMember,
+		new String[] { name, new String(annotationType.readableName())},
+		new String[] {	name, new String(annotationType.shortReadableName())},
+		memberValuePair.sourceStart,
+		memberValuePair.sourceEnd);
 }
 public void undefinedLabel(BranchStatement statement) {
 	String[] arguments = new String[] {new String(statement.label)};
@@ -3340,12 +4627,21 @@
 		statement.sourceStart,
 		statement.sourceEnd);
 }
+// can only occur inside binaries
+public void undefinedTypeVariableSignature(char[] variableName, ReferenceBinding binaryType) {
+	this.handle(
+		IProblem.UndefinedTypeVariable,
+		new String[] {new String(variableName), new String(binaryType.readableName()) },	
+		new String[] {new String(variableName), new String(binaryType.shortReadableName())},
+		AbortCompilation | Error,
+		0,
+		1);
+}
 public void undocumentedEmptyBlock(int blockStart, int blockEnd) {
-	String[] arguments = new String[] {};
 	this.handle(
 		IProblem.UndocumentedEmptyBlock,
-		arguments,
-		arguments,
+		NoArgument,
+		NoArgument,
 		blockStart,
 		blockEnd);
 }
@@ -3433,6 +4729,22 @@
 		castExpression.sourceStart,
 		castExpression.sourceEnd);
 }
+public void unnecessaryElse(ASTNode location) {
+	this.handle(
+		IProblem.UnnecessaryElse,
+		NoArgument,
+		NoArgument,
+		location.sourceStart,
+		location.sourceEnd);
+}
+public void unnecessaryEnclosingInstanceSpecification(Expression expression, ReferenceBinding targetType) {
+	this.handle(
+		IProblem.IllegalEnclosingInstanceSpecification,
+		new String[]{ new String(targetType.readableName())},
+		new String[]{ new String(targetType.shortReadableName())},
+		expression.sourceStart,
+		expression.sourceEnd);
+}
 public void unnecessaryInstanceof(InstanceOfExpression instanceofExpression, TypeBinding checkType) {
 	TypeBinding expressionType = instanceofExpression.expression.resolvedType;
 	this.handle(
@@ -3455,22 +4767,6 @@
 		reference.sourceStart,
 		end);
 }
-public void unnecessaryElse(ASTNode location) {
-	this.handle(
-		IProblem.UnnecessaryElse,
-		NoArgument,
-		NoArgument,
-		location.sourceStart,
-		location.sourceEnd);
-}
-public void unnecessaryEnclosingInstanceSpecification(Expression expression, ReferenceBinding targetType) {
-	this.handle(
-		IProblem.IllegalEnclosingInstanceSpecification,
-		new String[]{ new String(targetType.readableName())},
-		new String[]{ new String(targetType.shortReadableName())},
-		expression.sourceStart,
-		expression.sourceEnd);
-}
 public void unreachableCatchBlock(ReferenceBinding exceptionType, ASTNode location) {
 	this.handle(
 		IProblem.UnreachableCatch,
@@ -3515,6 +4811,101 @@
 		nameRef.sourceStart,
 		end);
 }
+public void unsafeCast(CastExpression castExpression, Scope scope) {
+	TypeBinding castedExpressionType = castExpression.expression.resolvedType;
+	TypeBinding erasedCastType = castExpression.resolvedType.erasure();
+	if (erasedCastType.isGenericType()) erasedCastType = scope.environment().createRawType((ReferenceBinding)erasedCastType, erasedCastType.enclosingType());
+	this.handle(
+		IProblem.UnsafeGenericCast,
+		new String[]{ 
+			new String(castedExpressionType.readableName()), 
+			new String(castExpression.resolvedType.readableName()),
+			new String(erasedCastType.readableName()),
+		},
+		new String[]{ 
+			new String(castedExpressionType.shortReadableName()), 
+			new String(castExpression.resolvedType.shortReadableName()),
+			new String(erasedCastType.shortReadableName()),
+		},
+		castExpression.sourceStart,
+		castExpression.sourceEnd);
+}
+public void unsafeRawConversion(Expression expression, TypeBinding expressionType, TypeBinding expectedType) {
+	this.handle(
+		IProblem.UnsafeRawConversion,
+		new String[] { new String(expressionType.readableName()), new String(expectedType.readableName()), new String(expectedType.erasure().readableName()) },
+		new String[] { new String(expressionType.shortReadableName()), new String(expectedType.shortReadableName()), new String(expectedType.erasure().shortReadableName()) },
+		expression.sourceStart,
+		expression.sourceEnd);    
+}
+public void unsafeRawFieldAssignment(FieldBinding rawField, TypeBinding expressionType, ASTNode location) {
+	this.handle(
+		IProblem.UnsafeRawFieldAssignment,
+		new String[] { 
+		        new String(expressionType.readableName()), new String(rawField.name), new String(rawField.declaringClass.readableName()), new String(rawField.declaringClass.erasure().readableName()) },
+		new String[] { 
+		        new String(expressionType.shortReadableName()), new String(rawField.name), new String(rawField.declaringClass.shortReadableName()), new String(rawField.declaringClass.erasure().shortReadableName()) },
+		location.sourceStart,
+		location.sourceEnd);    
+}
+public void unsafeRawInvocation(ASTNode location, MethodBinding rawMethod) {
+    if (rawMethod.isConstructor()) {
+		this.handle(
+			IProblem.UnsafeRawConstructorInvocation,
+			new String[] {
+				new String(rawMethod.declaringClass.readableName()),
+				typesAsString(rawMethod.original().isVarargs(), rawMethod.parameters, false),
+				new String(rawMethod.declaringClass.erasure().readableName()),
+			 }, 
+			new String[] {
+				new String(rawMethod.declaringClass.shortReadableName()),
+				typesAsString(rawMethod.original().isVarargs(), rawMethod.parameters, true),
+				new String(rawMethod.declaringClass.erasure().shortReadableName()),
+			 }, 
+			location.sourceStart,
+			location.sourceEnd);    
+    } else {
+		this.handle(
+			IProblem.UnsafeRawMethodInvocation,
+			new String[] {
+				new String(rawMethod.selector),
+				typesAsString(rawMethod.original().isVarargs(), rawMethod.parameters, false),
+				new String(rawMethod.declaringClass.readableName()),
+				new String(rawMethod.declaringClass.erasure().readableName()),
+			 }, 
+			new String[] {
+				new String(rawMethod.selector),
+				typesAsString(rawMethod.original().isVarargs(), rawMethod.parameters, true),
+				new String(rawMethod.declaringClass.shortReadableName()),
+				new String(rawMethod.declaringClass.erasure().shortReadableName()),
+			 }, 
+			location.sourceStart,
+			location.sourceEnd);    
+    }
+}
+public void unsafeReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod, ASTNode location) {
+	
+	this.handle(
+			IProblem.UnsafeReturnTypeOverride,
+			new String[] {
+				new String(currentMethod.returnType.readableName()),
+				new String(currentMethod.selector),
+				typesAsString(currentMethod.original().isVarargs(), currentMethod.original().parameters, false),
+				new String(currentMethod.declaringClass.readableName()),
+				new String(inheritedMethod.returnType.readableName()),
+				//new String(inheritedMethod.returnType.erasure().readableName()),
+			 }, 
+			new String[] {
+				new String(currentMethod.returnType.shortReadableName()),
+				new String(currentMethod.selector),
+				typesAsString(currentMethod.original().isVarargs(), currentMethod.original().parameters, true),
+				new String(currentMethod.declaringClass.shortReadableName()),
+				new String(inheritedMethod.returnType.shortReadableName()),
+				//new String(inheritedMethod.returnType.erasure().shortReadableName()),
+			 }, 
+			location.sourceStart,
+			location.sourceEnd);
+}
 public void unusedArgument(LocalDeclaration localDecl) {
 
 	String[] arguments = new String[] {new String(localDecl.name)};
@@ -3531,12 +4922,12 @@
 			IProblem.UnusedConstructorDeclaredThrownException,
 			new String[] {
 				new String(method.binding.declaringClass.readableName()),
-				parametersAsString(method.binding),
+				typesAsString(method.binding.isVarargs(), method.binding.parameters, false),
 				new String(exceptionType.readableName()),
 			 }, 
 			new String[] {
 				new String(method.binding.declaringClass.shortReadableName()),
-				parametersAsShortString(method.binding),
+				typesAsString(method.binding.isVarargs(), method.binding.parameters, true),
 				new String(exceptionType.shortReadableName()),
 			 }, 
 			location.sourceStart,
@@ -3547,13 +4938,13 @@
 			new String[] {
 				new String(method.binding.declaringClass.readableName()),
 				new String(method.selector),
-				parametersAsString(method.binding),
+				typesAsString(method.binding.isVarargs(), method.binding.parameters, false),
 				new String(exceptionType.readableName()),
 			 }, 
 			new String[] {
 				new String(method.binding.declaringClass.shortReadableName()),
 				new String(method.selector),
-				parametersAsShortString(method.binding),
+				typesAsString(method.binding.isVarargs(), method.binding.parameters, true),
 				new String(exceptionType.shortReadableName()),
 			 }, 
 			location.sourceStart,
@@ -3590,11 +4981,11 @@
 			IProblem.UnusedPrivateConstructor,
 		new String[] {
 			new String(constructor.declaringClass.readableName()),
-			parametersAsString(constructor)
+			typesAsString(constructor.isVarargs(), constructor.parameters, false)
 		 }, 
 		new String[] {
 			new String(constructor.declaringClass.shortReadableName()),
-			parametersAsShortString(constructor)
+			typesAsString(constructor.isVarargs(), constructor.parameters, true)
 		 }, 
 		constructorDecl.sourceStart,
 		constructorDecl.sourceEnd);
@@ -3657,14 +5048,14 @@
 	}
 	// no report for serialization support 'Object readResolve()'
 	if (!method.isStatic()
-			&& TypeIds.T_Object == method.returnType.id
+			&& TypeIds.T_JavaLangObject == method.returnType.id
 			&& method.parameters.length == 0
 			&& CharOperation.equals(method.selector, TypeConstants.READRESOLVE)) {
 		return;
 	}
 	// no report for serialization support 'Object writeReplace()'
 	if (!method.isStatic()
-			&& TypeIds.T_Object == method.returnType.id
+			&& TypeIds.T_JavaLangObject == method.returnType.id
 			&& method.parameters.length == 0
 			&& CharOperation.equals(method.selector, TypeConstants.WRITEREPLACE)) {
 		return;
@@ -3674,12 +5065,12 @@
 		new String[] {
 			new String(method.declaringClass.readableName()),
 			new String(method.selector),
-			parametersAsString(method)
+			typesAsString(method.isVarargs(), method.parameters, false)
 		 }, 
 		new String[] {
 			new String(method.declaringClass.shortReadableName()),
 			new String(method.selector),
-			parametersAsShortString(method)
+			typesAsString(method.isVarargs(), method.parameters, true)
 		 }, 
 		methodDecl.sourceStart,
 		methodDecl.sourceEnd);
@@ -3708,7 +5099,32 @@
 		sourceStart,
 		sourceEnd);	
 }
-
+public void useEnumAsAnIdentifier(int sourceStart, int sourceEnd) {
+	this.handle(
+		IProblem.UseEnumAsAnIdentifier,
+		NoArgument,
+		NoArgument,
+		sourceStart,
+		sourceEnd);	
+}
+public void varargsArgumentNeedCast(MethodBinding method, TypeBinding argumentType, InvocationSite location) {
+	TypeBinding lastParam = method.parameters[method.parameters.length-1];
+	if (method.isConstructor()) {
+		this.handle(
+			IProblem.ConstructorVarargsArgumentNeedCast,
+			new String[] {new String(argumentType.readableName()), new String(lastParam.readableName()), new String(method.declaringClass.readableName()), typesAsString(method.isVarargs(), method.parameters, false), },
+			new String[] {new String(argumentType.shortReadableName()), new String(lastParam.shortReadableName()), new String(method.declaringClass.shortReadableName()), typesAsString(method.isVarargs(), method.parameters, true), },
+			location.sourceStart(),
+			location.sourceEnd());
+	} else {
+		this.handle(
+			IProblem.MethodVarargsArgumentNeedCast,
+			new String[] { new String(argumentType.readableName()), new String(lastParam.readableName()), new String(method.selector), typesAsString(method.isVarargs(), method.parameters, false), new String(method.declaringClass.readableName()), },
+			new String[] { new String(argumentType.shortReadableName()), new String(lastParam.shortReadableName()), new String(method.selector), typesAsString(method.isVarargs(), method.parameters, true), new String(method.declaringClass.shortReadableName()), },
+			location.sourceStart(),
+			location.sourceEnd());
+	}
+}
 public void variableTypeCannotBeVoid(AbstractVariableDeclaration varDecl) {
 	String[] arguments = new String[] {new String(varDecl.name)};
 	this.handle(
@@ -3738,348 +5154,71 @@
 		currentMethod.sourceStart(),
 		currentMethod.sourceEnd());
 }
-public void nonExternalizedStringLiteral(ASTNode location) {
+public void wildcardAssignment(TypeBinding variableType, TypeBinding expressionType, ASTNode location) {
 	this.handle(
-		IProblem.NonExternalizedStringLiteral,
-		NoArgument,
-		NoArgument,
+		IProblem.WildcardFieldAssignment,
+		new String[] { 
+		        new String(expressionType.readableName()), new String(variableType.readableName()) },
+		new String[] { 
+		        new String(expressionType.shortReadableName()), new String(variableType.shortReadableName()) },
 		location.sourceStart,
-		location.sourceEnd);
+		location.sourceEnd);    
 }
-
-public void noMoreAvailableSpaceForConstant(TypeDeclaration typeDeclaration) {
-	this.handle(
-		IProblem.TooManyBytesForStringConstant,
-		new String[]{ new String(typeDeclaration.binding.readableName())},
-		new String[]{ new String(typeDeclaration.binding.shortReadableName())},
-		Abort | Error,
-		typeDeclaration.sourceStart,
-		typeDeclaration.sourceEnd);
-}
-
-public void noMoreAvailableSpaceInConstantPool(TypeDeclaration typeDeclaration) {
-	this.handle(
-		IProblem.TooManyConstantsInConstantPool,
-		new String[]{ new String(typeDeclaration.binding.readableName())},
-		new String[]{ new String(typeDeclaration.binding.shortReadableName())},
-		Abort | Error,
-		typeDeclaration.sourceStart,
-		typeDeclaration.sourceEnd);
-}
-
-private boolean isKeyword(int token) {
-	switch(token) {
-		case TerminalTokens.TokenNameabstract:
-		case TerminalTokens.TokenNameassert:
-		case TerminalTokens.TokenNamebyte:
-		case TerminalTokens.TokenNamebreak:
-		case TerminalTokens.TokenNameboolean:
-		case TerminalTokens.TokenNamecase:
-		case TerminalTokens.TokenNamechar:
-		case TerminalTokens.TokenNamecatch:
-		case TerminalTokens.TokenNameclass:
-		case TerminalTokens.TokenNamecontinue:
-		case TerminalTokens.TokenNamedo:
-		case TerminalTokens.TokenNamedouble:
-		case TerminalTokens.TokenNamedefault:
-		case TerminalTokens.TokenNameelse:
-		case TerminalTokens.TokenNameextends:
-		case TerminalTokens.TokenNamefor:
-		case TerminalTokens.TokenNamefinal:
-		case TerminalTokens.TokenNamefloat:
-		case TerminalTokens.TokenNamefalse:
-		case TerminalTokens.TokenNamefinally:
-		case TerminalTokens.TokenNameif:
-		case TerminalTokens.TokenNameint:
-		case TerminalTokens.TokenNameimport:
-		case TerminalTokens.TokenNameinterface:
-		case TerminalTokens.TokenNameimplements:
-		case TerminalTokens.TokenNameinstanceof:
-		case TerminalTokens.TokenNamelong:
-		case TerminalTokens.TokenNamenew:
-		case TerminalTokens.TokenNamenull:
-		case TerminalTokens.TokenNamenative:
-		case TerminalTokens.TokenNamepublic:
-		case TerminalTokens.TokenNamepackage:
-		case TerminalTokens.TokenNameprivate:
-		case TerminalTokens.TokenNameprotected:
-		case TerminalTokens.TokenNamereturn:
-		case TerminalTokens.TokenNameshort:
-		case TerminalTokens.TokenNamesuper:
-		case TerminalTokens.TokenNamestatic:
-		case TerminalTokens.TokenNameswitch:
-		case TerminalTokens.TokenNamestrictfp:
-		case TerminalTokens.TokenNamesynchronized:
-		case TerminalTokens.TokenNametry:
-		case TerminalTokens.TokenNamethis:
-		case TerminalTokens.TokenNametrue:
-		case TerminalTokens.TokenNamethrow:
-		case TerminalTokens.TokenNamethrows:
-		case TerminalTokens.TokenNametransient:
-		case TerminalTokens.TokenNamevoid:
-		case TerminalTokens.TokenNamevolatile:
-		case TerminalTokens.TokenNamewhile:
-			return true;
-		default: 
-			return false;
+public void wildcardInvocation(ASTNode location, TypeBinding receiverType, MethodBinding method, TypeBinding[] arguments) {
+	TypeBinding offendingArgument = null;
+	TypeBinding offendingParameter = null;
+	for (int i = 0, length = method.parameters.length; i < length; i++) {
+		TypeBinding parameter = method.parameters[i];
+		if (parameter.isWildcard() && (((WildcardBinding) parameter).kind != Wildcard.SUPER)) {
+			offendingParameter = parameter;
+			offendingArgument = arguments[i];
+			break;
+		}
 	}
-}
-
-private boolean isLiteral(int token) {
-	switch(token) {
-		case TerminalTokens.TokenNameIntegerLiteral:
-		case TerminalTokens.TokenNameLongLiteral:
-		case TerminalTokens.TokenNameFloatingPointLiteral:
-		case TerminalTokens.TokenNameDoubleLiteral:
-		case TerminalTokens.TokenNameStringLiteral:
-		case TerminalTokens.TokenNameCharacterLiteral:
-			return true;
-		default: 
-			return false;
-	}
-}
-
-private boolean isIdentifier(int token) {
-	return token == TerminalTokens.TokenNameIdentifier;
-}
-
-private void syntaxError(
-	int id,
-	int startPosition, 
-	int endPosition, 
-	int currentKind,
-	char[] currentTokenSource, 
-	String errorTokenName, 
-	String expectedToken) {
-
-	String eTokenName;
-	if (isKeyword(currentKind) ||
-		isLiteral(currentKind) ||
-		isIdentifier(currentKind)) { //$NON-NLS-1$
-			eTokenName = new String(currentTokenSource);
-	} else {
-		eTokenName = errorTokenName;
-	}
-
-	String[] arguments;
-	if(expectedToken != null) {
-		arguments = new String[] {eTokenName, expectedToken};
-	} else {
-		arguments = new String[] {eTokenName};
-	}
-	this.handle(
-		id,
-		arguments,
-		arguments,
-		startPosition,
-		endPosition);
-}
-
-public void parseErrorInsertBeforeToken(
-	int start,
-	int end,
-	int currentKind,
-	char[] errorTokenSource,
-	String errorTokenName,
-	String expectedToken){
-	this.syntaxError(
-		IProblem.ParsingErrorInsertTokenBefore,
-		start, 
-		end, 
-		currentKind,
-		errorTokenSource, 
-		errorTokenName, 
-		expectedToken); 
-}
-public void parseErrorInsertAfterToken(
-	int start,
-	int end,
-	int currentKind,
-	char[] errorTokenSource,
-	String errorTokenName,
-	String expectedToken){
-	this.syntaxError(
-		IProblem.ParsingErrorInsertTokenAfter,
-		start, 
-		end, 
-		currentKind,
-		errorTokenSource, 
-		errorTokenName, 
-		expectedToken); 
-}
-public void parseErrorDeleteToken(
-	int start,
-	int end,
-	int currentKind,
-	char[] errorTokenSource,
-	String errorTokenName){
-	this.syntaxError(
-		IProblem.ParsingErrorDeleteToken,
-		start, 
-		end, 
-		currentKind,
-		errorTokenSource, 
-		errorTokenName,
-		null); 
-}
-public void parseErrorReplaceToken(
-	int start,
-	int end,
-	int currentKind,
-	char[] errorTokenSource,
-	String errorTokenName,
-	String expectedToken){
-	this.syntaxError(
-		IProblem.ParsingError,
-		start, 
-		end, 
-		currentKind,
-		errorTokenSource, 
-		errorTokenName, 
-		expectedToken); 
-}
-public void parseErrorInvalidToken(
-	int start,
-	int end,
-	int currentKind,
-	char[] errorTokenSource,
-	String errorTokenName,
-	String expectedToken){
-	this.syntaxError(
-		IProblem.ParsingErrorInvalidToken,
-		start, 
-		end, 
-		currentKind,
-		errorTokenSource, 
-		errorTokenName, 
-		expectedToken); 
-}
-public void parseErrorUnexpectedEnd(
-	int start,
-	int end){
-		
-	String[] arguments;
-	if(this.referenceContext instanceof ConstructorDeclaration) {
-		arguments = new String[] {Util.bind("parser.endOfConstructor")}; //$NON-NLS-1$
-	} else if(this.referenceContext instanceof MethodDeclaration) {
-		arguments = new String[] {Util.bind("parser.endOfMethod")}; //$NON-NLS-1$
-	} else if(this.referenceContext instanceof TypeDeclaration) {
-		arguments = new String[] {Util.bind("parser.endOfInitializer")}; //$NON-NLS-1$
-	} else {
-		arguments = new String[] {Util.bind("parser.endOfFile")}; //$NON-NLS-1$
-	}
-	this.handle(
-		IProblem.ParsingErrorUnexpectedEOF,
-		arguments,
-		arguments,
-		start,
-		end);
-}
-public void parseErrorMergeTokens(
-	int start,
-	int end,
-	String expectedToken){
-	String[] arguments = new String[] {expectedToken};
-	this.handle(
-		IProblem.ParsingErrorMergeTokens,
-		arguments,
-		arguments,
-		start,
-		end);
-}
-public void parseErrorMisplacedConstruct(
-	int start,
-	int end){
-	this.handle(
-		IProblem.ParsingErrorMisplacedConstruct,
-		NoArgument,
-		NoArgument,
-		start,
-		end);
-}
-public void parseErrorNoSuggestion(
-	int start,
-	int end,
-	int currentKind,
-	char[] errorTokenSource,
-	String errorTokenName){
-	this.syntaxError(
-		IProblem.ParsingErrorNoSuggestion,
-		start, 
-		end, 
-		currentKind,
-		errorTokenSource, 
-		errorTokenName,
-		null); 
-}
-public void parseErrorDeleteTokens(
-	int start,
-	int end){
-	this.handle(
-		IProblem.ParsingErrorDeleteTokens,
-		NoArgument,
-		NoArgument,
-		start,
-		end);
-}
-public void parseErrorNoSuggestionForTokens(
-	int start,
-	int end){
-	this.handle(
-		IProblem.ParsingErrorNoSuggestionForTokens,
-		NoArgument,
-		NoArgument,
-		start,
-		end);
-}
-public void parseErrorReplaceTokens(
-	int start,
-	int end,
-	String expectedToken){
-	String[] arguments = new String[] {expectedToken};
-	this.handle(
-		IProblem.ParsingErrorReplaceTokens,
-		arguments,
-		arguments,
-		start,
-		end);
-}
-public void parseErrorInsertToComplete(
-	int start,
-	int end,
-	String inserted,
-	String completed){
-	String[] arguments = new String[] {inserted, completed};
-	this.handle(
-		IProblem.ParsingErrorInsertToComplete,
-		arguments,
-		arguments,
-		start,
-		end);
-}
-public void parseErrorInsertToCompleteScope(
-	int start,
-	int end,
-	String inserted){
-	String[] arguments = new String[] {inserted};
-	this.handle(
-		IProblem.ParsingErrorInsertToCompleteScope,
-		arguments,
-		arguments,
-		start,
-		end);
-}
-public void parseErrorInsertToCompletePhrase(
-	int start,
-	int end,
-	String inserted){
-	String[] arguments = new String[] {inserted};
-	this.handle(
-		IProblem.ParsingErrorInsertToCompletePhrase,
-		arguments,
-		arguments,
-		start,
-		end);
+	
+    if (method.isConstructor()) {
+		this.handle(
+			IProblem.WildcardConstructorInvocation,
+			new String[] {
+				new String(receiverType.sourceName()),
+				typesAsString(method.isVarargs(), method.parameters, false),
+				new String(receiverType.readableName()),
+				typesAsString(false, arguments, false),
+				new String(offendingArgument.readableName()),
+				new String(offendingParameter.readableName()),
+			 }, 
+			new String[] {
+				new String(receiverType.sourceName()),
+				typesAsString(method.isVarargs(), method.parameters, true),
+				new String(receiverType.shortReadableName()),
+				typesAsString(false, arguments, true),
+				new String(offendingArgument.shortReadableName()),
+				new String(offendingParameter.shortReadableName()),
+			 }, 
+			location.sourceStart,
+			location.sourceEnd);    
+    } else {
+		this.handle(
+			IProblem.WildcardMethodInvocation,
+			new String[] {
+				new String(method.selector),
+				typesAsString(method.isVarargs(), method.parameters, false),
+				new String(receiverType.readableName()),
+				typesAsString(false, arguments, false),
+				new String(offendingArgument.readableName()),
+				new String(offendingParameter.readableName()),
+			 }, 
+			new String[] {
+				new String(method.selector),
+				typesAsString(method.isVarargs(), method.parameters, true),
+				new String(receiverType.shortReadableName()),
+				typesAsString(false, arguments, true),
+				new String(offendingArgument.shortReadableName()),
+				new String(offendingParameter.shortReadableName()),
+			 }, 
+			location.sourceStart,
+			location.sourceEnd);    
+    }
 }
 public void wrongSequenceOfExceptionTypesError(TryStatement statement, TypeBinding exceptionType, int under, TypeBinding hidingExceptionType) {
 	//the two catch block under and upper are in an incorrect order.
@@ -4099,5 +5238,4 @@
 		typeRef.sourceStart,
 		typeRef.sourceEnd);
 }
-
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ShouldNotImplement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ShouldNotImplement.java
index 032465d..acceeda 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ShouldNotImplement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ShouldNotImplement.java
@@ -17,6 +17,7 @@
  *	(internal only)
  */
 public class ShouldNotImplement extends RuntimeException {
+	private static final long serialVersionUID = 2669970476264283736L; // backward compatible
 	public ShouldNotImplement(String message) {
 		super(message);
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
index 84aa385..f2117e2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
@@ -10,7 +10,7 @@
 ###############################################################################
 0 = {0}
 1 = super cannot be used in java.lang.Object
-2 = {0} cannot be resolved or is not a type
+2 = {0} cannot be resolved to a type
 3 = The type {0} is not visible
 4 = The type {0} is ambiguous
 5 = The type {0} is deprecated
@@ -63,7 +63,7 @@
 77 = The private field {0}.{1} is never read locally
 78 = The static field {0}.{1} should be accessed directly
 79 = Unqualified access to the field {0}.{1} 
-80 = The final field {0}.{1} cannot be assigned. It must be blank in this context, not qualified and not in compound assignment
+80 = The final field {0}.{1} cannot be assigned
 81 = The blank final field {0} may not have been initialized
 82 = The final field {0} may already have been assigned
 
@@ -73,6 +73,7 @@
 93 = The field {0}.{1} is hiding a field from type {2}
 94 = The parameter {0} is hiding another local variable defined in an enclosing type scope
 95 = The parameter {0} is hiding a field from type {1}
+96 = The serializable class {0} does not declare a static final serialVersionUID field of type long
 
 100 = The method {1}({2}) is undefined for the type {0}
 101 = The method {1}({2}) from the type {0} is not visible
@@ -120,7 +121,7 @@
 153 = case expressions must be constant expressions
 154 = The literal {1} of type {0} is out of range 
 156 = Cannot cast from {0} to {1}
-157 = Cannot instantiate the type {0}, since it is not a concrete class
+157 = Cannot instantiate the type {0}
 158 = Cannot define dimension expressions when an array initializer is provided
 159 = Variable must provide either dimension expressions or an array initializer
 160 = The operator {0} is undefined for the argument type(s) {1}
@@ -132,7 +133,7 @@
 166 = The default case is already defined
 167 = Unreachable catch block for {0}. This exception is never thrown from the try statement body
 168 = Unhandled exception type {0}
-169 = case constant must be a char, byte, short, or int instead of {0}
+169 = Cannot switch on a value of type {0}. Only int values or enum constants are permitted
 170 = Duplicate case
 171 = Duplicate label {0}
 172 = break cannot be used outside of a loop or a switch
@@ -144,8 +145,8 @@
 178 = The assignment to variable {0} has no effect
 179 = Possible accidental assignment in place of a comparison. A condition expression should not be reduced to an assignment
 180 = Unnecessary semicolon
-181 = Unnecessary cast to type {1} for expression of type {0}
-182 = Unnecessary cast to type {1} for expression of type {0}. It is already compatible with the argument type {2}
+181 = Unnecessary cast from {0} to {1}
+182 = Unnecessary cast from {0} to {1}. It is already compatible with the argument type {2}
 183 = The expression of type {0} is already an instance of type {1}
 184 = finally block does not complete normally
 185 = The declared exception {3} is not actually thrown by the method {1}({2}) from type {0}
@@ -153,6 +154,7 @@
 187 = Unreachable catch block for {0}. It is already handled by the catch block for {1}
 188 = Empty control-flow statement
 189 = Statement unnecessarily nested within else clause. The corresponding then clause does not complete normally
+
 190 = Read access to enclosing field {0}.{1} is emulated by a synthetic accessor method. Increasing its visibility will improve your performance
 191 = Write access to enclosing field {0}.{1} is emulated by a synthetic accessor method. Increasing its visibility will improve your performance
 192 = Access to enclosing method {1}({2}) from the type {0} is emulated by a synthetic accessor method. Increasing its visibility will improve your performance
@@ -160,11 +162,12 @@
 195 = The method {1} is defined in an inherited type and an enclosing scope
 196 = The field {0} is defined in an inherited type and an enclosing scope 
 197 = The type {0} is defined in an inherited type and an enclosing scope
+198 = Cannot allocate the member type {0} using its compound name when qualified by an enclosing instance. The member type name is resolved relatively to the qualifying instance type
 
 200 = Cannot use {0} in a static context 
-201 = The method {1}({2}) from the type {0} is not static
+201 = Cannot make a static reference to the non-static method {1}({2}) from the type {0}
 202 = Cannot specify an array dimension after an empty dimension
-203 = Invalid cast type expression
+203 = Invalid cast expression
 204 = Syntax error on token "{0}", {1} expected
 205 = Syntax error on token "{0}", no accurate correction available
 206 = Invalid argument to operation ++/--
@@ -206,6 +209,7 @@
 259 = String literal is not properly closed by a double-quote
 260 = Unexpected end of comment
 261 = Non-externalized string literal; it should be followed by //$NON-NLS-<n>$
+262 = Invalid digit (valid ones are 0..9)
 
 300 = The interface {0} cannot define an initializer
 301 = Duplicate modifier for the type {0}
@@ -214,16 +218,17 @@
 304 = Illegal modifier for the member class {0}; only public, protected, private, static, abstract & final are permitted
 305 = Illegal modifier for the member interface {0}; only public, protected, private, static & abstract are permitted
 306 = Illegal modifier for the local class {0}; only one of abstract or final is permitted
+307 = Access restriction: {0}
 308 = The class {0} can be either abstract or final, not both
 309 = The interface member type {0} can only be public
 310 = The member type {0} can only set one of public / protected / private
 311 = The member type {0} cannot be declared static; static types can only be declared in static or top level types
-312 = The interface {0} cannot be the superclass of {1}; a superclass must be a class
+312 = The type {0} cannot be the superclass of {1}; a superclass must be a class
 313 = The type {1} cannot subclass the final class {0}
 314 = Duplicate interface {0} for the type {1}
-315 = The class {0} cannot be a superinterface of {1}; a superinterface must be an interface
-316 = {1} causes a cycle - the type {0} cannot extend/implement itself or one of its own member types
-317 = A cycle exists in the type hierarchy between {0} and {1}
+315 = The type {0} cannot be a superinterface of {1}; a superinterface must be an interface
+316 = Cycle detected: the type {0} cannot extend/implement itself or one of its own member types
+317 = Cycle detected: a cycle exists in the type hierarchy between {0} and {1}
 318 = Nested type {0} hides an enclosing type
 319 = Duplicate nested type {0}
 320 = Cannot throw the type {0}
@@ -236,35 +241,38 @@
 327 = The hierarchy of the type {0} is inconsistent
 328 = The declared package does not match the expected package {0}
 329 = The type java.lang.Object cannot have a superclass or superinterfaces
+330 = The type java.lang.Object must be a class
 
-330 = {0} cannot be resolved or is not a valid superclass
-331 = Superclass {0} is not visible
-332 = Superclass {0} is ambiguous
-333 = Superclass {0} cannot be referenced using its binary name
-334 = Superclass {0} is defined in an inherited type and an enclosing scope
-335 = {0} cannot be resolved or is not a valid superinterface
-336 = Superinterface {0} is not visible
-337 = Superinterface {0} is ambiguous
-338 = Superinterface {0} cannot be referenced using its binary name
-339 = Superinterface {0} is defined in an inherited type and an enclosing scope
+###[obsolete] 330 = {0} cannot be resolved or is not a valid superclass
+###[obsolete] 331 = Superclass {0} is not visible
+###[obsolete] 332 = Superclass {0} is ambiguous
+###[obsolete] 333 = Superclass {0} cannot be referenced using its binary name
+###[obsolete] 334 = Superclass {0} is defined in an inherited type and an enclosing scope
+###[obsolete] 335 = {0} cannot be resolved or is not a valid superinterface
+###[obsolete] 336 = Superinterface {0} is not visible
+###[obsolete] 337 = Superinterface {0} is ambiguous
+###[obsolete] 338 = Superinterface {0} cannot be referenced using its binary name
+###[obsolete] 339 = Superinterface {0} is defined in an inherited type and an enclosing scope
+
 340 = Duplicate field {0}.{1}
 341 = Duplicate modifier for the field {0}
 342 = Illegal modifier for the field {0}; only public, protected, private, static, final, transient & volatile are permitted
-343 = Illegal modifier for the interface field {0}; only public, static & final are permitted
+343 = Illegal modifier for the interface field {0}.{1}; only public, static & final are permitted
 344 = The field {0} can only set one of public / protected / private
 345 = The field {0} can be either final or volatile, not both
 346 = The field {0} cannot be declared static; static fields can only be declared in static or top level types
 
-350 = {2} cannot be resolved (or is not a valid type) for the field {1}.{0}
-351 = The type {2} is not visible for the field {1}.{0}
-352 = The type {2} is ambiguous for the field {1}.{0}
-353 = The field type {2} cannot be referenced using its binary name
-354 = The field type {2} is defined in an inherited type and an enclosing scope
-355 = Duplicate method {0} in type {1}
+###[obsolete] 350 = {2} cannot be resolved (or is not a valid type) for the field {1}.{0}
+###[obsolete] 351 = The type {2} is not visible for the field {1}.{0}
+###[obsolete] 352 = The type {2} is ambiguous for the field {1}.{0}
+###[obsolete] 353 = The field type {2} cannot be referenced using its binary name
+###[obsolete] 354 = The field type {2} is defined in an inherited type and an enclosing scope
+
+355 = Duplicate method {0}({2}) in type {1}
 356 = Illegal modifier for parameter {0}; only final is permitted
 357 = Duplicate modifier for the method {1} in type {0}
-358 = Illegal modifier for the method {1} in type {0}
-359 = Illegal modifier for the interface method {1} in type {0}; only public & abstract are permitted
+358 = Illegal modifier for the method {0}.{1}({2})
+359 = Illegal modifier for the interface method {0}.{1}({2}); only public & abstract are permitted
 360 = The method {1} in type {0} can only set one of public / protected / private
 361 = The method {1} cannot be declared static; static methods can only be declared in a static or top level type
 362 = The abstract method {1} in type {0} can only set a visibility modifier, one of public or protected
@@ -275,34 +283,41 @@
 367 = The native method {1} cannot also be declared strictfp
 368 = Duplicate modifier for parameter {0}
 
-370 = {2} cannot be resolved (or is not a valid type) for the parameter {1} of the method {0}
-371 = The type {2} is not visible for the parameter {1} of the method {0}
-372 = The type {2} is ambiguous for the parameter {1} of the method {0}
-373 = The parameter type {2} cannot be referenced using its binary name
-374 = The parameter type {2} is defined in an inherited type and an enclosing scope
-375 = {1} cannot be resolved (or is not an exception type) for the method {0}
-376 = The exception type {1} is not visible for the method {0}
-377 = The exception type {1} is ambiguous for the method {0}
-378 = The exception type {1} cannot be referenced using its binary name
-379 = The exception type {1} is defined in an inherited type and an enclosing scope
-380 = {1} cannot be resolved (or is not a valid return type) for the method {0}
-381 = The return type {1} is not visible for the method {0}
-382 = The return type {1} is ambiguous for the method {0}
-383 = The return type {1} cannot be referenced using its binary name
-384 = The return type {1} is defined in an inherited type and an enclosing scope
+###[obsolete] 370 = {2} cannot be resolved (or is not a valid type) for the parameter {1} of the method {0}
+###[obsolete] 371 = The type {2} is not visible for the parameter {1} of the method {0}
+###[obsolete] 372 = The type {2} is ambiguous for the parameter {1} of the method {0}
+###[obsolete] 373 = The parameter type {2} cannot be referenced using its binary name
+###[obsolete] 374 = The parameter type {2} is defined in an inherited type and an enclosing scope
+###[obsolete] 375 = {1} cannot be resolved (or is not an exception type) for the method {0}
+###[obsolete] 376 = The exception type {1} is not visible for the method {0}
+###[obsolete] 377 = The exception type {1} is ambiguous for the method {0}
+###[obsolete] 378 = The exception type {1} cannot be referenced using its binary name
+###[obsolete] 379 = The exception type {1} is defined in an inherited type and an enclosing scope
+###[obsolete] 380 = {1} cannot be resolved (or is not a valid return type) for the method {0}
+###[obsolete] 381 = The return type {1} is not visible for the method {0}
+###[obsolete] 382 = The return type {1} is ambiguous for the method {0}
+###[obsolete] 383 = The return type {1} cannot be referenced using its binary name
+###[obsolete] 384 = The return type {1} is defined in an inherited type and an enclosing scope
+
 385 = The import {0} conflicts with a type defined in the same file
 386 = The import {0} collides with another imported type
 387 = Only a type can be imported. {0} resolves to a package
 388 = The import {0} is never used
 390 = The import {0} cannot be resolved
-391 = The imported type {0} is not visible
-392 = The imported type {0} is ambiguous
-393 = The imported type {0} cannot be referenced using its binary name
-394 = The imported type {0} is defined in an inherited type and an enclosing scope
+
+###[obsolete] 391 = The imported type {0} is not visible
+###[obsolete] 392 = The imported type {0} is ambiguous
+###[obsolete] 393 = The imported type {0} cannot be referenced using its binary name
+###[obsolete] 394 = The imported type {0} is defined in an inherited type and an enclosing scope
+
+391 = The static import {0} must be a field or member type
+
 395 = Duplicate modifier for the variable {0}
 396 = Illegal modifier for the variable {0}; only final is permitted
-
-400 = Class must implement the inherited abstract method {0}
+397 = The variable {0} cannot be null; it was either set to a non-null value or assumed to be non-null when last used
+398 = The variable {0} can only be null; it was either set to null or checked for null when last used
+	
+400 = The type {3} must implement the inherited abstract method {2}.{0}({1})
 401 = Cannot override the final method from {0}
 402 = Exception {0} is not compatible with throws clause in {1}
 403 = Exception {0} in throws clause of {1} is not compatible with {2}
@@ -317,6 +332,7 @@
 412 = The method {0} overrides a deprecated method from {1}
 413 = The return type is incompatible with {0}, thus this interface cannot be implemented
 414 = Exception {0} is not compatible with throws clause in {1}, thus this interface cannot be implemented
+415 = The variable argument type {0} of the method {1} must be the last parameter
 
 420 = Code snippet support cannot find the class {0}
 421 = Code snippet support cannot find the method {0}.{1}({2}) 
@@ -329,11 +345,14 @@
 433 = Too many methods for type {0}. Maximum is 65535
 
 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 1.5 on
 
 450 = {0} {1}
 
 460 = Empty block should be documented
 
+### DOC 
+469 = Invalid param tag type parameter name
 470 = Unexpected tag
 471 = Missing tag for parameter {0}
 472 = Missing parameter name
@@ -348,7 +367,7 @@
 481 = Exception {0} is not declared
 482 = Missing reference
 483 = Invalid reference
-484 = Invalid URL link format
+484 = Malformed link reference
 485 = Invalid parameters declaration
 486 = Missing comment for {0} declaration
 487 = Invalid tag
@@ -367,7 +386,7 @@
 500 = Cannot invoke {1}({2}) on the primitive type {0}
 501 = The method {1}({2}) in the type {0} is not applicable for the arguments ({3})
 502 = Cannot invoke {1}({2}) on the array type {0}
-503 = {0} cannot be resolved or is not a type
+503 = {0} cannot be resolved to a type
 504 = The type {0} is not visible
 505 = The type {0} is ambiguous
 506 = The type {0} is deprecated
@@ -377,5 +396,123 @@
 510 = The type {0} is defined in an inherited type and an enclosing scope
 511 = {0} is an ambiguous method reference or is not a field
 512 = Missing closing brace for inline tag
-513 = Malformed reference (missing separator after method reference closing brace)
-515 = Javadoc: 
+513 = Missing #: "{0}"
+514 = Malformed reference (missing end space separator)
+515 = Missing return type description
+516 = Only static field reference is allowed for @value tag
+517 = Unexpected text
+518 = Invalid param tag name
+519 = Javadoc: 
+
+### GENERICS
+520 = Duplicate type parameter {0}
+521 = Cannot refer to the type parameter {0} as a supertype
+522 = Cannot make a static reference to the type parameter {0}
+523 = The type java.lang.Object cannot be declared as a generic
+524 = The type {0} is not generic; it cannot be parameterized with arguments <{1}>
+525 = Incorrect number of arguments for type {0}; it cannot be parameterized with arguments <{1}>
+526 = Bound mismatch: The type {0} is not a valid substitute for the bounded parameter <{2} extends {3}> of the type {1}
+527 = Method {0}({2}) has the same erasure {0}({3}) as another method in type {1}
+528 = Illegal forward reference to type parameter {0}
+529 = The type {0} is not an interface; it cannot be specified as a bounded parameter
+530 = Type safety: The constructor {0}({1}) belongs to the raw type {0}. References to generic type {2} should be parameterized
+531 = Type safety: The method {0}({1}) belongs to the raw type {2}. References to generic type {3} should be parameterized
+532 = Type safety: The expression of type {0} is converted to {1} using a raw conversion. References to generic type {2} should be parameterized
+533 = Cannot use the type parameter {0} in a catch block
+534 = Cannot use the parameterized type {0} either in catch block or throws clause
+535 = Cannot create a generic array of {0}
+536 = Type safety: The field {1} from the raw type {2} is assigned a value of type {0}. References to generic type {3} should be parameterized
+537 = The type parameter {0} should not be bounded by the final type {1}. Final types cannot be further extended
+538 = Inconsistent classfile encountered: The undefined type parameter {0} is referenced from within {1}
+539 = The interface {2} cannot be implemented more than once with different arguments: {0} and {1}
+540 = Bound mismatch: The constructor {0}({1}) of type {2} is not applicable for the arguments ({3}). The wildcard parameter {5} has no lower bound, and may actually be more restrictive than argument {4}
+541 = Bound mismatch: The method {0}({1}) of type {2} is not applicable for the arguments ({3}). The wildcard parameter {5} has no lower bound, and may actually be more restrictive than argument {4}
+542 = Bound mismatch: Cannot assign expression of type {0} to wildcard type {1}. The wildcard type has no lower bound, and may actually be more restrictive than expression type
+543 = Bound mismatch: The generic method {0}({1}) of type {2} is not applicable for the arguments ({3}) since the type {4} is not a valid substitute for the bounded parameter <{5} extends {6}>
+544 = Bound mismatch: The generic constructor {0}({1}) of type {2} is not applicable for the arguments ({3}) since the type {4} is not a valid substitute for the bounded parameter <{5} extends {6}>
+545 = Type safety: The cast from {0} to {1} is actually checking against the erased type {2}
+546 = Cannot perform instanceof check against parameterized type {0}. Use instead its raw form {1} since generic type information will be erased at runtime
+547 = Cannot perform instanceof check against type parameter {0}. Use instead its erasure {1} since generic type information will be erased at runtime
+548 = The method {0}({1}) of type {2} is not generic; it cannot be parameterized with arguments <{3}>
+549 = Incorrect number of type arguments for generic method <{3}>{0}({1}) of type {2}; it cannot be parameterized with arguments <{4}>
+550 = The parameterized method <{3}>{0}({1}) of type {2} is not applicable for the arguments ({4})
+551 = The constructor {0}({1}) of type {2} is not generic; it cannot be parameterized with arguments <{3}>
+552 = Incorrect number of type arguments for generic constructor <{3}>{0}({1}) of type {2}; it cannot be parameterized with arguments <{4}>
+553 = The parameterized constructor <{3}>{0}({1}) of type {2} is not applicable for the arguments ({4})
+554 = The method {0}({1}) of raw type {2} is no longer generic; it cannot be parameterized with arguments <{3}>
+555 = The constructor {0}({1}) of raw type {2} is no longer generic; it cannot be parameterized with arguments <{3}>
+556 = The type {1} cannot extend or implement {0}. A supertype may not specify any wildcard
+557 = The generic class {0} may not subclass java.lang.Throwable
+558 = Illegal class literal for the type parameter {0}
+559 = Type safety: The return type {0} of the method {1}({2}) of type {3} needs unchecked conversion to conform to the return type {4} of inherited method
+560 = Name clash: The method {0}({1}) of type {2} has the same erasure as {0}({3}) of type {4} but does not override it
+561 = The member type {0}<{1}> must be qualified with a parameterized type, since it is not static
+562 = The member type {0} must be parameterized, since it is qualified with a parameterized type
+563 = The member type {0} cannot be qualified with a parameterized type, since it is static. Remove arguments from qualifying type {1}
+564 = Bound conflict: {0} is inherited with conflicting arguments
+565 = Duplicate methods named {0} with the parameters ({2}) and ({3}) are defined by the type {1}
+
+### FOREACH
+580 = Type mismatch: cannot convert from element type {0} to {1}
+581 = Can only iterate over an array or an instance of java.lang.Iterable
+
+### SOURCE LEVEL
+590 = Syntax error, type parameters are only available if source level is 1.5
+591 = Syntax error, static imports are only available if source level is 1.5
+592 = Syntax error, ''for each'' statements are only available if source level is 1.5
+593 = Syntax error, parameterized types are only available if source level is 1.5
+594 = Syntax error, enum declarations are only available if source level is 1.5
+595 = Syntax error, varargs are only available if source level is 1.5
+596 = Syntax error, annotations are only available if source level is 1.5
+597 = Syntax error, annotation declarations are only available if source level is 1.5
+
+### ANNOTATIONS
+600 = Illegal modifier for the annotation attribute {0}.{1}; only public & abstract are permitted
+601 = Extended dimensions are illegal in an annotation attribute declaration
+602 = Package annotations must be in file package-info.java
+603 = Illegal modifier for the annotation type {0}; only public & abstract are permitted
+604 = Illegal modifier for the member annotation type {0}; only public, protected, private, static & abstract are permitted
+605 = Invalid type {0} for the annotation attribute {2}.{1}; only primitive type, String, Class, annotation, enumeration are permitted or 1-dimensional arrays thereof
+606 = Cycle detected: the annotation type {0} cannot contain attributes of the annotation type itself
+607 = Cycle detected: a cycle exists in between annotation attributes of {0} and {1}
+608 = Duplicate annotation @{0}
+609 = The annotation @{0} must define the attribute {1}
+610 = Duplicate attribute {0} in annotation @{1}
+611 = The attribute {0} is undefined for the annotation type {1}
+612 = The value for annotation attribute {0}.{1} must be a class literal
+613 = The value for annotation attribute {0}.{1} must be a constant expression
+614 = The annotation field {0}.{1} must be initialized with a constant expression
+615 = Illegal modifier for the annotation field {0}.{1}; only public, static & final are permitted
+616 = The annotation type {0} cannot override the method {1}.{2}({3})
+617 = Annotation attributes cannot have parameters
+618 = Annotation attributes cannot be generic
+619 = Annotation type declaration cannot have an explicit superclass
+620 = Annotation type declaration cannot have explicit superinterfaces
+621 = Duplicate element {0} specified in annotation @{1}
+622 = The annotation @{0} is disallowed for this location
+623 = The method {0}({1}) of type {2} must override a superclass method
+624 = Annotation type declaration cannot have a constructor
+
+### CORRUPTED BINARIES
+700 = The class file {0} contains a signature ''{1}'' ill-formed at position {2}
+
+### AUTOBOXING
+720 = The expression of type {0} is boxed into {1}
+721 = The expression of type {0} is unboxed into {1}
+
+### ENUMS
+750 = Illegal modifier for the enum {0}; only public is permitted
+751 = Illegal modifier for the enum constant {0}; no modifier is allowed
+752 = Illegal modifier for the local enum {0}; only abstract is permitted
+753 = Illegal modifier for the member enum {0}; only public, protected, private, static & abstract are permitted
+754 = The enum {1} already defines the method {0}({2}) implicitly
+755 = Cannot qualify the name of the enum constant {0} in a case label
+756 = The type {1} may not subclass {0} explicitly
+757 = Cannot invoke super constructor from enum constructor {0}({1})
+758 = The enum {2} can only define the abstract method {0}({1}) if it also defines enum constants with corresponding implementations
+
+### VARARGS
+800 = Extended dimensions are illegal for a variable argument
+801 = Varargs argument {0} should be cast to {1} when passed to the method {2}({3}) from type {4}
+802 = Varargs argument {0} should be cast to {1} when passed to the constructor {2}({3})
+
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/FloatUtil.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/FloatUtil.java
new file mode 100644
index 0000000..6f2c816
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/FloatUtil.java
@@ -0,0 +1,421 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.util;
+
+/**
+ * Internal utility for declaing with hexadecimal double and float literals.
+ * 
+ * @since 3.1
+ */
+public class FloatUtil {
+
+	private static final int DOUBLE_FRACTION_WIDTH = 52;
+
+	private static final int DOUBLE_PRECISION = 53;
+
+	private static final int MAX_DOUBLE_EXPONENT = +1023;
+	
+	private static final int MIN_NORMALIZED_DOUBLE_EXPONENT = -1022;
+
+	private static final int MIN_UNNORMALIZED_DOUBLE_EXPONENT = MIN_NORMALIZED_DOUBLE_EXPONENT
+			- DOUBLE_PRECISION;
+
+	private static final int DOUBLE_EXPONENT_BIAS = +1023;
+
+	private static final int DOUBLE_EXPONENT_SHIFT = 52;
+
+	private static final int SINGLE_FRACTION_WIDTH = 23;
+
+	private static final int SINGLE_PRECISION = 24;
+
+	private static final int MAX_SINGLE_EXPONENT = +127;
+
+	private static final int MIN_NORMALIZED_SINGLE_EXPONENT = -126;
+
+	private static final int MIN_UNNORMALIZED_SINGLE_EXPONENT = MIN_NORMALIZED_SINGLE_EXPONENT
+			- SINGLE_PRECISION;
+
+	private static final int SINGLE_EXPONENT_BIAS = +127;
+
+	private static final int SINGLE_EXPONENT_SHIFT = 23;
+
+	/**
+	 * Returns the float value corresponding to the given 
+	 * hexadecimal floating-point single precision literal.
+	 * The literal must be syntactially correct, and must be
+	 * a float literal (end in a 'f' or 'F'). It must not
+	 * include either leading or trailing whitespace or
+	 * a sign.
+	 * <p>
+	 * This method returns the same answer as
+	 * Float.parseFloat(new String(source)) does in JDK 1.5,
+	 * except that this method returns Floal.NaN if it
+	 * would underflow to 0 (parseFloat just returns 0).
+	 * The method handles all the tricky cases, including 
+	 * fraction rounding to 24 bits and gradual underflow.
+	 * </p>
+	 * 
+	 * @param source source string containing single precision
+	 * hexadecimal floating-point literal
+	 * @return the float value, including Float.POSITIVE_INFINITY
+	 * if the non-zero value is too large to be represented, and
+	 * Float.NaN if the non-zero value is too small to be represented
+	 */
+	public static float valueOfHexFloatLiteral(char[] source) {
+		long bits = convertHexFloatingPointLiteralToBits(source);
+		return Float.intBitsToFloat((int) bits);
+	}
+
+	/**
+	 * Returns the double value corresponding to the given 
+	 * hexadecimal floating-point double precision literal.
+	 * The literal must be syntactially correct, and must be
+	 * a double literal (end in an optional 'd' or 'D').
+	 * It must not include either leading or trailing whitespace or
+	 * a sign.
+	 * <p>
+	 * This method returns the same answer as
+	 * Double.parseDouble(new String(source)) does in JDK 1.5,
+	 * except that this method throw NumberFormatException in
+	 * the case of overflow to infinity or underflow to 0.
+	 * The method handles all the tricky cases, including 
+	 * fraction rounding to 53 bits and gradual underflow.
+	 * </p>
+	 * 
+	 * @param source source string containing double precision
+	 * hexadecimal floating-point literal
+	 * @return the double value, including Double.POSITIVE_INFINITY
+	 * if the non-zero value is too large to be represented, and
+	 * Double.NaN if the non-zero value is too small to be represented
+	 */
+	public static double valueOfHexDoubleLiteral(char[] source) {
+		long bits = convertHexFloatingPointLiteralToBits(source);
+		return Double.longBitsToDouble(bits);
+	}
+
+	/**
+	 * Returns the given hexadecimal floating-point literal as
+	 * the bits for a single-precision  (float) or a
+	 * double-precision (double) IEEE floating point number.
+	 * The literal must be syntactially correct.  It must not
+	 * include either leading or trailing whitespace or a sign.
+	 * 
+	 * @param source source string containing hexadecimal floating-point literal
+	 * @return for double precision literals, bits suitable 
+	 * for passing to Double.longBitsToDouble; for single precision literals,
+	 * bits suitable for passing to Single.intBitsToDouble in the bottom
+	 * 32 bits of the result
+	 * @throws NumberFormatException if the number cannot be parsed
+	 */
+	private static long convertHexFloatingPointLiteralToBits(char[] source) {
+		int length = source.length;
+		long mantissa = 0;
+
+		// Step 1: process the '0x' lead-in
+		int next = 0;
+		char nextChar = source[next];
+		nextChar = source[next];
+		if (nextChar == '0') {
+			next++;
+		} else {
+			throw new NumberFormatException();
+		}
+		nextChar = source[next];
+		if (nextChar == 'X' || nextChar == 'x') {
+			next++;
+		} else {
+			throw new NumberFormatException();
+		}
+
+		// Step 2: process leading '0's either before or after the '.'
+		int binaryPointPosition = -1;
+		loop: while (true) {
+			nextChar = source[next];
+			switch (nextChar) {
+			case '0':
+				next++;
+				continue loop;
+			case '.':
+				binaryPointPosition = next;
+				next++;
+				continue loop;
+			default:
+				break loop;
+			}
+		}
+
+		// Step 3: process the mantissa
+		// leading zeros have been trimmed
+		int mantissaBits = 0;
+		int leadingDigitPosition = -1;
+		loop: while (true) {
+			nextChar = source[next];
+			int hexdigit;
+			switch (nextChar) {
+			case '0':
+			case '1':
+			case '2':
+			case '3':
+			case '4':
+			case '5':
+			case '6':
+			case '7':
+			case '8':
+			case '9':
+				hexdigit = nextChar - '0';
+				break;
+			case 'a':
+			case 'b':
+			case 'c':
+			case 'd':
+			case 'e':
+			case 'f':
+				hexdigit = (nextChar - 'a') + 10;
+				break;
+			case 'A':
+			case 'B':
+			case 'C':
+			case 'D':
+			case 'E':
+			case 'F':
+				hexdigit = (nextChar - 'A') + 10;
+				break;
+			case '.':
+				binaryPointPosition = next;
+				next++;
+				continue loop;
+			default:
+				if (binaryPointPosition < 0) {
+					// record virtual '.' as being to right of all digits
+					binaryPointPosition = next;
+				}
+				break loop;
+			}
+			if (mantissaBits == 0) {
+				// this is the first non-zero hex digit
+				// ignore leading binary 0's in hex digit
+				leadingDigitPosition = next;
+				mantissa = hexdigit;
+				mantissaBits = 4;
+			} else if (mantissaBits < 60) {
+				// middle hex digits
+				mantissa <<= 4;
+				mantissa |= hexdigit;
+				mantissaBits += 4;
+			} else {
+				// more mantissa bits than we can handle
+				// drop this hex digit on the ground
+			}
+			next++;
+			continue loop;
+		}
+
+		// Step 4: process the 'P'
+		nextChar = source[next];
+		if (nextChar == 'P' || nextChar == 'p') {
+			next++;
+		} else {
+			throw new NumberFormatException();
+		}
+
+		// Step 5: process the exponent
+		int exponent = 0;
+		int exponentSign = +1;
+		loop: while (next < length) {
+			nextChar = source[next];
+			switch (nextChar) {
+			case '+':
+				exponentSign = +1;
+				next++;
+				continue loop;
+			case '-':
+				exponentSign = -1;
+				next++;
+				continue loop;
+			case '0':
+			case '1':
+			case '2':
+			case '3':
+			case '4':
+			case '5':
+			case '6':
+			case '7':
+			case '8':
+			case '9':
+				int digit = nextChar - '0';
+				exponent = (exponent * 10) + digit;
+				next++;
+				continue loop;
+			default:
+				break loop;
+			}
+		}
+
+		// Step 6: process the optional 'f' or 'd'
+		boolean doublePrecision = true;
+		if (next < length) {
+			nextChar = source[next];
+			switch (nextChar) {
+			case 'f':
+			case 'F':
+				doublePrecision = false;
+				next++;
+				break;
+			case 'd':
+			case 'D':
+				doublePrecision = true;
+				next++;
+				break;
+			default:
+				throw new NumberFormatException();
+			}
+		}
+
+		// at this point, all the parsing is done
+		// Step 7: handle mantissa of zero
+		if (mantissa == 0) {
+			return 0L;
+		}
+
+		// Step 8: normalize non-zero mantissa
+		// mantissa is in right-hand mantissaBits
+		// ensure that top bit (as opposed to hex digit) is 1
+		int scaleFactorCompensation = 0;
+		long top = (mantissa >>> (mantissaBits - 4));
+		if ((top & 0x8) == 0) {
+			mantissaBits--;
+			scaleFactorCompensation++;
+			if ((top & 0x4) == 0) {
+				mantissaBits--;
+				scaleFactorCompensation++;
+				if ((top & 0x2) == 0) {
+					mantissaBits--;
+					scaleFactorCompensation++;
+				}
+			}
+		}
+		
+		// Step 9: convert double literals to IEEE double
+		long result = 0L;
+		if (doublePrecision) {
+			long fraction;
+			if (mantissaBits > DOUBLE_PRECISION) {
+				// more bits than we can keep
+				int extraBits = mantissaBits - DOUBLE_PRECISION;
+				// round to DOUBLE_PRECISION bits
+				fraction = mantissa >>> (extraBits - 1);
+				long lowBit = fraction & 0x1;
+				fraction += lowBit;
+				fraction = fraction >>> 1;
+				if ((fraction & (1L << DOUBLE_PRECISION)) != 0) {
+					fraction = fraction >>> 1;
+					scaleFactorCompensation -= 1;
+				}
+			} else {
+				// less bits than the faction can hold - pad on right with 0s
+				fraction = mantissa << (DOUBLE_PRECISION - mantissaBits);
+			}
+
+			int scaleFactor = 0; // how many bits to move '.' to before leading hex digit
+			if (mantissaBits > 0) {
+				if (leadingDigitPosition < binaryPointPosition) {
+					// e.g., 0x80.0p0 has scaleFactor == +8 
+					scaleFactor = 4 * (binaryPointPosition - leadingDigitPosition);
+					// e.g., 0x10.0p0 has scaleFactorCompensation == +3 
+					scaleFactor -= scaleFactorCompensation;
+				} else {
+					// e.g., 0x0.08p0 has scaleFactor == -4 
+					scaleFactor = -4
+							* (leadingDigitPosition - binaryPointPosition - 1);
+					// e.g., 0x0.01p0 has scaleFactorCompensation == +3 
+					scaleFactor -= scaleFactorCompensation;
+				}
+			}
+
+			int e = (exponentSign * exponent) + scaleFactor;
+			if (e - 1 > MAX_DOUBLE_EXPONENT) {
+				// overflow to +infinity
+				result = Double.doubleToLongBits(Double.POSITIVE_INFINITY);
+			} else if (e - 1 >= MIN_NORMALIZED_DOUBLE_EXPONENT) {
+				// can be represented as a normalized double
+				// the left most bit must be discarded (it's always a 1)
+				long biasedExponent = e - 1 + DOUBLE_EXPONENT_BIAS;
+				result = fraction & ~(1L << DOUBLE_FRACTION_WIDTH);
+				result |= (biasedExponent << DOUBLE_EXPONENT_SHIFT);
+			} else if (e - 1 > MIN_UNNORMALIZED_DOUBLE_EXPONENT) {
+				// can be represented as an unnormalized double
+				long biasedExponent = 0;
+				result = fraction >>> (MIN_NORMALIZED_DOUBLE_EXPONENT - e + 1);
+				result |= (biasedExponent << DOUBLE_EXPONENT_SHIFT);
+			} else {
+				// underflow - return Double.NaN
+				result = Double.doubleToLongBits(Double.NaN);
+			}
+			return result;
+		}
+
+		// Step 10: convert float literals to IEEE single
+		long fraction;
+		if (mantissaBits > SINGLE_PRECISION) {
+			// more bits than we can keep
+			int extraBits = mantissaBits - SINGLE_PRECISION;
+			// round to DOUBLE_PRECISION bits
+			fraction = mantissa >>> (extraBits - 1);
+			long lowBit = fraction & 0x1;
+			fraction += lowBit;
+			fraction = fraction >>> 1;
+			if ((fraction & (1L << SINGLE_PRECISION)) != 0) {
+				fraction = fraction >>> 1;
+				scaleFactorCompensation -= 1;
+			}
+		} else {
+			// less bits than the faction can hold - pad on right with 0s
+			fraction = mantissa << (SINGLE_PRECISION - mantissaBits);
+		}
+
+		int scaleFactor = 0; // how many bits to move '.' to before leading hex digit
+		if (mantissaBits > 0) {
+			if (leadingDigitPosition < binaryPointPosition) {
+				// e.g., 0x80.0p0 has scaleFactor == +8 
+				scaleFactor = 4 * (binaryPointPosition - leadingDigitPosition);
+				// e.g., 0x10.0p0 has scaleFactorCompensation == +3 
+				scaleFactor -= scaleFactorCompensation;
+			} else {
+				// e.g., 0x0.08p0 has scaleFactor == -4 
+				scaleFactor = -4
+						* (leadingDigitPosition - binaryPointPosition - 1);
+				// e.g., 0x0.01p0 has scaleFactorCompensation == +3 
+				scaleFactor -= scaleFactorCompensation;
+			}
+		}
+
+		int e = (exponentSign * exponent) + scaleFactor;
+		if (e - 1 > MAX_SINGLE_EXPONENT) {
+			// overflow to +infinity
+			result = Float.floatToIntBits(Float.POSITIVE_INFINITY);
+		} else if (e - 1 >= MIN_NORMALIZED_SINGLE_EXPONENT) {
+			// can be represented as a normalized single
+			// the left most bit must be discarded (it's always a 1)
+			long biasedExponent = e - 1 + SINGLE_EXPONENT_BIAS;
+			result = fraction & ~(1L << SINGLE_FRACTION_WIDTH);
+			result |= (biasedExponent << SINGLE_EXPONENT_SHIFT);
+		} else if (e - 1 > MIN_UNNORMALIZED_SINGLE_EXPONENT) {
+			// can be represented as an unnormalized single
+			long biasedExponent = 0;
+			result = fraction >>> (MIN_NORMALIZED_SINGLE_EXPONENT - e + 1);
+			result |= (biasedExponent << SINGLE_EXPONENT_SHIFT);
+		} else {
+			// underflow - return Float.NaN
+			result = Float.floatToIntBits(Float.NaN);
+		}
+		return result;
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfObjectToInt.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfObjectToInt.java
new file mode 100644
index 0000000..18656f7
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfObjectToInt.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.util;
+
+/**
+ * Hashtable of {Object --> int }
+ */
+public final class HashtableOfObjectToInt implements Cloneable {
+	
+	// to avoid using Enumerations, walk the individual tables skipping nulls
+	public Object[] keyTable;
+	public int[] valueTable;
+
+	public int elementSize; // number of elements in the table
+	int threshold;
+
+	public HashtableOfObjectToInt() {
+		this(13);
+	}
+
+	public HashtableOfObjectToInt(int size) {
+
+		this.elementSize = 0;
+		this.threshold = size; // size represents the expected number of elements
+		int extraRoom = (int) (size * 1.75f);
+		if (this.threshold == extraRoom)
+			extraRoom++;
+		this.keyTable = new Object[extraRoom];
+		this.valueTable = new int[extraRoom];
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		HashtableOfObjectToInt result = (HashtableOfObjectToInt) super.clone();
+		result.elementSize = this.elementSize;
+		result.threshold = this.threshold;
+
+		int length = this.keyTable.length;
+		result.keyTable = new Object[length];
+		System.arraycopy(this.keyTable, 0, result.keyTable, 0, length);
+
+		length = this.valueTable.length;
+		result.valueTable = new int[length];
+		System.arraycopy(this.valueTable, 0, result.valueTable, 0, length);
+		return result;
+	}
+
+	public boolean containsKey(Object key) {
+
+		int index = key.hashCode() % this.valueTable.length;
+		Object currentKey;
+		while ((currentKey = this.keyTable[index]) != null) {
+			if (currentKey.equals(key))
+				return true;
+			index = (index + 1) % this.keyTable.length;
+		}
+		return false;
+	}
+
+	public int get(Object key) {
+
+		int index = key.hashCode() % this.valueTable.length;
+		Object currentKey;
+		while ((currentKey = this.keyTable[index]) != null) {
+			if (currentKey.equals(key))
+				return this.valueTable[index];
+			index = (index + 1) % this.keyTable.length;
+		}
+		return -1;
+	}
+
+	public int put(Object key, int value) {
+
+		int index = key.hashCode() % this.valueTable.length;
+		Object currentKey;
+		while ((currentKey = this.keyTable[index]) != null) {
+			if (currentKey.equals(key))
+				return this.valueTable[index] = value;
+			index = (index + 1) % this.keyTable.length;
+		}
+		this.keyTable[index] = key;
+		this.valueTable[index] = value;
+
+		// assumes the threshold is never equal to the size of the table
+		if (++elementSize > threshold)
+			rehash();
+		return value;
+	}
+
+	public int removeKey(Object key) {
+
+		int index = key.hashCode() % this.valueTable.length;
+		Object currentKey;
+		while ((currentKey = this.keyTable[index]) != null) {
+			if (currentKey.equals(key)) {
+				int value = this.valueTable[index];
+				elementSize--;
+				this.keyTable[index] = null;
+				rehash();
+				return value;
+			}
+			index = (index + 1) % this.keyTable.length;
+		}
+		return -1;
+	}
+
+	private void rehash() {
+
+		HashtableOfObjectToInt newHashtable = new HashtableOfObjectToInt(elementSize * 2);		// double the number of expected elements
+		Object currentKey;
+		for (int i = this.keyTable.length; --i >= 0;)
+			if ((currentKey = this.keyTable[i]) != null)
+				newHashtable.put(currentKey, this.valueTable[i]);
+
+		this.keyTable = newHashtable.keyTable;
+		this.valueTable = newHashtable.valueTable;
+		this.threshold = newHashtable.threshold;
+	}
+
+	public int size() {
+		return elementSize;
+	}
+
+	public String toString() {
+		String s = ""; //$NON-NLS-1$
+		Object key;
+		for (int i = 0, length = this.keyTable.length; i < length; i++)
+			if ((key = this.keyTable[i]) != null)
+				s += key + " -> " + this.valueTable[i] + "\n"; 	//$NON-NLS-2$ //$NON-NLS-1$
+		return s;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleLookupTable.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SimpleLookupTable.java
similarity index 98%
rename from org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleLookupTable.java
rename to org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SimpleLookupTable.java
index 5f411a4..978c301 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleLookupTable.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SimpleLookupTable.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
-package org.eclipse.jdt.internal.core.util;
+package org.eclipse.jdt.internal.compiler.util;
 
 /**
  * A simple lookup table is a non-synchronized Hashtable, whose keys
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
index 957c329..ef2e5bd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
@@ -29,40 +29,47 @@
 	public interface Displayable {
 		String displayString(Object o);
 	}
-
-	public static String LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$
-	public static char[] LINE_SEPARATOR_CHARS = LINE_SEPARATOR.toCharArray();
-	
-	private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
-	private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
-	private static final int DEFAULT_READING_SIZE = 8192;
+	static {
+		relocalize();
+	}
 
 	/* Bundle containing messages */
 	protected static ResourceBundle bundle;
 	private final static String bundleName =
 		"org.eclipse.jdt.internal.compiler.util.messages"; //$NON-NLS-1$
-	static {
-		relocalize();
-	}
+	private static final int DEFAULT_READING_SIZE = 8192;
+	
+	private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
+
+	public static String LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$
+	public static char[] LINE_SEPARATOR_CHARS = LINE_SEPARATOR.toCharArray();
+	private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
+	
 	/**
-	 * Lookup the message with the given ID in this catalog and bind its
-	 * substitution locations with the given strings.
+	 * Lookup the message with the given ID in this catalog 
 	 */
-	public static String bind(String id, String binding1, String binding2) {
-		return bind(id, new String[] { binding1, binding2 });
+	public static String bind(String id) {
+		return bind(id, (String[]) null);
 	}
 	/**
 	 * Lookup the message with the given ID in this catalog and bind its
 	 * substitution locations with the given string.
 	 */
-	public static String bind(String id, String binding) {
-		return bind(id, new String[] { binding });
+	public static String bind(String id, String argument) {
+		return bind(id, new String[] { argument });
+	}
+	/**
+	 * Lookup the message with the given ID in this catalog and bind its
+	 * substitution locations with the given strings.
+	 */
+	public static String bind(String id, String argument1, String argument2) {
+		return bind(id, new String[] { argument1, argument2 });
 	}
 	/**
 	 * Lookup the message with the given ID in this catalog and bind its
 	 * substitution locations with the given string values.
 	 */
-	public static String bind(String id, String[] bindings) {
+	public static String bind(String id, String[] arguments) {
 		if (id == null)
 			return "No message available"; //$NON-NLS-1$
 		String message = null;
@@ -73,11 +80,17 @@
 			// the id we were looking for.  In most cases this is semi-informative so is not too bad.
 			return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
 		}
+		return bindMessage(message, arguments);
+	}
+	/**
+	 * Bind some message with given string values.
+	 */
+	public static String bindMessage(String message, String[] arguments) {
 		// for compatibility with MessageFormat which eliminates double quotes in original message
 		char[] messageWithNoDoubleQuotes =
 			CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
 	
-		if (bindings == null) return new String(messageWithNoDoubleQuotes);
+		if (arguments == null) return new String(messageWithNoDoubleQuotes);
 	
 		int length = messageWithNoDoubleQuotes.length;
 		int start = 0;
@@ -85,25 +98,27 @@
 		StringBuffer output = null;
 		while (true) {
 			if ((end = CharOperation.indexOf('{', messageWithNoDoubleQuotes, start)) > -1) {
-				if (output == null) output = new StringBuffer(length+bindings.length*20);
+				if (output == null) output = new StringBuffer(length+arguments.length*20);
 				output.append(messageWithNoDoubleQuotes, start, end - start);
 				if ((start = CharOperation.indexOf('}', messageWithNoDoubleQuotes, end + 1)) > -1) {
 					int index = -1;
 					String argId = new String(messageWithNoDoubleQuotes, end + 1, start - end - 1);
 					try {
 						index = Integer.parseInt(argId);
-						output.append(bindings[index]);
+						if (arguments[index] == null) {
+							output.append('{').append(argId).append('}'); // leave parameter in since no better arg '{0}'
+						} else {
+							output.append(arguments[index]);
+						}						
 					} catch (NumberFormatException nfe) { // could be nested message ID {compiler.name}
 						boolean done = false;
-						if (!id.equals(argId)) {
-							String argMessage = null;
-							try {
-								argMessage = bundle.getString(argId);
-								output.append(argMessage);
-								done = true;
-							} catch (MissingResourceException e) {
-								// unable to bind argument, ignore (will leave argument in)
-							}
+						String argMessage = null;
+						try {
+							argMessage = bundle.getString(argId);
+							output.append(argMessage);
+							done = true;
+						} catch (MissingResourceException e) {
+							// unable to bind argument, ignore (will leave argument in)
 						}
 						if (!done) output.append(messageWithNoDoubleQuotes, end + 1, start - end);
 					} catch (ArrayIndexOutOfBoundsException e) {
@@ -123,23 +138,6 @@
 		return output.toString();
 	}
 	/**
-	 * Lookup the message with the given ID in this catalog 
-	 */
-	public static String bind(String id) {
-		return bind(id, (String[]) null);
-	}
-	/**
-	 * Creates a NLS catalog for the given locale.
-	 */
-	public static void relocalize() {
-		try {
-			bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
-		} catch(MissingResourceException e) {
-			System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
-			throw e;
-		}
-	}
-	/**
 	 * Returns the given bytes as a char array using a given encoding (null means platform default).
 	 */
 	public static char[] bytesToChar(byte[] bytes, String encoding) throws IOException {
@@ -328,7 +326,7 @@
 
 			// Do not keep first character for UTF-8 BOM encoding
 			int start = 0;
-			if ("UTF-8".equals(encoding)) { //$NON-NLS-1$
+			if (contentsLength > 0 && "UTF-8".equals(encoding)) { //$NON-NLS-1$
 				if (contents[0] == 0xFEFF) { // if BOM char then skip
 					contentsLength--;
 					start = 1;
@@ -355,7 +353,7 @@
 			}
 			// Do not keep first character for UTF-8 BOM encoding
 			int start = 0;
-			if ("UTF-8".equals(encoding)) { //$NON-NLS-1$
+			if (length > 0 && "UTF-8".equals(encoding)) { //$NON-NLS-1$
 				if (contents[0] == 0xFEFF) { // if BOM char then skip
 					len--;
 					start = 1;
@@ -424,6 +422,21 @@
 	 * Returns true iff str.toLowerCase().endsWith(".class")
 	 * implementation is not creating extra strings.
 	 */
+	public final static boolean isClassFileName(char[] name) {
+		int nameLength = name == null ? 0 : name.length;
+		int suffixLength = SUFFIX_CLASS.length;
+		if (nameLength < suffixLength) return false;
+
+		for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
+			char c = name[offset + i];
+			if (c != SUFFIX_class[i] && c != SUFFIX_CLASS[i]) return false;
+		}
+		return true;		
+	}	
+	/**
+	 * Returns true iff str.toLowerCase().endsWith(".class")
+	 * implementation is not creating extra strings.
+	 */
 	public final static boolean isClassFileName(String name) {
 		int nameLength = name == null ? 0 : name.length();
 		int suffixLength = SUFFIX_CLASS.length;
@@ -436,21 +449,64 @@
 		}
 		return true;		
 	}	
+	/* TODO (philippe) should consider promoting it to CharOperation
+	 * Returns whether the given resource path matches one of the inclusion/exclusion
+	 * patterns.
+	 * NOTE: should not be asked directly using pkg root pathes
+	 * @see IClasspathEntry#getInclusionPatterns
+	 * @see IClasspathEntry#getExclusionPatterns
+	 */
+	public final static boolean isExcluded(char[] path, char[][] inclusionPatterns, char[][] exclusionPatterns, boolean isFolderPath) {
+		if (inclusionPatterns == null && exclusionPatterns == null) return false;
+
+		inclusionCheck: if (inclusionPatterns != null) {
+			for (int i = 0, length = inclusionPatterns.length; i < length; i++) {
+				char[] pattern = inclusionPatterns[i];
+				char[] folderPattern = pattern;
+				if (isFolderPath) {
+					int lastSlash = CharOperation.lastIndexOf('/', pattern);
+					if (lastSlash != -1 && lastSlash != pattern.length-1){ // trailing slash -> adds '**' for free (see http://ant.apache.org/manual/dirtasks.html)
+						int star = CharOperation.indexOf('*', pattern, lastSlash);
+						if ((star == -1
+								|| star >= pattern.length-1 
+								|| pattern[star+1] != '*')) {
+							folderPattern = CharOperation.subarray(pattern, 0, lastSlash);
+						}
+					}
+				}
+				if (CharOperation.pathMatch(folderPattern, path, true, '/')) {
+					break inclusionCheck;
+				}
+			}
+			return true; // never included
+		}
+		if (isFolderPath) {
+			path = CharOperation.concat(path, new char[] {'*'}, '/');
+		}
+		exclusionCheck: if (exclusionPatterns != null) {
+			for (int i = 0, length = exclusionPatterns.length; i < length; i++) {
+				if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/')) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}			
 	/**
-	 * Returns true iff str.toLowerCase().endsWith(".class")
+	 * Returns true iff str.toLowerCase().endsWith(".java")
 	 * implementation is not creating extra strings.
 	 */
-	public final static boolean isClassFileName(char[] name) {
+	public final static boolean isJavaFileName(char[] name) {
 		int nameLength = name == null ? 0 : name.length;
-		int suffixLength = SUFFIX_CLASS.length;
+		int suffixLength = SUFFIX_JAVA.length;
 		if (nameLength < suffixLength) return false;
 
 		for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
 			char c = name[offset + i];
-			if (c != SUFFIX_class[i] && c != SUFFIX_CLASS[i]) return false;
+			if (c != SUFFIX_java[i] && c != SUFFIX_JAVA[i]) return false;
 		}
 		return true;		
-	}	
+	}
 	/**
 	 * Returns true iff str.toLowerCase().endsWith(".java")
 	 * implementation is not creating extra strings.
@@ -468,19 +524,28 @@
 		return true;		
 	}
 	/**
-	 * Returns true iff str.toLowerCase().endsWith(".java")
-	 * implementation is not creating extra strings.
+	 * Creates a NLS catalog for the given locale.
 	 */
-	public final static boolean isJavaFileName(char[] name) {
-		int nameLength = name == null ? 0 : name.length;
-		int suffixLength = SUFFIX_JAVA.length;
-		if (nameLength < suffixLength) return false;
-
-		for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
-			char c = name[offset + i];
-			if (c != SUFFIX_java[i] && c != SUFFIX_JAVA[i]) return false;
+	public static void relocalize() {
+		try {
+			bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
+		} catch(MissingResourceException e) {
+			System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
+			throw e;
 		}
-		return true;		
+	}
+
+	/**
+	 * Converts a boolean value into Boolean.
+	 * @param bool The boolean to convert
+	 * @return The corresponding Boolean object (TRUE or FALSE).
+	 */
+	public static Boolean toBoolean(boolean bool) {
+		if (bool) {
+			return Boolean.TRUE;
+		} else {
+			return Boolean.FALSE;
+		}
 	}
 	/**
 	 * Converts an array of Objects into String.
@@ -507,17 +572,4 @@
 		}
 		return buffer.toString();
 	}
-
-	/**
-	 * Converts a boolean value into Boolean.
-	 * @param bool The boolean to convert
-	 * @return The corresponding Boolean object (TRUE or FALSE).
-	 */
-	public static Boolean toBoolean(boolean bool) {
-		if (bool) {
-			return Boolean.TRUE;
-		} else {
-			return Boolean.FALSE;
-		}
-	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/WeakHashSet.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/WeakHashSet.java
new file mode 100644
index 0000000..8d91129
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/WeakHashSet.java
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.util;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+/**
+ * A hashset whose values can be garbage collected.
+ */
+public class WeakHashSet {
+	
+	public class HashableWeakReference extends WeakReference {
+		public int hashCode;
+		public HashableWeakReference(Object referent, ReferenceQueue queue) {
+			super(referent, queue);
+			this.hashCode = referent.hashCode();
+		}
+		public boolean equals(Object obj) {
+			if (!(obj instanceof HashableWeakReference)) return false;
+			Object referent = get();
+			Object other = ((HashableWeakReference) obj).get();
+			if (referent == null) return other == null;
+			return referent.equals(other);
+		}
+		public int hashCode() {
+			return this.hashCode;
+		}
+		public String toString() {
+			Object referent = get();
+			if (referent == null) return "[hashCode=" + this.hashCode + "] <referent was garbage collected>"; //$NON-NLS-1$  //$NON-NLS-2$
+			return "[hashCode=" + this.hashCode + "] " + referent.toString(); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+	
+	HashableWeakReference[] values;
+	public int elementSize; // number of elements in the table
+	int threshold;
+	ReferenceQueue referenceQueue = new ReferenceQueue();	
+	
+	public WeakHashSet() {
+		this(5);
+	}
+	
+	public WeakHashSet(int size) {
+		this.elementSize = 0;
+		this.threshold = size; // size represents the expected number of elements
+		int extraRoom = (int) (size * 1.75f);
+		if (this.threshold == extraRoom)
+			extraRoom++;
+		this.values = new HashableWeakReference[extraRoom];
+	}
+	
+	/*
+	 * Adds the given object to this set.
+	 * If an object that is equals to the given object already exists, do nothing.
+	 * Returns the existing object or the new object if not found.
+	 */
+	public Object add(Object obj) {
+		cleanupGarbageCollectedValues();
+		int index = (obj.hashCode() & 0x7FFFFFFF) % this.values.length;
+		HashableWeakReference currentValue;
+		while ((currentValue = this.values[index]) != null) {
+			Object referent;
+			if (obj.equals(referent = currentValue.get())) {
+				return referent;
+			}
+			index = (index + 1) % this.values.length;
+		}
+		this.values[index] = new HashableWeakReference(obj, this.referenceQueue);
+
+		// assumes the threshold is never equal to the size of the table
+		if (++this.elementSize > this.threshold)
+			rehash();
+		
+		return obj;
+	}
+		
+	private void addValue(HashableWeakReference value) {
+		Object obj = value.get();
+		if (obj == null) return;
+		int valuesLength = this.values.length;
+		int index = (value.hashCode & 0x7FFFFFFF) % valuesLength;
+		HashableWeakReference currentValue;
+		while ((currentValue = this.values[index]) != null) {
+			if (obj.equals(currentValue.get())) {
+				return;
+			}
+			index = (index + 1) % valuesLength;
+		}
+		this.values[index] = value;
+
+		// assumes the threshold is never equal to the size of the table
+		if (++this.elementSize > this.threshold)
+			rehash();
+	}
+	
+	private void cleanupGarbageCollectedValues() {
+		HashableWeakReference toBeRemoved;
+		while ((toBeRemoved = (HashableWeakReference) this.referenceQueue.poll()) != null) {
+			int hashCode = toBeRemoved.hashCode;
+			int valuesLength = this.values.length;
+			int index = (hashCode & 0x7FFFFFFF) % valuesLength;
+			HashableWeakReference currentValue;
+			while ((currentValue = this.values[index]) != null) {
+				if (currentValue == toBeRemoved) {
+					// replace the value at index with the last value with the same hash
+					int sameHash = index;
+					int current;
+					while ((currentValue = this.values[current = (sameHash + 1) % valuesLength]) != null && currentValue.hashCode == hashCode)
+						sameHash = current;
+					this.values[index] = this.values[sameHash];
+					this.values[sameHash] = null;
+					this.elementSize--;
+					break;
+				}
+				index = (index + 1) % valuesLength;
+			}
+		}
+	}
+	
+	public boolean contains(Object obj) {
+		return get(obj) != null;
+	}
+	
+	/*
+	 * Return the object that is in this set and that is equals to the given object.
+	 * Return null if not found.
+	 */
+	public Object get(Object obj) {
+		cleanupGarbageCollectedValues();
+		int valuesLength = this.values.length;
+		int index = (obj.hashCode() & 0x7FFFFFFF) % valuesLength;
+		HashableWeakReference currentValue;
+		while ((currentValue = this.values[index]) != null) {
+			Object referent;
+			if (obj.equals(referent = currentValue.get())) {
+				return referent;
+			}
+			index = (index + 1) % valuesLength;
+		}
+		return null;
+	}
+		
+	private void rehash() {
+		WeakHashSet newHashSet = new WeakHashSet(this.elementSize * 2);		// double the number of expected elements
+		newHashSet.referenceQueue = this.referenceQueue;
+		HashableWeakReference currentValue;
+		for (int i = 0, length = this.values.length; i < length; i++)
+			if ((currentValue = this.values[i]) != null)
+				newHashSet.addValue(currentValue);
+
+		this.values = newHashSet.values;
+		this.threshold = newHashSet.threshold;
+		this.elementSize = newHashSet.elementSize;
+	}
+
+	/*
+	 * Removes the object that is in this set and that is equals to the given object.
+	 * Return the object that was in the set, or null if not found.
+	 */
+	public Object remove(Object obj) {
+		cleanupGarbageCollectedValues();
+		int valuesLength = this.values.length;
+		int index = (obj.hashCode() & 0x7FFFFFFF) % valuesLength;
+		HashableWeakReference currentValue;
+		while ((currentValue = this.values[index]) != null) {
+			Object referent;
+			if (obj.equals(referent = currentValue.get())) {
+				this.elementSize--;
+				this.values[index] = null;
+				rehash();
+				return referent;
+			}
+			index = (index + 1) % valuesLength;
+		}
+		return null;
+	}
+
+	public int size() {
+		return this.elementSize;
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer("{"); //$NON-NLS-1$
+		for (int i = 0, length = this.values.length; i < length; i++) {
+			HashableWeakReference value = this.values[i];
+			if (value != null) {
+				Object ref = value.get();
+				if (ref != null) {
+					buffer.append(ref.toString());
+					buffer.append(", "); //$NON-NLS-1$
+				}
+			}
+		}
+		buffer.append("}"); //$NON-NLS-1$
+		return buffer.toString();
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/messages.properties
index 8a1f05c..7a53316 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/messages.properties
@@ -54,10 +54,6 @@
 parser.endOfMethod = end of method
 parser.endOfInitializer = end of initializer
 
-### binding
-binding.subclass = anonymous subclass of {0}
-binding.implementation = anonymous implementation of {0}
-
 ### ast
 ast.missingCode = Missing code gen implementation
 
@@ -66,4 +62,5 @@
 constant.cannotConvertedTo = {0} constant cannot be converted to {1}
 
 ### miscellaneous
-error.undefinedBaseType = Undefined base type: {0}
+error.undefinedTypeVariable = Undefined type variable: {0}
+error.missingBound = The class files for {0} and {1} are out of sync
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
index 34d301a..88afc17 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
@@ -13,10 +13,13 @@
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IClassFile;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaProject;
@@ -229,6 +232,8 @@
 	 * @param compilationUnitDeclaration an internal AST node for a compilation unit declaration
 	 * @param source the string of the Java compilation unit
 	 * @param options compiler options
+	 * @param workingCopyOwner the owner of the working copy that the AST is created from, 
+	 *     or <code>null</code> if none
 	 * @param monitor the progress monitor used to report progress and request cancelation,
 	 *     or <code>null</code> if none
 	 * @param isResolved whether the given compilation unit declaration is resolved
@@ -240,21 +245,21 @@
 		char[] source,
 		Map options,
 		boolean isResolved,
+		WorkingCopyOwner workingCopyOwner,
 		IProgressMonitor monitor) {
 		
 		ASTConverter converter = new ASTConverter(options, isResolved, monitor);
 		AST ast = AST.newAST(level);
 		int savedDefaultNodeFlag = ast.getDefaultNodeFlag();
 		ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
-		BindingResolver resolver = isResolved ? new DefaultBindingResolver(compilationUnitDeclaration.scope) : new BindingResolver();
+		BindingResolver resolver = isResolved ? new DefaultBindingResolver(compilationUnitDeclaration.scope, workingCopyOwner, new DefaultBindingResolver.BindingTables()) : new BindingResolver();
 		ast.setBindingResolver(resolver);
 		converter.setAST(ast);
 	
-		CompilationUnit cu = converter.convert(compilationUnitDeclaration, source);
-		cu.setLineEndTable(compilationUnitDeclaration.compilationResult.lineSeparatorPositions);
-		resolver.storeModificationCount(ast.modificationCount());
+		CompilationUnit unit = converter.convert(compilationUnitDeclaration, source);
+		unit.setLineEndTable(compilationUnitDeclaration.compilationResult.lineSeparatorPositions);
 		ast.setDefaultNodeFlag(savedDefaultNodeFlag);
-		return cu;
+		return unit;
 	}
 
 	/**
@@ -281,17 +286,22 @@
 	// TODO (jeem) When JLS3 support is complete (post 3.0) - deprecated Clients should port their code to use the new JLS3 API and call {@link #newAST(int)} instead of using this constructor.
 	public AST(Map options) {
 		this(JLS2);
-		// override scanner if 1.4 asked for
-		if (JavaCore.VERSION_1_4.equals(options.get(JavaCore.COMPILER_SOURCE))) {
-			this.scanner = new Scanner(
-				true /*comment*/, 
-				true /*whitespace*/, 
-				false /*nls*/, 
-				ClassFileConstants.JDK1_4 /*sourceLevel*/, 
-				null/*taskTag*/, 
-				null/*taskPriorities*/,
-				true/*taskCaseSensitive*/);
+		Object sourceLevelOption = options.get(JavaCore.COMPILER_SOURCE);
+		long sourceLevel = ClassFileConstants.JDK1_3;
+		if (JavaCore.VERSION_1_4.equals(sourceLevelOption)) {
+			sourceLevel = ClassFileConstants.JDK1_4;
+		} else if (JavaCore.VERSION_1_5.equals(sourceLevelOption)) {
+			sourceLevel = ClassFileConstants.JDK1_5;
 		}
+		// override scanner if 1.4 or 1.5 asked for
+		this.scanner = new Scanner(
+			true /*comment*/, 
+			true /*whitespace*/, 
+			false /*nls*/, 
+			sourceLevel /*sourceLevel*/,
+			null/*taskTag*/, 
+			null/*taskPriorities*/,
+			true/*taskCaseSensitive*/);
 	}
 		
 	/**
@@ -1546,7 +1556,7 @@
 	 * Creates an unparented enum constant declaration node owned by this AST.
 	 * The name of the constant is an unspecified, but legal, name; 
 	 * no doc comment; no modifiers or annotations; no arguments; 
-	 * and an empty class body.
+	 * and does not declare an anonymous class.
 	 * 
 	 * @return a new unparented enum constant declaration node
 	 * @exception UnsupportedOperationException if this operation is used in
@@ -1562,7 +1572,8 @@
 	 * Creates an unparented enum declaration node owned by this AST.
 	 * The name of the enum is an unspecified, but legal, name; 
 	 * no doc comment; no modifiers or annotations; 
-	 * no superinterfaces; and no body declarations.
+	 * no superinterfaces; and empty lists of enum constants
+	 * and body declarations.
 	 * 
 	 * @return a new unparented enum declaration node
 	 * @exception UnsupportedOperationException if this operation is used in
@@ -1636,6 +1647,62 @@
 		return result;
 	}
 
+	/**
+	 * Creates and returns a list of new unparented modifier nodes 
+	 * for the given modifier flags. When multiple modifiers are 
+	 * requested the modifiers nodes will appear in the following order:
+	 * public, protected, private, abstract, static, final, synchronized,
+	 * native, strictfp, transient, volatile. This order is consistent
+	 * with the recommendations in JLS2 8.1.1, 8.3.1, and 8.4.3.
+	 * 
+	 * @param flags bitwise or of modifier flags declared on {@link Modifier}
+	 * @return a possibly empty list of new unparented modifier nodes
+	 *   (element type <code>Modifier</code>)
+	 * @exception UnsupportedOperationException if this operation is used in
+	 * a JLS2 AST
+	 * @since 3.1
+	 */
+	public List newModifiers(int flags) {
+		if (this.apiLevel == AST.JLS2) {
+			unsupportedIn2();
+		}
+		List result = new ArrayList(3); // 3 modifiers is more than average
+		if (Modifier.isPublic(flags)) {
+			result.add(newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD));
+		}
+		if (Modifier.isProtected(flags)) {
+			result.add(newModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD));
+		}
+		if (Modifier.isPrivate(flags)) {
+			result.add(newModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD));
+		}
+		if (Modifier.isAbstract(flags)) {
+			result.add(newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD));
+		}
+		if (Modifier.isStatic(flags)) {
+			result.add(newModifier(Modifier.ModifierKeyword.STATIC_KEYWORD));
+		}
+		if (Modifier.isFinal(flags)) {
+			result.add(newModifier(Modifier.ModifierKeyword.FINAL_KEYWORD));
+		}
+		if (Modifier.isSynchronized(flags)) {
+			result.add(newModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD));
+		}
+		if (Modifier.isNative(flags)) {
+			result.add(newModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD));
+		}
+		if (Modifier.isStrictfp(flags)) {
+			result.add(newModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD));
+		}
+		if (Modifier.isTransient(flags)) {
+			result.add(newModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD));
+		}
+		if (Modifier.isVolatile(flags)) {
+			result.add(newModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD));
+		}
+		return result;
+	}
+
 	//=============================== COMMENTS ===========================
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
index a2f3302..ecd5dfc 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
@@ -22,14 +22,27 @@
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
 import org.eclipse.jdt.internal.compiler.ast.JavadocArgumentExpression;
 import org.eclipse.jdt.internal.compiler.ast.JavadocFieldReference;
 import org.eclipse.jdt.internal.compiler.ast.JavadocMessageSend;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.StringLiteralConcatenation;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.env.IConstants;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
@@ -40,249 +53,71 @@
  */
 class ASTConverter {
 
-	private AST ast;
+	protected AST ast;
+	protected Comment[] commentsTable;
 	char[] compilationUnitSource;
-	Scanner scanner;
-	private boolean resolveBindings;
-	private Set pendingThisExpressionScopeResolution;
-	private Set pendingNameScopeResolution;	
-	private IProgressMonitor monitor;
+	protected DocCommentParser docParser;
 	// comments
-	private boolean insideComments;
-	private DocCommentParser docParser;
-	private Comment[] commentsTable;
+	protected boolean insideComments;
+	protected IProgressMonitor monitor;
+	protected Set pendingNameScopeResolution;	
+	protected Set pendingThisExpressionScopeResolution;
+	protected boolean resolveBindings;
+	Scanner scanner;
 	private DefaultCommentMapper commentMapper;
 
 	public ASTConverter(Map options, boolean resolveBindings, IProgressMonitor monitor) {
 		this.resolveBindings = resolveBindings;
+		Object sourceModeSetting = options.get(JavaCore.COMPILER_SOURCE);
+		long sourceLevel = ClassFileConstants.JDK1_3;
+		if (JavaCore.VERSION_1_4.equals(sourceModeSetting)) {
+			sourceLevel = ClassFileConstants.JDK1_4;
+		} else if (JavaCore.VERSION_1_5.equals(sourceModeSetting)) {
+			sourceLevel = ClassFileConstants.JDK1_5;
+		}
+
 		this.scanner = new Scanner(
-					true /*comment*/,
-					false /*whitespace*/,
-					false /*nls*/,
-					JavaCore.VERSION_1_4.equals(options.get(JavaCore.COMPILER_SOURCE)) ? ClassFileConstants.JDK1_4 : ClassFileConstants.JDK1_3 /*sourceLevel*/, 
-					null /*taskTags*/,
-					null/*taskPriorities*/,
-					true/*taskCaseSensitive*/);
+			true /*comment*/,
+			false /*whitespace*/,
+			false /*nls*/,
+			sourceLevel /*sourceLevel*/,
+			null /*taskTags*/,
+			null/*taskPriorities*/,
+			true/*taskCaseSensitive*/);
 		this.monitor = monitor;
 		this.insideComments = JavaCore.ENABLED.equals(options.get(JavaCore.COMPILER_DOC_COMMENT_SUPPORT));
 	}
 	
-	public void setAST(AST ast) {
-		this.ast = ast;
-		this.docParser = new DocCommentParser(this.ast, this.scanner, this.insideComments);
-	}
-
-	/*
-	 * Internal use only
-	 * Used to convert class body declarations
-	 */
-	public TypeDeclaration convert(org.eclipse.jdt.internal.compiler.ast.ASTNode[] nodes) {
-		TypeDeclaration typeDecl = this.ast.newTypeDeclaration();
-		int nodesLength = nodes.length;
-		for (int i = 0; i < nodesLength; i++) {
-			org.eclipse.jdt.internal.compiler.ast.ASTNode node = nodes[i];
-			if (node instanceof org.eclipse.jdt.internal.compiler.ast.Initializer) {
-				org.eclipse.jdt.internal.compiler.ast.Initializer oldInitializer = (org.eclipse.jdt.internal.compiler.ast.Initializer) node;
-				Initializer initializer = this.ast.newInitializer();
-				initializer.setBody(convert(oldInitializer.block));
-				initializer.setModifiers(oldInitializer.modifiers);
-				initializer.setSourceRange(oldInitializer.declarationSourceStart, oldInitializer.sourceEnd - oldInitializer.declarationSourceStart + 1);
-//				setJavaDocComment(initializer);
-//				initializer.setJavadoc(convert(oldInitializer.javadoc));
-				convert(oldInitializer.javadoc, initializer);
-				typeDecl.bodyDeclarations().add(initializer);
-			} else if (node instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) {
-				org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) node;
-				if (i > 0
-					&& (nodes[i - 1] instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration)
-					&& ((org.eclipse.jdt.internal.compiler.ast.FieldDeclaration)nodes[i - 1]).declarationSourceStart == fieldDeclaration.declarationSourceStart) {
-					// we have a multiple field declaration
-					// We retrieve the existing fieldDeclaration to add the new VariableDeclarationFragment
-					FieldDeclaration currentFieldDeclaration = (FieldDeclaration) typeDecl.bodyDeclarations().get(typeDecl.bodyDeclarations().size() - 1);
-					currentFieldDeclaration.fragments().add(convertToVariableDeclarationFragment(fieldDeclaration));
-				} else {
-					// we can create a new FieldDeclaration
-					typeDecl.bodyDeclarations().add(convertToFieldDeclaration(fieldDeclaration));
+	protected void adjustSourcePositionsForParent(org.eclipse.jdt.internal.compiler.ast.Expression expression) {
+		int start = expression.sourceStart;
+		int end = expression.sourceEnd;
+		int leftParentCount = 1;
+		int rightParentCount = 0;
+		this.scanner.resetTo(start, end);
+		try {
+			int token = this.scanner.getNextToken();
+			expression.sourceStart = this.scanner.currentPosition;
+			boolean stop = false;
+			while (!stop && ((token  = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF)) {
+				switch(token) {
+					case TerminalTokens.TokenNameLPAREN:
+						leftParentCount++;
+						break;
+					case TerminalTokens.TokenNameRPAREN:
+						rightParentCount++;
+						if (rightParentCount == leftParentCount) {
+							// we found the matching parenthesis
+							stop = true;
+						}
 				}
-			} else if(node instanceof org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration) {
-				AbstractMethodDeclaration nextMethodDeclaration = (AbstractMethodDeclaration) node;
-				if (!nextMethodDeclaration.isDefaultConstructor() && !nextMethodDeclaration.isClinit()) {
-					typeDecl.bodyDeclarations().add(convert(nextMethodDeclaration));
-				}
-			} else if(node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
-				org.eclipse.jdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
-				typeDecl.bodyDeclarations().add(convert(nextMemberDeclaration));
 			}
+			expression.sourceEnd = this.scanner.startPosition - 1;
+		} catch(InvalidInputException e) {
+			// ignore
 		}
-		return typeDecl;
-	}
-	
-	public CompilationUnit convert(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration unit, char[] source) {
-		this.compilationUnitSource = source;
-		this.scanner.setSource(source);
-		this.scanner.lineEnds = unit.compilationResult().lineSeparatorPositions;
-		CompilationUnit compilationUnit = this.ast.newCompilationUnit();
-		// handle the package declaration immediately
-		// There is no node corresponding to the package declaration
-		if (this.resolveBindings) {
-			recordNodes(compilationUnit, unit);
-		}
-		if (unit.currentPackage != null) {
-			PackageDeclaration packageDeclaration = convertPackage(unit);
-			compilationUnit.setPackage(packageDeclaration);
-		}
-		org.eclipse.jdt.internal.compiler.ast.ImportReference[] imports = unit.imports;
-		if (imports != null) {
-			int importLength = imports.length;
-			for (int i = 0; i < importLength; i++) {
-				compilationUnit.imports().add(convertImport(imports[i]));
-			}
-		}
-
-		// Parse comments
-		int[][] comments = unit.comments;
-		if (comments != null) {
-			buildCommentsTable(compilationUnit, comments);
-		}
-
-		org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = unit.types;
-		if (types != null) {
-			int typesLength = types.length;
-			for (int i = 0; i < typesLength; i++) {
-				compilationUnit.types().add(convert(types[i]));
-			}
-		}
-		compilationUnit.setSourceRange(unit.sourceStart, unit.sourceEnd - unit.sourceStart  + 1);
-		
-		int problemLength = unit.compilationResult.problemCount;
-		if (problemLength != 0) {
-			IProblem[] resizedProblems = null;
-			final IProblem[] problems = unit.compilationResult.problems;
-			if (problems.length == problemLength) {
-				resizedProblems = problems;
-			} else {
-				System.arraycopy(problems, 0, (resizedProblems = new IProblem[problemLength]), 0, problemLength);
-			}
-			propagateErrors(compilationUnit, resizedProblems);
-			compilationUnit.setProblems(resizedProblems);
-		}
-		if (this.resolveBindings) {
-			lookupForScopes();
-		}
-		compilationUnit.initCommentMapper(this.scanner);
-		return compilationUnit;
-	}
-	
-	/**
-	 * @param compilationUnit
-	 * @param comments
-	 */
-	void buildCommentsTable(CompilationUnit compilationUnit, int[][] comments) {
-		// Build comment table
-		this.commentsTable = new Comment[comments.length];
-		int nbr = 0;
-		for (int i = 0; i < comments.length; i++) {
-			Comment comment = createComment(comments[i]);
-			if (comment != null) {
-				comment.setAlternateRoot(compilationUnit);
-				this.commentsTable[nbr++] = comment;
-			}
-		}
-		// Resize table if  necessary
-		if (nbr<comments.length) {
-			Comment[] newCommentsTable = new Comment[nbr];
-			System.arraycopy(this.commentsTable, 0, newCommentsTable, 0, nbr);
-			this.commentsTable = newCommentsTable;
-		}
-		compilationUnit.setCommentTable(this.commentsTable);
 	}
 
-	public PackageDeclaration convertPackage(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration compilationUnitDeclaration) {
-		org.eclipse.jdt.internal.compiler.ast.ImportReference importReference = compilationUnitDeclaration.currentPackage;
-		PackageDeclaration packageDeclaration = this.ast.newPackageDeclaration();
-		char[][] tokens = importReference.tokens;
-		int length = importReference.tokens.length;
-		long[] positions = importReference.sourcePositions;
-		int start = (int)(positions[0]>>>32);
-		int end = (int)(positions[length - 1] & 0xFFFFFFFF);
-		Name name = null;
-		if (length > 1) {
-			name = setQualifiedNameNameAndSourceRanges(tokens, positions, importReference);
-		} else {
-			name = this.ast.newSimpleName(new String(tokens[0]));
-			name.setSourceRange(start, end - start + 1);
-		}
-		packageDeclaration.setSourceRange(importReference.declarationSourceStart, importReference.declarationEnd - importReference.declarationSourceStart + 1);
-		packageDeclaration.setName(name);
-		if (this.resolveBindings) {
-			recordNodes(packageDeclaration, importReference);
-			recordNodes(name, compilationUnitDeclaration);
-		}
-		return packageDeclaration;
-	}
-	
-	public ImportDeclaration convertImport(org.eclipse.jdt.internal.compiler.ast.ImportReference importReference) {
-		ImportDeclaration importDeclaration = this.ast.newImportDeclaration();
-		boolean onDemand = importReference.onDemand;
-		char[][] tokens = importReference.tokens;
-		int length = importReference.tokens.length;
-		long[] positions = importReference.sourcePositions;
-		Name name = null;
-		if (length > 1) {
-			name = setQualifiedNameNameAndSourceRanges(tokens, positions, importReference);
-		} else {
-			name = this.ast.newSimpleName(new String(tokens[0]));
-			int start = (int)(positions[0]>>>32);
-			int end = (int)(positions[0] & 0xFFFFFFFF);
-			name.setSourceRange(start, end - start + 1);
-		}
-		importDeclaration.setSourceRange(importReference.declarationSourceStart, importReference.declarationEnd - importReference.declarationSourceStart + 1);
-		importDeclaration.setName(name);
-		importDeclaration.setOnDemand(onDemand);
-		if (this.resolveBindings) {
-			recordNodes(importDeclaration, importReference);
-		}
-		return importDeclaration;
-	}
-
-	public TypeDeclaration convert(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
-		checkCanceled();
-		TypeDeclaration typeDecl = this.ast.newTypeDeclaration();
-		int modifiers = typeDeclaration.modifiers;
-		modifiers &= ~IConstants.AccInterface; // remove AccInterface flags
-		modifiers &= CompilerModifiers.AccJustFlag;
-		typeDecl.setModifiers(modifiers);
-		typeDecl.setInterface(typeDeclaration.isInterface());
-		SimpleName typeName = this.ast.newSimpleName(new String(typeDeclaration.name));
-		typeName.setSourceRange(typeDeclaration.sourceStart, typeDeclaration.sourceEnd - typeDeclaration.sourceStart + 1);
-		typeDecl.setName(typeName);
-		typeDecl.setSourceRange(typeDeclaration.declarationSourceStart, typeDeclaration.bodyEnd - typeDeclaration.declarationSourceStart + 1);
-		
-		// need to set the superclass and super interfaces here since we cannot distinguish them at
-		// the type references level.
-		if (typeDeclaration.superclass != null) {
-			typeDecl.setSuperclass(convert(typeDeclaration.superclass));
-		}
-		
-		org.eclipse.jdt.internal.compiler.ast.TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
-		if (superInterfaces != null) {
-			for (int index = 0, length = superInterfaces.length; index < length; index++) {
-				typeDecl.superInterfaces().add(convert(superInterfaces[index]));
-			}
-		}
-		
-		buildBodyDeclarations(typeDeclaration, typeDecl);
-		// The javadoc comment is now got from list store in compilation unit declaration
-//		setJavaDocComment(typeDecl);
-		if (this.resolveBindings) {
-			recordNodes(typeDecl, typeDeclaration);
-			recordNodes(typeName, typeDeclaration);
-			typeDecl.resolveBinding();
-		}
-		return typeDecl;
-	}
-	
-	private void buildBodyDeclarations(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration, TypeDeclaration typeDecl) {
+	protected void buildBodyDeclarations(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration, AbstractTypeDeclaration typeDecl) {
 		// add body declaration in the lexical order
 		org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] members = typeDeclaration.memberTypes;
 		org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields = typeDeclaration.fields;
@@ -327,7 +162,11 @@
 			}
 			switch (nextDeclarationType) {
 				case 0 :
-					checkAndAddMultipleFieldDeclaration(fields, fieldsIndex, typeDecl.bodyDeclarations());
+					if (nextFieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+						typeDecl.bodyDeclarations().add(convert(nextFieldDeclaration));
+					} else {
+						checkAndAddMultipleFieldDeclaration(fields, fieldsIndex, typeDecl.bodyDeclarations());
+					}
 					fieldsIndex++;
 					break;
 				case 1 :
@@ -338,20 +177,185 @@
 					break;
 				case 2 :
 					membersIndex++;
-					typeDecl.bodyDeclarations().add(convert(nextMemberDeclaration));
+					ASTNode node = convert(nextMemberDeclaration);
+					if (node == null) {
+						typeDecl.setFlags(typeDecl.getFlags() | ASTNode.MALFORMED);
+					} else {
+						typeDecl.bodyDeclarations().add(node);
+					}
 			}
 		}
 		// Convert javadoc
-//		typeDecl.setJavadoc(convert(typeDeclaration.javadoc));
 		convert(typeDeclaration.javadoc, typeDecl);
 	}
 	
-	private void checkAndAddMultipleFieldDeclaration(org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields, int index, List bodyDeclarations) {
+	protected void buildBodyDeclarations(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enumDeclaration2, EnumDeclaration enumDeclaration) {
+		// add body declaration in the lexical order
+		org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] members = enumDeclaration2.memberTypes;
+		org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields = enumDeclaration2.fields;
+		org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration[] methods = enumDeclaration2.methods;
+		
+		int fieldsLength = fields == null? 0 : fields.length;
+		int methodsLength = methods == null? 0 : methods.length;
+		int membersLength = members == null ? 0 : members.length;
+		int fieldsIndex = 0;
+		int methodsIndex = 0;
+		int membersIndex = 0;
+		
+		while ((fieldsIndex < fieldsLength)
+			|| (membersIndex < membersLength)
+			|| (methodsIndex < methodsLength)) {
+			org.eclipse.jdt.internal.compiler.ast.FieldDeclaration nextFieldDeclaration = null;
+			org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration nextMethodDeclaration = null;
+			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = null;
+		
+			int position = Integer.MAX_VALUE;
+			int nextDeclarationType = -1;
+			if (fieldsIndex < fieldsLength) {
+				nextFieldDeclaration = fields[fieldsIndex];
+				if (nextFieldDeclaration.declarationSourceStart < position) {
+					position = nextFieldDeclaration.declarationSourceStart;
+					nextDeclarationType = 0; // FIELD
+				}
+			}
+			if (methodsIndex < methodsLength) {
+				nextMethodDeclaration = methods[methodsIndex];
+				if (nextMethodDeclaration.declarationSourceStart < position) {
+					position = nextMethodDeclaration.declarationSourceStart;
+					nextDeclarationType = 1; // METHOD
+				}
+			}
+			if (membersIndex < membersLength) {
+				nextMemberDeclaration = members[membersIndex];
+				if (nextMemberDeclaration.declarationSourceStart < position) {
+					position = nextMemberDeclaration.declarationSourceStart;
+					nextDeclarationType = 2; // MEMBER
+				}
+			}
+			switch (nextDeclarationType) {
+				case 0 :
+					if (nextFieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+						enumDeclaration.enumConstants().add(convert(nextFieldDeclaration));
+					} else {
+						checkAndAddMultipleFieldDeclaration(fields, fieldsIndex, enumDeclaration.bodyDeclarations());
+					}
+					fieldsIndex++;
+					break;
+				case 1 :
+					methodsIndex++;
+					if (!nextMethodDeclaration.isDefaultConstructor() && !nextMethodDeclaration.isClinit()) {
+						enumDeclaration.bodyDeclarations().add(convert(nextMethodDeclaration));
+					}
+					break;
+				case 2 :
+					membersIndex++;
+					enumDeclaration.bodyDeclarations().add(convert(nextMemberDeclaration));
+					break;
+			}
+		}
+		convert(enumDeclaration2.javadoc, enumDeclaration);
+	}
+	
+	protected void buildBodyDeclarations(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration expression, AnonymousClassDeclaration anonymousClassDeclaration) {
+		// add body declaration in the lexical order
+		org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] members = expression.memberTypes;
+		org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields = expression.fields;
+		org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration[] methods = expression.methods;
+		
+		int fieldsLength = fields == null? 0 : fields.length;
+		int methodsLength = methods == null? 0 : methods.length;
+		int membersLength = members == null ? 0 : members.length;
+		int fieldsIndex = 0;
+		int methodsIndex = 0;
+		int membersIndex = 0;
+		
+		while ((fieldsIndex < fieldsLength)
+			|| (membersIndex < membersLength)
+			|| (methodsIndex < methodsLength)) {
+			org.eclipse.jdt.internal.compiler.ast.FieldDeclaration nextFieldDeclaration = null;
+			org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration nextMethodDeclaration = null;
+			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = null;
+		
+			int position = Integer.MAX_VALUE;
+			int nextDeclarationType = -1;
+			if (fieldsIndex < fieldsLength) {
+				nextFieldDeclaration = fields[fieldsIndex];
+				if (nextFieldDeclaration.declarationSourceStart < position) {
+					position = nextFieldDeclaration.declarationSourceStart;
+					nextDeclarationType = 0; // FIELD
+				}
+			}
+			if (methodsIndex < methodsLength) {
+				nextMethodDeclaration = methods[methodsIndex];
+				if (nextMethodDeclaration.declarationSourceStart < position) {
+					position = nextMethodDeclaration.declarationSourceStart;
+					nextDeclarationType = 1; // METHOD
+				}
+			}
+			if (membersIndex < membersLength) {
+				nextMemberDeclaration = members[membersIndex];
+				if (nextMemberDeclaration.declarationSourceStart < position) {
+					position = nextMemberDeclaration.declarationSourceStart;
+					nextDeclarationType = 2; // MEMBER
+				}
+			}
+			switch (nextDeclarationType) {
+				case 0 :
+					if (nextFieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+						anonymousClassDeclaration.bodyDeclarations().add(convert(nextFieldDeclaration));
+					} else {
+						checkAndAddMultipleFieldDeclaration(fields, fieldsIndex, anonymousClassDeclaration.bodyDeclarations());
+					}
+					fieldsIndex++;
+					break;
+				case 1 :
+					methodsIndex++;
+					if (!nextMethodDeclaration.isDefaultConstructor() && !nextMethodDeclaration.isClinit()) {
+						anonymousClassDeclaration.bodyDeclarations().add(convert(nextMethodDeclaration));
+					}
+					break;
+				case 2 :
+					membersIndex++;
+					ASTNode node = convert(nextMemberDeclaration);
+					if (node == null) {
+						anonymousClassDeclaration.setFlags(anonymousClassDeclaration.getFlags() | ASTNode.MALFORMED);
+					} else {
+						anonymousClassDeclaration.bodyDeclarations().add(node);
+					}
+			}
+		}
+	}
+	
+	/**
+	 * @param compilationUnit
+	 * @param comments
+	 */
+	void buildCommentsTable(CompilationUnit compilationUnit, int[][] comments) {
+		// Build comment table
+		this.commentsTable = new Comment[comments.length];
+		int nbr = 0;
+		for (int i = 0; i < comments.length; i++) {
+			Comment comment = createComment(comments[i]);
+			if (comment != null) {
+				comment.setAlternateRoot(compilationUnit);
+				this.commentsTable[nbr++] = comment;
+			}
+		}
+		// Resize table if  necessary
+		if (nbr<comments.length) {
+			Comment[] newCommentsTable = new Comment[nbr];
+			System.arraycopy(this.commentsTable, 0, newCommentsTable, 0, nbr);
+			this.commentsTable = newCommentsTable;
+		}
+		compilationUnit.setCommentTable(this.commentsTable);
+	}
+	
+	protected void checkAndAddMultipleFieldDeclaration(org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields, int index, List bodyDeclarations) {
 		if (fields[index] instanceof org.eclipse.jdt.internal.compiler.ast.Initializer) {
 			org.eclipse.jdt.internal.compiler.ast.Initializer oldInitializer = (org.eclipse.jdt.internal.compiler.ast.Initializer) fields[index];
 			Initializer initializer = this.ast.newInitializer();
 			initializer.setBody(convert(oldInitializer.block));
-			initializer.setModifiers(oldInitializer.modifiers);
+			setModifiers(initializer, oldInitializer);
 			initializer.setSourceRange(oldInitializer.declarationSourceStart, oldInitializer.sourceEnd - oldInitializer.declarationSourceStart + 1);
 			// The javadoc comment is now got from list store in compilation unit declaration
 //			setJavaDocComment(initializer);
@@ -370,8 +374,8 @@
 			bodyDeclarations.add(convertToFieldDeclaration(fields[index]));
 		}
 	}
-	
-	private void checkAndAddMultipleLocalDeclaration(org.eclipse.jdt.internal.compiler.ast.Statement[] stmts, int index, List blockStatements) {
+
+	protected void checkAndAddMultipleLocalDeclaration(org.eclipse.jdt.internal.compiler.ast.Statement[] stmts, int index, List blockStatements) {
 		if (index > 0
 		    && stmts[index - 1] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
 		    	org.eclipse.jdt.internal.compiler.ast.LocalDeclaration local1 = (org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) stmts[index - 1];
@@ -391,207 +395,12 @@
 		}
 	}
 
-	private void checkCanceled() {
+	protected void checkCanceled() {
 		if (this.monitor != null && this.monitor.isCanceled())
 			throw new OperationCanceledException();
 	}
 
-	public Name convert(org.eclipse.jdt.internal.compiler.ast.TypeReference typeReference) {
-		char[][] typeName = typeReference.getTypeName();
-		int length = typeName.length;
-		Name name = null;
-		if (length > 1) {
-			// QualifiedName
-			org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference qualifiedTypeReference = (org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) typeReference;
-			long[] positions = qualifiedTypeReference.sourcePositions;			
-			name = setQualifiedNameNameAndSourceRanges(typeName, positions, typeReference);
-		} else {
-			name = this.ast.newSimpleName(new String(typeName[0]));
-			name.setSourceRange(typeReference.sourceStart, typeReference.sourceEnd - typeReference.sourceStart + 1);
-		}
-		if (this.resolveBindings) {
-			recordNodes(name, typeReference);
-		}
-		return name;
-	}
-	
-	public SimpleName convert(org.eclipse.jdt.internal.compiler.ast.SingleNameReference nameReference) {
-		SimpleName name = this.ast.newSimpleName(new String(nameReference.token));		
-		if (this.resolveBindings) {
-			recordNodes(name, nameReference);
-		}
-		name.setSourceRange(nameReference.sourceStart, nameReference.sourceEnd - nameReference.sourceStart + 1);
-		return name;
-	}
-
-	public Name convert(org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference nameReference) {
-		return setQualifiedNameNameAndSourceRanges(nameReference.tokens, nameReference.sourcePositions, nameReference);
-	}
-
-	private QualifiedName setQualifiedNameNameAndSourceRanges(char[][] typeName, long[] positions, org.eclipse.jdt.internal.compiler.ast.ASTNode node) {
-		int length = typeName.length;
-		SimpleName firstToken = this.ast.newSimpleName(new String(typeName[0]));
-		firstToken.index = length - 1;
-		int start0 = (int)(positions[0]>>>32);
-		int start = start0;
-		int end = (int)(positions[0] & 0xFFFFFFFF);
-		firstToken.setSourceRange(start, end - start + 1);
-		SimpleName secondToken = this.ast.newSimpleName(new String(typeName[1]));
-		secondToken.index = length - 2;
-		start = (int)(positions[1]>>>32);
-		end = (int)(positions[1] & 0xFFFFFFFF);
-		secondToken.setSourceRange(start, end - start + 1);
-		QualifiedName qualifiedName = this.ast.newQualifiedName(firstToken, secondToken);
-		if (this.resolveBindings) {
-			recordNodes(qualifiedName, node);
-			recordPendingNameScopeResolution(qualifiedName);
-			recordNodes(firstToken, node);
-			recordNodes(secondToken, node);
-			recordPendingNameScopeResolution(firstToken);
-			recordPendingNameScopeResolution(secondToken);
-		}
-		qualifiedName.index = length - 2;
-		qualifiedName.setSourceRange(start0, end - start0 + 1);
-		SimpleName newPart = null;
-		for (int i = 2; i < length; i++) {
-			newPart = this.ast.newSimpleName(new String(typeName[i]));
-			newPart.index = length - i - 1;
-			start = (int)(positions[i]>>>32);
-			end = (int)(positions[i] & 0xFFFFFFFF);
-			newPart.setSourceRange(start,  end - start + 1);
-			qualifiedName = this.ast.newQualifiedName(qualifiedName, newPart);
-			qualifiedName.index = newPart.index;
-			qualifiedName.setSourceRange(start0, end - start0 + 1);
-			if (this.resolveBindings) {
-				recordNodes(qualifiedName, node);
-				recordNodes(newPart, node);				
-				recordPendingNameScopeResolution(qualifiedName);
-				recordPendingNameScopeResolution(newPart);
-			}
-		}
-		QualifiedName name = qualifiedName;
-		if (this.resolveBindings) {
-			recordNodes(name, node);
-			recordPendingNameScopeResolution(name);
-		}
-		return name;
-	}
-	
-	public Expression convert(org.eclipse.jdt.internal.compiler.ast.ThisReference reference) {
-		if (reference.isImplicitThis()) {
-			// There is no source associated with an implicit this
-			return null;
-		} else if (reference instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) reference);
-		} else if (reference instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference) reference);
-		}  else {
-			ThisExpression thisExpression = this.ast.newThisExpression();
-			thisExpression.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
-			if (this.resolveBindings) {
-				recordNodes(thisExpression, reference);
-				recordPendingThisExpressionScopeResolution(thisExpression);
-			}
-			return thisExpression;
-		}
-	}
-
-	public ThisExpression convert(org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference reference) {
-		ThisExpression thisExpression = this.ast.newThisExpression();
-		thisExpression.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
-		thisExpression.setQualifier(convert(reference.qualification));
-		if (this.resolveBindings) {
-			recordNodes(thisExpression, reference);
-			recordPendingThisExpressionScopeResolution(thisExpression);
-		}
-		return thisExpression;
-	}
-
-	public Name convert(org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference reference) {
-		return convert(reference.qualification);
-	}
-
-	public ArrayAccess convert(org.eclipse.jdt.internal.compiler.ast.ArrayReference reference) {
-		ArrayAccess arrayAccess = this.ast.newArrayAccess();
-		if (this.resolveBindings) {
-			recordNodes(arrayAccess, reference);
-		}
-		arrayAccess.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
-		arrayAccess.setArray(convert(reference.receiver));
-		arrayAccess.setIndex(convert(reference.position));
-		return arrayAccess;
-	}
-	
-	public Expression convert(org.eclipse.jdt.internal.compiler.ast.FieldReference reference) {
-		if (reference.receiver.isSuper()) {
-			SuperFieldAccess superFieldAccess = this.ast.newSuperFieldAccess();
-			if (this.resolveBindings) {
-				recordNodes(superFieldAccess, reference);
-			}
-			if (reference.receiver instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) {
-				Name qualifier = convert((org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) reference.receiver);
-				superFieldAccess.setQualifier(qualifier);
-				if (this.resolveBindings) {
-					recordNodes(qualifier, reference.receiver);
-				}
-			}
-			SimpleName simpleName = this.ast.newSimpleName(new String(reference.token)); 
-			int sourceStart = (int)(reference.nameSourcePosition>>>32);
-			int length = (int)(reference.nameSourcePosition & 0xFFFFFFFF) - sourceStart + 1;
-			simpleName.setSourceRange(sourceStart, length);
-			superFieldAccess.setName(simpleName);
-			if (this.resolveBindings) {
-				recordNodes(simpleName, reference);
-			}
-			superFieldAccess.setSourceRange(reference.receiver.sourceStart, reference.sourceEnd - reference.receiver.sourceStart + 1);
-			return superFieldAccess;
-		} else {
-			FieldAccess fieldAccess = this.ast.newFieldAccess();
-			if (this.resolveBindings) {
-				recordNodes(fieldAccess, reference);
-			}
-			Expression receiver = convert(reference.receiver);
-			fieldAccess.setExpression(receiver);
-			SimpleName simpleName = this.ast.newSimpleName(new String(reference.token)); 
-			int sourceStart = (int)(reference.nameSourcePosition>>>32);
-			int length = (int)(reference.nameSourcePosition & 0xFFFFFFFF) - sourceStart + 1;
-			simpleName.setSourceRange(sourceStart, length);
-			fieldAccess.setName(simpleName);
-			if (this.resolveBindings) {
-				recordNodes(simpleName, reference);
-			}
-			fieldAccess.setSourceRange(receiver.getStartPosition(), reference.sourceEnd - receiver.getStartPosition() + 1);
-			return fieldAccess;
-		}
-	}
-	
-	public Expression convert(org.eclipse.jdt.internal.compiler.ast.Reference reference) {
-		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.NameReference) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.NameReference) reference);
-		}
-		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.ThisReference) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.ThisReference) reference);
-		}
-		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.ArrayReference) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.ArrayReference) reference);
-		}
-		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.FieldReference) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.FieldReference) reference);
-		}
-		throw new IllegalArgumentException("Not yet implemented: convert(" + reference.getClass() + ")");//$NON-NLS-1$//$NON-NLS-2$
-	}
-						
-	public Name convert(org.eclipse.jdt.internal.compiler.ast.NameReference reference) {
-		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference) reference);
-		}
-		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.SingleNameReference) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.SingleNameReference) reference);
-		}
-		throw new IllegalArgumentException("Not yet implemented: convert(" + reference.getClass() + ")");//$NON-NLS-1$//$NON-NLS-2$
-	}	
-
-	private void completeRecord(ArrayType arrayType, org.eclipse.jdt.internal.compiler.ast.ASTNode astNode) {
+	protected void completeRecord(ArrayType arrayType, org.eclipse.jdt.internal.compiler.ast.ASTNode astNode) {
 		ArrayType array = arrayType;
 		int dimensions = array.getDimensions();
 		for (int i = 0; i < dimensions; i++) {
@@ -602,100 +411,14 @@
 			}
 		}
 	}
-	
-	public Type convertType(org.eclipse.jdt.internal.compiler.ast.TypeReference typeReference) {
-		Type type = null;				
-		int sourceStart = -1;
-		int length = 0;
-		int dimensions = typeReference.dimensions();
-		if (typeReference instanceof org.eclipse.jdt.internal.compiler.ast.SingleTypeReference) {
-			// this is either an ArrayTypeReference or a SingleTypeReference
-			char[] name = ((org.eclipse.jdt.internal.compiler.ast.SingleTypeReference) typeReference).getTypeName()[0];
-			sourceStart = typeReference.sourceStart;
-			length = typeReference.sourceEnd - typeReference.sourceStart + 1;
-			if (dimensions != 0) {
-				// need to find out if this is an array type of primitive types or not
-				if (isPrimitiveType(name)) {
-					int end = retrieveEndOfElementTypeNamePosition(sourceStart, sourceStart + length);
-					if (end == -1) {
-						end = sourceStart + length - 1;
-					}					
-					PrimitiveType primitiveType = this.ast.newPrimitiveType(getPrimitiveTypeCode(name));
-					primitiveType.setSourceRange(sourceStart, end - sourceStart + 1);
-					type = this.ast.newArrayType(primitiveType, dimensions);
-					if (this.resolveBindings) {
-						// store keys for inner types
-						completeRecord((ArrayType) type, typeReference);
-					}
-					type.setSourceRange(sourceStart, length);
-				} else {
-					SimpleName simpleName = this.ast.newSimpleName(new String(name));
-					// we need to search for the starting position of the first brace in order to set the proper length
-					// PR http://dev.eclipse.org/bugs/show_bug.cgi?id=10759
-					int end = retrieveEndOfElementTypeNamePosition(sourceStart, sourceStart + length);
-					if (end == -1) {
-						end = sourceStart + length - 1;
-					}
-					simpleName.setSourceRange(sourceStart, end - sourceStart + 1);
-					SimpleType simpleType = this.ast.newSimpleType(simpleName);
-					simpleType.setSourceRange(sourceStart, end - sourceStart + 1);
-					type = this.ast.newArrayType(simpleType, dimensions);
-					type.setSourceRange(sourceStart, length);
-					if (this.resolveBindings) {
-						completeRecord((ArrayType) type, typeReference);
-						this.recordNodes(simpleName, typeReference);
-					}
-				}
-			} else {
-				if (isPrimitiveType(name)) {
-					type = this.ast.newPrimitiveType(getPrimitiveTypeCode(name));
-					type.setSourceRange(sourceStart, length);
-				} else {
-					SimpleName simpleName = this.ast.newSimpleName(new String(name));
-					simpleName.setSourceRange(sourceStart, length);
-					type = this.ast.newSimpleType(simpleName);
-					type.setSourceRange(sourceStart, length);
-					if (this.resolveBindings) {
-						this.recordNodes(simpleName, typeReference);
-					}
-				}
-			}
-		} else {
-			char[][] name = ((org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) typeReference).getTypeName();
-			int nameLength = name.length;
-			long[] positions = ((org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) typeReference).sourcePositions;
-			sourceStart = (int)(positions[0]>>>32);
-			length = (int)(positions[nameLength - 1] & 0xFFFFFFFF) - sourceStart + 1;
-			Name qualifiedName = this.setQualifiedNameNameAndSourceRanges(name, positions, typeReference);
-			if (dimensions != 0) {
-				// need to find out if this is an array type of primitive types or not
-				SimpleType simpleType = this.ast.newSimpleType(qualifiedName);
-				simpleType.setSourceRange(sourceStart, length);
-				type = this.ast.newArrayType(simpleType, dimensions);
-				if (this.resolveBindings) {
-					completeRecord((ArrayType) type, typeReference);
-				}				
-				int end = retrieveEndOfDimensionsPosition(sourceStart+length, this.compilationUnitSource.length);
-				if (end != -1) {
-					type.setSourceRange(sourceStart, end - sourceStart + 1);
-				} else {
-					type.setSourceRange(sourceStart, length);
-				}
-			} else {
-				type = this.ast.newSimpleType(qualifiedName);
-				type.setSourceRange(sourceStart, length);
-			}
-		}
-		if (this.resolveBindings) {
-			this.recordNodes(type, typeReference);
-		}
-		return type;
-	}
 		
-	public MethodDeclaration convert(org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration methodDeclaration) {
+	public ASTNode convert(org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration methodDeclaration) {
 		checkCanceled();
+		if (methodDeclaration instanceof org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration) methodDeclaration);
+		}
 		MethodDeclaration methodDecl = this.ast.newMethodDeclaration();
-		methodDecl.setModifiers(methodDeclaration.modifiers & org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers.AccJustFlag);
+		setModifiers(methodDecl, methodDeclaration);
 		boolean isConstructor = methodDeclaration.isConstructor();
 		methodDecl.setConstructor(isConstructor);
 		SimpleName methodName = this.ast.newSimpleName(new String(methodDeclaration.selector));
@@ -719,13 +442,19 @@
 		}
 		org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall explicitConstructorCall = null;
 		if (isConstructor) {
-			// set the return type to VOID
-			PrimitiveType returnType = this.ast.newPrimitiveType(PrimitiveType.VOID);
-			returnType.setSourceRange(methodDeclaration.sourceStart, 0);
-			methodDecl.setReturnType(returnType);
 			org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration constructorDeclaration = (org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration) methodDeclaration;
 			explicitConstructorCall = constructorDeclaration.constructorCall;
-		} else {
+			switch(this.ast.apiLevel) {
+				case AST.JLS2 :
+					// set the return type to VOID
+					PrimitiveType returnType = this.ast.newPrimitiveType(PrimitiveType.VOID);
+					returnType.setSourceRange(methodDeclaration.sourceStart, 0);
+					methodDecl.setReturnType(returnType);
+					break;
+				case AST.JLS3 :
+					methodDecl.setReturnType2(null);
+			}
+		} else if (methodDeclaration instanceof org.eclipse.jdt.internal.compiler.ast.MethodDeclaration) {
 			org.eclipse.jdt.internal.compiler.ast.MethodDeclaration method = (org.eclipse.jdt.internal.compiler.ast.MethodDeclaration) methodDeclaration;
 			org.eclipse.jdt.internal.compiler.ast.TypeReference typeReference = method.returnType;
 			if (typeReference != null) {
@@ -740,10 +469,10 @@
 		int declarationSourceStart = methodDeclaration.declarationSourceStart;
 		int declarationSourceEnd = methodDeclaration.bodyEnd;
 		methodDecl.setSourceRange(declarationSourceStart, declarationSourceEnd - declarationSourceStart + 1);
-		int closingPosition = retrieveRightBraceOrSemiColonPosition(methodDecl, methodDeclaration);
+		int closingPosition = retrieveRightBraceOrSemiColonPosition(methodDeclaration.bodyEnd + 1, methodDeclaration.declarationSourceEnd);
 		if (closingPosition != -1) {
 			int startPosition = methodDecl.getStartPosition();
-			methodDecl.setSourceRange(startPosition, closingPosition - startPosition);
+			methodDecl.setSourceRange(startPosition, closingPosition - startPosition + 1);
 
 			org.eclipse.jdt.internal.compiler.ast.Statement[] statements = methodDeclaration.statements;
 			
@@ -802,10 +531,21 @@
 				}
 			}			
 		}
+
+		org.eclipse.jdt.internal.compiler.ast.TypeParameter[] typeParameters = methodDeclaration.typeParameters();
+		if (typeParameters != null) {
+			switch(this.ast.apiLevel) {
+				case AST.JLS2 :
+					methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED);
+					break;
+				case AST.JLS3 :
+					for (int i = 0, max = typeParameters.length; i < max; i++) {
+						methodDecl.typeParameters().add(convert(typeParameters[i]));
+					}
+			}
+		}
 		
 		// The javadoc comment is now got from list store in compilation unit declaration
-//		setJavaDocComment(methodDecl);
-//		methodDecl.setJavadoc(convert(methodDeclaration.javadoc));
 		convert(methodDeclaration.javadoc, methodDecl);
 		if (this.resolveBindings) {
 			recordNodes(methodDecl, methodDeclaration);
@@ -814,136 +554,30 @@
 		}
 		return methodDecl;
 	}	
-
-	public Expression convert(org.eclipse.jdt.internal.compiler.ast.Expression expression) {
-		if ((expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) != 0) {
-			return convertToParenthesizedExpression(expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.CastExpression) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.CastExpression) expression);
-		}
-		// switch between all types of expression
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.AllocationExpression) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.AllocationExpression) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ArrayInitializer) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.ArrayInitializer) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.PrefixExpression) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.PrefixExpression) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.PostfixExpression) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.PostfixExpression) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.CompoundAssignment) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.CompoundAssignment) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.Assignment) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.Assignment) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.FalseLiteral) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.FalseLiteral) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.TrueLiteral) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.TrueLiteral) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.NullLiteral) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.NullLiteral) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.CharLiteral) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.CharLiteral) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.DoubleLiteral) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.DoubleLiteral) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.FloatLiteral) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.FloatLiteral) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.IntLiteralMinValue) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.IntLiteralMinValue) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.IntLiteral) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.IntLiteral) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.LongLiteralMinValue) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.LongLiteralMinValue) expression);
-		}				
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.LongLiteral) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.LongLiteral) expression);
-		}
-		if (expression instanceof StringLiteralConcatenation) {
-			return convert((StringLiteralConcatenation) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral) expression);
-		}	
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.StringLiteral) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.StringLiteral) expression);
-		}				
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression) expression);
-		}				
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression) expression);
-		}				
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.EqualExpression) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.EqualExpression) expression);
-		}				
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.BinaryExpression) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.BinaryExpression) expression);
-		}				
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression) expression);
-		}				
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.UnaryExpression) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.UnaryExpression) expression);
-		}				
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ConditionalExpression) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.ConditionalExpression) expression);
-		}				
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.MessageSend) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.MessageSend) expression);
-		}				
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.Reference) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.Reference) expression);
-		}
-		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.TypeReference) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.TypeReference) expression);
-		}				
-		throw new IllegalArgumentException("Not yet implemented: convert(" + expression.getClass() + ")");//$NON-NLS-1$//$NON-NLS-2$
-	}
-
-	public ParenthesizedExpression convertToParenthesizedExpression(org.eclipse.jdt.internal.compiler.ast.Expression expression) {
-		ParenthesizedExpression parenthesizedExpression = this.ast.newParenthesizedExpression();
-		if (this.resolveBindings) {
-			recordNodes(parenthesizedExpression, expression);
-		}
-		parenthesizedExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
-		adjustSourcePositionsForParent(expression);
-		trimWhiteSpacesAndComments(expression);
-		// decrement the number of parenthesis
-		int numberOfParenthesis = (expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedSHIFT;
-		expression.bits &= ~org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK;
-		expression.bits |= (numberOfParenthesis - 1) << org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedSHIFT;
-		parenthesizedExpression.setExpression(convert(expression));
-		return parenthesizedExpression;
-	}
 	
 	public ClassInstanceCreation convert(org.eclipse.jdt.internal.compiler.ast.AllocationExpression expression) {
 		ClassInstanceCreation classInstanceCreation = this.ast.newClassInstanceCreation();
 		if (this.resolveBindings) {
 			recordNodes(classInstanceCreation, expression);
 		}
-		classInstanceCreation.setName(convert(expression.type));
+		if (expression.typeArguments != null) {
+			switch(this.ast.apiLevel) {
+				case AST.JLS2 :
+					classInstanceCreation.setFlags(classInstanceCreation.getFlags() | ASTNode.MALFORMED);
+					break;
+				case AST.JLS3 :
+					for (int i = 0, max = expression.typeArguments.length; i < max; i++) {
+						classInstanceCreation.typeArguments().add(convertType(expression.typeArguments[i]));
+					}
+			}
+		}
+		switch(this.ast.apiLevel) {
+			case AST.JLS2 :
+				classInstanceCreation.setName(convert(expression.type));
+				break;
+			case AST.JLS3 :
+				classInstanceCreation.setType(convertType(expression.type));
+		}
 		classInstanceCreation.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
 		org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = expression.arguments;
 		if (arguments != null) {
@@ -955,66 +589,131 @@
 		removeTrailingCommentFromExpressionEndingWithAParen(classInstanceCreation);
 		return classInstanceCreation;
 	}
+
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression expression) {
+		InfixExpression infixExpression = this.ast.newInfixExpression();
+		if (this.resolveBindings) {
+			recordNodes(infixExpression, expression);
+		}
+		Expression leftExpression = convert(expression.left);
+		infixExpression.setLeftOperand(leftExpression);
+		infixExpression.setRightOperand(convert(expression.right));
+		infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_AND);
+		int startPosition = leftExpression.getStartPosition();
+		infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+		return infixExpression;
 	
-	private void buildBodyDeclarations(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration expression, AnonymousClassDeclaration anonymousClassDeclaration) {
-		// add body declaration in the lexical order
-		org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] members = expression.memberTypes;
-		org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields = expression.fields;
-		org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration[] methods = expression.methods;
+	}
+
+	public AnnotationTypeDeclaration convertToAnnotationDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+		checkCanceled();
+		AnnotationTypeDeclaration typeDecl = this.ast.newAnnotationTypeDeclaration();
+		setModifiers(typeDecl, typeDeclaration);
+		SimpleName typeName = this.ast.newSimpleName(new String(typeDeclaration.name));
+		typeName.setSourceRange(typeDeclaration.sourceStart, typeDeclaration.sourceEnd - typeDeclaration.sourceStart + 1);
+		typeDecl.setName(typeName);
+		typeDecl.setSourceRange(typeDeclaration.declarationSourceStart, typeDeclaration.bodyEnd - typeDeclaration.declarationSourceStart + 1);
 		
-		int fieldsLength = fields == null? 0 : fields.length;
-		int methodsLength = methods == null? 0 : methods.length;
-		int membersLength = members == null ? 0 : members.length;
-		int fieldsIndex = 0;
-		int methodsIndex = 0;
-		int membersIndex = 0;
+		buildBodyDeclarations(typeDeclaration, typeDecl);
+		// The javadoc comment is now got from list store in compilation unit declaration
+		if (this.resolveBindings) {
+			recordNodes(typeDecl, typeDeclaration);
+			recordNodes(typeName, typeDeclaration);
+			typeDecl.resolveBinding();
+		}
+		return typeDecl;
+	}
+	
+	public ASTNode convert(org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration annotationTypeMemberDeclaration) {
+		checkCanceled();
+		if (this.ast.apiLevel == AST.JLS2) {
+			return null;
+		}
+		AnnotationTypeMemberDeclaration annotationTypeMemberDeclaration2 = this.ast.newAnnotationTypeMemberDeclaration();
+		setModifiers(annotationTypeMemberDeclaration2, annotationTypeMemberDeclaration);
+		SimpleName methodName = this.ast.newSimpleName(new String(annotationTypeMemberDeclaration.selector));
+		int start = annotationTypeMemberDeclaration.sourceStart;
+		int end = retrieveIdentifierEndPosition(start, annotationTypeMemberDeclaration.sourceEnd);
+		methodName.setSourceRange(start, end - start + 1);
+		annotationTypeMemberDeclaration2.setName(methodName);
+		org.eclipse.jdt.internal.compiler.ast.TypeReference typeReference = annotationTypeMemberDeclaration.returnType;
+		if (typeReference != null) {
+			Type returnType = convertType(typeReference);
+			setTypeForMethodDeclaration(annotationTypeMemberDeclaration2, returnType, 0);
+		}
+		int declarationSourceStart = annotationTypeMemberDeclaration.declarationSourceStart;
+		int declarationSourceEnd = annotationTypeMemberDeclaration.bodyEnd;
+		annotationTypeMemberDeclaration2.setSourceRange(declarationSourceStart, declarationSourceEnd - declarationSourceStart + 1);
+		// The javadoc comment is now got from list store in compilation unit declaration
+		convert(annotationTypeMemberDeclaration.javadoc, annotationTypeMemberDeclaration2);
+		org.eclipse.jdt.internal.compiler.ast.Expression memberValue = annotationTypeMemberDeclaration.defaultValue;
+		if (memberValue != null) {
+			annotationTypeMemberDeclaration2.setDefault(convert(memberValue));
+		}
+		if (this.resolveBindings) {
+			recordNodes(annotationTypeMemberDeclaration2, annotationTypeMemberDeclaration);
+			recordNodes(methodName, annotationTypeMemberDeclaration);
+			annotationTypeMemberDeclaration2.resolveBinding();
+		}
+		return annotationTypeMemberDeclaration2;
+	}
+	
+	public SingleVariableDeclaration convert(org.eclipse.jdt.internal.compiler.ast.Argument argument) {
+		SingleVariableDeclaration variableDecl = this.ast.newSingleVariableDeclaration();
+		setModifiers(variableDecl, argument);
+		SimpleName name = this.ast.newSimpleName(new String(argument.name));
+		int start = argument.sourceStart;
+		int nameEnd = argument.sourceEnd;
+		name.setSourceRange(start, nameEnd - start + 1);
+		variableDecl.setName(name);
+		final int typeSourceEnd = argument.type.sourceEnd;
+		final int extraDimensions = retrieveExtraDimension(nameEnd + 1, typeSourceEnd);
+		variableDecl.setExtraDimensions(extraDimensions);
+		final boolean isVarArgs = argument.isVarArgs();
+		if (isVarArgs && extraDimensions == 0) {
+			// remove the ellipsis from the type source end
+			argument.type.sourceEnd = retrieveEllipsisStartPosition(argument.type.sourceStart, typeSourceEnd);
+		}
+		Type type = convertType(argument.type);
+		int typeEnd = type.getStartPosition() + type.getLength() - 1;
+		int rightEnd = Math.max(typeEnd, argument.declarationSourceEnd);
+		/*
+		 * There is extra work to do to set the proper type positions
+		 * See PR http://bugs.eclipse.org/bugs/show_bug.cgi?id=23284
+		 */
+		if (isVarArgs) {
+			setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions + 1);
+		} else {
+			setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions);
+		}
+		variableDecl.setSourceRange(argument.declarationSourceStart, rightEnd - argument.declarationSourceStart + 1);
 		
-		while ((fieldsIndex < fieldsLength)
-			|| (membersIndex < membersLength)
-			|| (methodsIndex < methodsLength)) {
-			org.eclipse.jdt.internal.compiler.ast.FieldDeclaration nextFieldDeclaration = null;
-			org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration nextMethodDeclaration = null;
-			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = null;
-		
-			int position = Integer.MAX_VALUE;
-			int nextDeclarationType = -1;
-			if (fieldsIndex < fieldsLength) {
-				nextFieldDeclaration = fields[fieldsIndex];
-				if (nextFieldDeclaration.declarationSourceStart < position) {
-					position = nextFieldDeclaration.declarationSourceStart;
-					nextDeclarationType = 0; // FIELD
-				}
-			}
-			if (methodsIndex < methodsLength) {
-				nextMethodDeclaration = methods[methodsIndex];
-				if (nextMethodDeclaration.declarationSourceStart < position) {
-					position = nextMethodDeclaration.declarationSourceStart;
-					nextDeclarationType = 1; // METHOD
-				}
-			}
-			if (membersIndex < membersLength) {
-				nextMemberDeclaration = members[membersIndex];
-				if (nextMemberDeclaration.declarationSourceStart < position) {
-					position = nextMemberDeclaration.declarationSourceStart;
-					nextDeclarationType = 2; // MEMBER
-				}
-			}
-			switch (nextDeclarationType) {
-				case 0 :
-					checkAndAddMultipleFieldDeclaration(fields, fieldsIndex, anonymousClassDeclaration.bodyDeclarations());
-					fieldsIndex++;
+		if (isVarArgs) {
+			switch(this.ast.apiLevel) {
+				case AST.JLS2 :
+					variableDecl.setFlags(variableDecl.getFlags() | ASTNode.MALFORMED);
 					break;
-				case 1 :
-					methodsIndex++;
-					if (!nextMethodDeclaration.isDefaultConstructor() && !nextMethodDeclaration.isClinit()) {
-						anonymousClassDeclaration.bodyDeclarations().add(convert(nextMethodDeclaration));
-					}
-					break;
-				case 2 :
-					membersIndex++;
-					anonymousClassDeclaration.bodyDeclarations().add(convert(nextMemberDeclaration));
+				case AST.JLS3 :
+					variableDecl.setVarargs(true);
 			}
 		}
+		if (this.resolveBindings) {
+			recordNodes(name, argument);
+			recordNodes(variableDecl, argument);
+			variableDecl.resolveBinding();
+		}
+		return variableDecl;
+	}
+
+	
+	public Annotation convert(org.eclipse.jdt.internal.compiler.ast.Annotation annotation) {
+		if (annotation instanceof org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation) annotation);
+		} else if (annotation instanceof org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation) annotation);
+		} else {
+			return convert((org.eclipse.jdt.internal.compiler.ast.NormalAnnotation) annotation);
+		}
 	}
 
 	public ArrayCreation convert(org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression expression) {
@@ -1067,33 +766,6 @@
 		return arrayCreation;
 	}
 
-	public SingleVariableDeclaration convert(org.eclipse.jdt.internal.compiler.ast.Argument argument) {
-		SingleVariableDeclaration variableDecl = this.ast.newSingleVariableDeclaration();
-		variableDecl.setModifiers(argument.modifiers);
-		SimpleName name = this.ast.newSimpleName(new String(argument.name));
-		int start = argument.sourceStart;
-		int nameEnd = argument.sourceEnd;
-		name.setSourceRange(start, nameEnd - start + 1);
-		variableDecl.setName(name);
-		final int extraDimensions = retrieveExtraDimension(nameEnd + 1, argument.type.sourceEnd);
-		variableDecl.setExtraDimensions(extraDimensions);
-		Type type = convertType(argument.type);
-		int typeEnd = type.getStartPosition() + type.getLength() - 1;
-		int rightEnd = Math.max(typeEnd, argument.declarationSourceEnd);
-		/*
-		 * There is extra work to do to set the proper type positions
-		 * See PR http://bugs.eclipse.org/bugs/show_bug.cgi?id=23284
-		 */
-		setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions);
-		variableDecl.setSourceRange(argument.declarationSourceStart, rightEnd - argument.declarationSourceStart + 1);
-		if (this.resolveBindings) {
-			recordNodes(name, argument);
-			recordNodes(variableDecl, argument);
-			variableDecl.resolveBinding();
-		}
-		return variableDecl;
-	}
-
 	public ArrayInitializer convert(org.eclipse.jdt.internal.compiler.ast.ArrayInitializer expression) {
 		ArrayInitializer arrayInitializer = this.ast.newArrayInitializer();
 		if (this.resolveBindings) {
@@ -1114,55 +786,30 @@
 		return arrayInitializer;
 	}
 
-	public Expression convert(org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression allocation) {
-		if (allocation.anonymousType != null) {
-			ClassInstanceCreation classInstanceCreation = this.ast.newClassInstanceCreation();
-			classInstanceCreation.setName(convert(allocation.type));
-			if (allocation.enclosingInstance != null) {
-				classInstanceCreation.setExpression(convert(allocation.enclosingInstance));
-			}
-			int declarationSourceStart = allocation.sourceStart;
-			classInstanceCreation.setSourceRange(declarationSourceStart, allocation.anonymousType.bodyEnd - declarationSourceStart + 1);
-			org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = allocation.arguments;
-			if (arguments != null) {
-				int length = arguments.length;
-				for (int i = 0; i < length; i++) {
-					classInstanceCreation.arguments().add(convert(arguments[i]));
-				}
-			}
-			AnonymousClassDeclaration anonymousClassDeclaration = this.ast.newAnonymousClassDeclaration();
-			int start = retrieveStartBlockPosition(allocation.anonymousType.sourceEnd, allocation.anonymousType.bodyEnd);
-			anonymousClassDeclaration.setSourceRange(start, allocation.anonymousType.bodyEnd - start + 1);
-			classInstanceCreation.setAnonymousClassDeclaration(anonymousClassDeclaration);
-			buildBodyDeclarations(allocation.anonymousType, anonymousClassDeclaration);
-			if (this.resolveBindings) {
-				recordNodes(classInstanceCreation, allocation.anonymousType);
-				recordNodes(anonymousClassDeclaration, allocation.anonymousType);
-				anonymousClassDeclaration.resolveBinding();
-			}
-			return classInstanceCreation;			
-		} else {
-			ClassInstanceCreation classInstanceCreation = this.ast.newClassInstanceCreation();
-			classInstanceCreation.setExpression(convert(allocation.enclosingInstance));
-			classInstanceCreation.setName(convert(allocation.type));
-			classInstanceCreation.setSourceRange(allocation.sourceStart, allocation.sourceEnd - allocation.sourceStart + 1);
-			org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = allocation.arguments;
-			if (arguments != null) {
-				int length = arguments.length;
-				for (int i = 0; i < length; i++) {
-					Expression argument = convert(arguments[i]);
-					if (this.resolveBindings) {
-						recordNodes(argument, arguments[i]);
-					}
-					classInstanceCreation.arguments().add(argument);
-				}
-			}
-			if (this.resolveBindings) {
-				recordNodes(classInstanceCreation, allocation);
-			}
-			removeTrailingCommentFromExpressionEndingWithAParen(classInstanceCreation);
-			return classInstanceCreation;
+	public ArrayAccess convert(org.eclipse.jdt.internal.compiler.ast.ArrayReference reference) {
+		ArrayAccess arrayAccess = this.ast.newArrayAccess();
+		if (this.resolveBindings) {
+			recordNodes(arrayAccess, reference);
 		}
+		arrayAccess.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
+		arrayAccess.setArray(convert(reference.receiver));
+		arrayAccess.setIndex(convert(reference.position));
+		return arrayAccess;
+	}
+
+	public AssertStatement convert(org.eclipse.jdt.internal.compiler.ast.AssertStatement statement) {
+		AssertStatement assertStatement = this.ast.newAssertStatement();
+		int end = statement.assertExpression.sourceEnd + 1;
+		assertStatement.setExpression(convert(statement.assertExpression));
+		org.eclipse.jdt.internal.compiler.ast.Expression exceptionArgument = statement.exceptionArgument;
+		if (exceptionArgument != null) {
+			assertStatement.setMessage(convert(exceptionArgument));
+			end = exceptionArgument.sourceEnd + 1;
+		}
+		int start = statement.sourceStart;
+		int sourceEnd = retrieveEndingSemiColonPosition(end, this.compilationUnitSource.length);
+		assertStatement.setSourceRange(start, sourceEnd - start + 1);
+		return assertStatement;
 	}
 	
 	public Assignment convert(org.eclipse.jdt.internal.compiler.ast.Assignment expression) {
@@ -1179,289 +826,54 @@
 		return assignment;
 	}
 
-	public Assignment convert(org.eclipse.jdt.internal.compiler.ast.CompoundAssignment expression) {
-		Assignment assignment = this.ast.newAssignment();
-		Expression lhs = convert(expression.lhs);
-		assignment.setLeftHandSide(lhs);
-		int start = lhs.getStartPosition();
-		assignment.setSourceRange(start, expression.sourceEnd - start + 1);
-		switch (expression.operator) {
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
-				assignment.setOperator(Assignment.Operator.PLUS_ASSIGN);
-				break;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
-				assignment.setOperator(Assignment.Operator.MINUS_ASSIGN);
-				break;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MULTIPLY :
-				assignment.setOperator(Assignment.Operator.TIMES_ASSIGN);
-				break;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.DIVIDE :
-				assignment.setOperator(Assignment.Operator.DIVIDE_ASSIGN);
-				break;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.AND :
-				assignment.setOperator(Assignment.Operator.BIT_AND_ASSIGN);
-				break;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.OR :
-				assignment.setOperator(Assignment.Operator.BIT_OR_ASSIGN);
-				break;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.XOR :
-				assignment.setOperator(Assignment.Operator.BIT_XOR_ASSIGN);
-				break;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.REMAINDER :
-				assignment.setOperator(Assignment.Operator.REMAINDER_ASSIGN);
-				break;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LEFT_SHIFT :
-				assignment.setOperator(Assignment.Operator.LEFT_SHIFT_ASSIGN);
-				break;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.RIGHT_SHIFT :
-				assignment.setOperator(Assignment.Operator.RIGHT_SHIFT_SIGNED_ASSIGN);
-				break;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.UNSIGNED_RIGHT_SHIFT :
-				assignment.setOperator(Assignment.Operator.RIGHT_SHIFT_UNSIGNED_ASSIGN);
-				break;
+	/*
+	 * Internal use only
+	 * Used to convert class body declarations
+	 */
+	public TypeDeclaration convert(org.eclipse.jdt.internal.compiler.ast.ASTNode[] nodes) {
+		TypeDeclaration typeDecl = this.ast.newTypeDeclaration();
+		int nodesLength = nodes.length;
+		for (int i = 0; i < nodesLength; i++) {
+			org.eclipse.jdt.internal.compiler.ast.ASTNode node = nodes[i];
+			if (node instanceof org.eclipse.jdt.internal.compiler.ast.Initializer) {
+				org.eclipse.jdt.internal.compiler.ast.Initializer oldInitializer = (org.eclipse.jdt.internal.compiler.ast.Initializer) node;
+				Initializer initializer = this.ast.newInitializer();
+				initializer.setBody(convert(oldInitializer.block));
+				setModifiers(initializer, oldInitializer);
+				initializer.setSourceRange(oldInitializer.declarationSourceStart, oldInitializer.sourceEnd - oldInitializer.declarationSourceStart + 1);
+//				setJavaDocComment(initializer);
+//				initializer.setJavadoc(convert(oldInitializer.javadoc));
+				convert(oldInitializer.javadoc, initializer);
+				typeDecl.bodyDeclarations().add(initializer);
+			} else if (node instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) {
+				org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) node;
+				if (i > 0
+					&& (nodes[i - 1] instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration)
+					&& ((org.eclipse.jdt.internal.compiler.ast.FieldDeclaration)nodes[i - 1]).declarationSourceStart == fieldDeclaration.declarationSourceStart) {
+					// we have a multiple field declaration
+					// We retrieve the existing fieldDeclaration to add the new VariableDeclarationFragment
+					FieldDeclaration currentFieldDeclaration = (FieldDeclaration) typeDecl.bodyDeclarations().get(typeDecl.bodyDeclarations().size() - 1);
+					currentFieldDeclaration.fragments().add(convertToVariableDeclarationFragment(fieldDeclaration));
+				} else {
+					// we can create a new FieldDeclaration
+					typeDecl.bodyDeclarations().add(convertToFieldDeclaration(fieldDeclaration));
+				}
+			} else if(node instanceof org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration) {
+				AbstractMethodDeclaration nextMethodDeclaration = (AbstractMethodDeclaration) node;
+				if (!nextMethodDeclaration.isDefaultConstructor() && !nextMethodDeclaration.isClinit()) {
+					typeDecl.bodyDeclarations().add(convert(nextMethodDeclaration));
+				}
+			} else if(node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+				org.eclipse.jdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
+				ASTNode nextMemberDeclarationNode = convert(nextMemberDeclaration);
+				if (nextMemberDeclarationNode == null) {
+					typeDecl.setFlags(typeDecl.getFlags() | ASTNode.MALFORMED);
+				} else {
+					typeDecl.bodyDeclarations().add(nextMemberDeclarationNode);
+				}
+			}
 		}
-		assignment.setRightHandSide(convert(expression.expression));
-		return assignment;
-	}
-
-	public PrefixExpression convert(org.eclipse.jdt.internal.compiler.ast.PrefixExpression expression) {
-		PrefixExpression prefixExpression = this.ast.newPrefixExpression();
-		if (this.resolveBindings) {
-			recordNodes(prefixExpression, expression);
-		}
-		prefixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
-		prefixExpression.setOperand(convert(expression.lhs));
-		switch (expression.operator) {
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
-				prefixExpression.setOperator(PrefixExpression.Operator.INCREMENT);
-				break;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
-				prefixExpression.setOperator(PrefixExpression.Operator.DECREMENT);
-				break;
-		}
-		return prefixExpression;
-	}
-
-	public PostfixExpression convert(org.eclipse.jdt.internal.compiler.ast.PostfixExpression expression) {
-		PostfixExpression postfixExpression = this.ast.newPostfixExpression();
-		if (this.resolveBindings) {
-			recordNodes(postfixExpression, expression);
-		}
-		postfixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
-		postfixExpression.setOperand(convert(expression.lhs));
-		switch (expression.operator) {
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
-				postfixExpression.setOperator(PostfixExpression.Operator.INCREMENT);
-				break;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
-				postfixExpression.setOperator(PostfixExpression.Operator.DECREMENT);
-				break;
-		}
-		return postfixExpression;
-	}
-
-	public CastExpression convert(org.eclipse.jdt.internal.compiler.ast.CastExpression expression) {
-		CastExpression castExpression = this.ast.newCastExpression();
-		castExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
-		org.eclipse.jdt.internal.compiler.ast.Expression type = expression.type;
-		trimWhiteSpacesAndComments(type);
-		if (type instanceof org.eclipse.jdt.internal.compiler.ast.TypeReference ) {
-			castExpression.setType(convertType((org.eclipse.jdt.internal.compiler.ast.TypeReference)type));
-		} else if (type instanceof org.eclipse.jdt.internal.compiler.ast.NameReference) {
-			castExpression.setType(convertToType((org.eclipse.jdt.internal.compiler.ast.NameReference)type));
-		}
-		castExpression.setExpression(convert(expression.expression));
-		if (this.resolveBindings) {
-			recordNodes(castExpression, expression);
-		}
-		return castExpression;
-	}
-		
-	public Type convertToType(org.eclipse.jdt.internal.compiler.ast.NameReference reference) {
-		Name name = convert(reference);
-		SimpleType type = this.ast.newSimpleType(name);
-		type.setSourceRange(name.getStartPosition(), name.getLength());
-		if (this.resolveBindings) {
-			this.recordNodes(type, reference);
-		}
-		return type;
-	}
-	public Expression convert(org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess expression) {
-		TypeLiteral typeLiteral = this.ast.newTypeLiteral();
-		if (this.resolveBindings) {
-			this.recordNodes(typeLiteral, expression);
-		}
-		typeLiteral.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
-		typeLiteral.setType(convertType(expression.type));
-		return typeLiteral;
-	}
-
-	public BooleanLiteral convert(org.eclipse.jdt.internal.compiler.ast.FalseLiteral expression) {
-		BooleanLiteral literal = this.ast.newBooleanLiteral(false);
-		if (this.resolveBindings) {
-			this.recordNodes(literal, expression);
-		}
-		literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
-		return literal;	
-	}
-		
-	public BooleanLiteral convert(org.eclipse.jdt.internal.compiler.ast.TrueLiteral expression) {
-		BooleanLiteral literal = this.ast.newBooleanLiteral(true);
-		if (this.resolveBindings) {
-			this.recordNodes(literal, expression);
-		}
-		literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
-		return literal;		
-	}
-
-	public InfixExpression convert(StringLiteralConcatenation expression) {
-		expression.computeConstant();
-		InfixExpression infixExpression = this.ast.newInfixExpression();
-		infixExpression.setOperator(InfixExpression.Operator.PLUS);
-		org.eclipse.jdt.internal.compiler.ast.StringLiteral[] stringLiterals = expression.literals;
-		infixExpression.setLeftOperand(convert(stringLiterals[0]));
-		infixExpression.setRightOperand(convert(stringLiterals[1]));
-		for (int i = 2; i < expression.counter; i++) {
-			infixExpression.extendedOperands().add(convert(stringLiterals[i]));
-		}
-		if (this.resolveBindings) {
-			this.recordNodes(infixExpression, expression);
-		}
-		infixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
-		return infixExpression;
-	}
-
-	public org.eclipse.jdt.core.dom.NullLiteral convert(org.eclipse.jdt.internal.compiler.ast.NullLiteral expression) {
-		org.eclipse.jdt.core.dom.NullLiteral literal = this.ast.newNullLiteral();
-		if (this.resolveBindings) {
-			this.recordNodes(literal, expression);
-		}
-		literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
-		return literal;		
-	}
-
-	public CharacterLiteral convert(org.eclipse.jdt.internal.compiler.ast.CharLiteral expression) {
-		int length = expression.sourceEnd - expression.sourceStart + 1;	
-		int sourceStart = expression.sourceStart;
-		char[] tokens = new char[length];
-		System.arraycopy(this.compilationUnitSource, sourceStart, tokens, 0, length);
-		CharacterLiteral literal = this.ast.newCharacterLiteral();
-		if (this.resolveBindings) {
-			this.recordNodes(literal, expression);
-		}
-		literal.setEscapedValue(new String(tokens));
-		literal.setSourceRange(sourceStart, length);
-		removeLeadingAndTrailingCommentsFromLiteral(literal);
-		return literal;
-	}
-
-	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.DoubleLiteral expression) {
-		int length = expression.sourceEnd - expression.sourceStart + 1;	
-		int sourceStart = expression.sourceStart;
-		char[] tokens = new char[length];
-		System.arraycopy(this.compilationUnitSource, sourceStart, tokens, 0, length);
-		NumberLiteral literal = this.ast.newNumberLiteral(new String(tokens));
-		if (this.resolveBindings) {
-			this.recordNodes(literal, expression);
-		}
-		literal.setSourceRange(sourceStart, length);
-		removeLeadingAndTrailingCommentsFromLiteral(literal);
-		return literal;
-	}
-
-	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.FloatLiteral expression) {
-		int length = expression.sourceEnd - expression.sourceStart + 1;	
-		int sourceStart = expression.sourceStart;
-		char[] tokens = new char[length];
-		System.arraycopy(this.compilationUnitSource, sourceStart, tokens, 0, length);
-		NumberLiteral literal = this.ast.newNumberLiteral(new String(tokens));
-		if (this.resolveBindings) {
-			this.recordNodes(literal, expression);
-		}
-		literal.setSourceRange(sourceStart, length);
-		removeLeadingAndTrailingCommentsFromLiteral(literal);
-		return literal;
-	}
-
-	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.IntLiteral expression) {
-		int length = expression.sourceEnd - expression.sourceStart + 1;	
-		int sourceStart = expression.sourceStart;
-		char[] tokens = new char[length];
-		System.arraycopy(this.compilationUnitSource, sourceStart, tokens, 0, length);
-		NumberLiteral literal = this.ast.newNumberLiteral(new String(tokens));
-		if (this.resolveBindings) {
-			this.recordNodes(literal, expression);
-		}
-		literal.setSourceRange(sourceStart, length);
-		removeLeadingAndTrailingCommentsFromLiteral(literal);
-		return literal;
-	}
-
-	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.IntLiteralMinValue expression) {
-		int length = expression.sourceEnd - expression.sourceStart + 1;	
-		int sourceStart = expression.sourceStart;
-		char[] tokens = new char[length];
-		System.arraycopy(this.compilationUnitSource, sourceStart, tokens, 0, length);
-		NumberLiteral literal = this.ast.newNumberLiteral(new String(tokens));
-		if (this.resolveBindings) {
-			this.recordNodes(literal, expression);
-		}
-		literal.setSourceRange(sourceStart, length);
-		removeLeadingAndTrailingCommentsFromLiteral(literal);
-		return literal;
-	}
-
-	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.LongLiteral expression) {
-		int length = expression.sourceEnd - expression.sourceStart + 1;	
-		int sourceStart = expression.sourceStart;
-		char[] tokens = new char[length];
-		System.arraycopy(this.compilationUnitSource, sourceStart, tokens, 0, length);
-		NumberLiteral literal = this.ast.newNumberLiteral(new String(tokens));
-		if (this.resolveBindings) {
-			this.recordNodes(literal, expression);
-		}
-		literal.setSourceRange(sourceStart, length);
-		removeLeadingAndTrailingCommentsFromLiteral(literal);
-		return literal;
-	}
-
-	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.LongLiteralMinValue expression) {
-		int length = expression.sourceEnd - expression.sourceStart + 1;	
-		int sourceStart = expression.sourceStart;
-		char[] tokens = new char[length];
-		System.arraycopy(this.compilationUnitSource, sourceStart, tokens, 0, length);
-		NumberLiteral literal = this.ast.newNumberLiteral(new String(tokens));
-		if (this.resolveBindings) {
-			this.recordNodes(literal, expression);
-		}
-		literal.setSourceRange(sourceStart, length);
-		removeLeadingAndTrailingCommentsFromLiteral(literal);
-		return literal;
-	}
-
-	public StringLiteral convert(org.eclipse.jdt.internal.compiler.ast.StringLiteral expression) {
-		int length = expression.sourceEnd - expression.sourceStart + 1;	
-		int sourceStart = expression.sourceStart;
-		char[] tokens = new char[length];
-		System.arraycopy(this.compilationUnitSource, sourceStart, tokens, 0, length);
-		StringLiteral literal = this.ast.newStringLiteral();
-		if (this.resolveBindings) {
-			this.recordNodes(literal, expression);
-		}
-		literal.setEscapedValue(new String(tokens));
-		literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
-		return literal;
-	}
-
-	public StringLiteral convert(org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral expression) {
-		expression.computeConstant();
-		StringLiteral literal = this.ast.newStringLiteral();
-		if (this.resolveBindings) {
-			this.recordNodes(literal, expression);
-		}
-		literal.setLiteralValue(expression.constant.stringValue());
-		literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
-		return literal;
+		return typeDecl;
 	}
 	
 	public Expression convert(org.eclipse.jdt.internal.compiler.ast.BinaryExpression expression) {
@@ -1593,7 +1005,7 @@
 		} else if (expression.left instanceof StringLiteralConcatenation
 				&& ((expression.left.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0)) {
 			StringLiteralConcatenation literal = (StringLiteralConcatenation) expression.left;
-			final org.eclipse.jdt.internal.compiler.ast.StringLiteral[] stringLiterals = literal.literals;
+			final org.eclipse.jdt.internal.compiler.ast.Expression[] stringLiterals = literal.literals;
 			infixExpression.setLeftOperand(convert(stringLiterals[0]));
 			infixExpression.setRightOperand(convert(stringLiterals[1]));
 			for (int i = 2; i < literal.counter; i++) {
@@ -1611,28 +1023,638 @@
 		infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
 		return infixExpression;
 	}
-			
-	public PrefixExpression convert(org.eclipse.jdt.internal.compiler.ast.UnaryExpression expression) {
-		PrefixExpression prefixExpression = this.ast.newPrefixExpression();
-		if (this.resolveBindings) {
-			this.recordNodes(prefixExpression, expression);
+
+	public Block convert(org.eclipse.jdt.internal.compiler.ast.Block statement) {
+		Block block = this.ast.newBlock();
+		if (statement.sourceEnd > 0) {
+			block.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
 		}
-		prefixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
-		prefixExpression.setOperand(convert(expression.expression));
-		switch ((expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT) {
+		org.eclipse.jdt.internal.compiler.ast.Statement[] statements = statement.statements;
+		if (statements != null) {
+			int statementsLength = statements.length;
+			for (int i = 0; i < statementsLength; i++) {
+				if (statements[i] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
+					checkAndAddMultipleLocalDeclaration(statements, i, block.statements());
+				} else {
+					block.statements().add(convert(statements[i]));
+				}				
+			}
+		}
+		return block;
+	}
+	
+	public BreakStatement convert(org.eclipse.jdt.internal.compiler.ast.BreakStatement statement)  {
+		BreakStatement breakStatement = this.ast.newBreakStatement();
+		breakStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+		if (statement.label != null) {
+			SimpleName name = this.ast.newSimpleName(new String(statement.label));
+			retrieveIdentifierAndSetPositions(statement.sourceStart, statement.sourceEnd, name);
+			breakStatement.setLabel(name);
+		}
+		retrieveSemiColonPosition(breakStatement);
+		return breakStatement;
+	}
+		
+		
+	public SwitchCase convert(org.eclipse.jdt.internal.compiler.ast.CaseStatement statement) {
+		SwitchCase switchCase = this.ast.newSwitchCase();
+		org.eclipse.jdt.internal.compiler.ast.Expression constantExpression = statement.constantExpression;
+		if (constantExpression == null) {
+			switchCase.setExpression(null);
+		} else {
+			switchCase.setExpression(convert(constantExpression));
+		}
+		switchCase.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+		retrieveColonPosition(switchCase);
+		return switchCase;
+	}
+
+	public CastExpression convert(org.eclipse.jdt.internal.compiler.ast.CastExpression expression) {
+		CastExpression castExpression = this.ast.newCastExpression();
+		castExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+		org.eclipse.jdt.internal.compiler.ast.Expression type = expression.type;
+		trimWhiteSpacesAndComments(type);
+		if (type instanceof org.eclipse.jdt.internal.compiler.ast.TypeReference ) {
+			castExpression.setType(convertType((org.eclipse.jdt.internal.compiler.ast.TypeReference)type));
+		} else if (type instanceof org.eclipse.jdt.internal.compiler.ast.NameReference) {
+			castExpression.setType(convertToType((org.eclipse.jdt.internal.compiler.ast.NameReference)type));
+		}
+		castExpression.setExpression(convert(expression.expression));
+		if (this.resolveBindings) {
+			recordNodes(castExpression, expression);
+		}
+		return castExpression;
+	}
+
+	public CharacterLiteral convert(org.eclipse.jdt.internal.compiler.ast.CharLiteral expression) {
+		int length = expression.sourceEnd - expression.sourceStart + 1;	
+		int sourceStart = expression.sourceStart;
+		char[] tokens = new char[length];
+		System.arraycopy(this.compilationUnitSource, sourceStart, tokens, 0, length);
+		CharacterLiteral literal = this.ast.newCharacterLiteral();
+		if (this.resolveBindings) {
+			this.recordNodes(literal, expression);
+		}
+		literal.setEscapedValue(new String(tokens));
+		literal.setSourceRange(sourceStart, length);
+		removeLeadingAndTrailingCommentsFromLiteral(literal);
+		return literal;
+	}
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess expression) {
+		TypeLiteral typeLiteral = this.ast.newTypeLiteral();
+		if (this.resolveBindings) {
+			this.recordNodes(typeLiteral, expression);
+		}
+		typeLiteral.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+		typeLiteral.setType(convertType(expression.type));
+		return typeLiteral;
+	}
+	
+	public CompilationUnit convert(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration unit, char[] source) {
+		this.compilationUnitSource = source;
+		this.scanner.setSource(unit.compilationResult);
+		CompilationUnit compilationUnit = this.ast.newCompilationUnit();
+		// handle the package declaration immediately
+		// There is no node corresponding to the package declaration
+		if (this.resolveBindings) {
+			recordNodes(compilationUnit, unit);
+		}
+		if (unit.currentPackage != null) {
+			PackageDeclaration packageDeclaration = convertPackage(unit);
+			compilationUnit.setPackage(packageDeclaration);
+		}
+		org.eclipse.jdt.internal.compiler.ast.ImportReference[] imports = unit.imports;
+		if (imports != null) {
+			int importLength = imports.length;
+			for (int i = 0; i < importLength; i++) {
+				compilationUnit.imports().add(convertImport(imports[i]));
+			}
+		}
+
+		// Parse comments
+		int[][] comments = unit.comments;
+		if (comments != null) {
+			buildCommentsTable(compilationUnit, comments);
+		}
+
+		org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = unit.types;
+		if (types != null) {
+			int typesLength = types.length;
+			for (int i = 0; i < typesLength; i++) {
+				ASTNode type = convert(types[i]);
+				if (type == null) {
+					compilationUnit.setFlags(compilationUnit.getFlags() | ASTNode.MALFORMED);
+				} else {
+					compilationUnit.types().add(type);
+				}
+			}
+		}
+		compilationUnit.setSourceRange(unit.sourceStart, unit.sourceEnd - unit.sourceStart  + 1);
+		
+		int problemLength = unit.compilationResult.problemCount;
+		if (problemLength != 0) {
+			IProblem[] resizedProblems = null;
+			final IProblem[] problems = unit.compilationResult.problems;
+			if (problems.length == problemLength) {
+				resizedProblems = problems;
+			} else {
+				System.arraycopy(problems, 0, (resizedProblems = new IProblem[problemLength]), 0, problemLength);
+			}
+			ASTSyntaxErrorPropagator syntaxErrorPropagator = new ASTSyntaxErrorPropagator(resizedProblems);
+			compilationUnit.accept(syntaxErrorPropagator);
+			compilationUnit.setProblems(resizedProblems);
+		}
+		if (this.resolveBindings) {
+			lookupForScopes();
+		}
+		compilationUnit.initCommentMapper(this.scanner);
+		return compilationUnit;
+	}
+
+	public Assignment convert(org.eclipse.jdt.internal.compiler.ast.CompoundAssignment expression) {
+		Assignment assignment = this.ast.newAssignment();
+		Expression lhs = convert(expression.lhs);
+		assignment.setLeftHandSide(lhs);
+		int start = lhs.getStartPosition();
+		assignment.setSourceRange(start, expression.sourceEnd - start + 1);
+		switch (expression.operator) {
 			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
-				prefixExpression.setOperator(PrefixExpression.Operator.PLUS);
+				assignment.setOperator(Assignment.Operator.PLUS_ASSIGN);
 				break;
 			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
-				prefixExpression.setOperator(PrefixExpression.Operator.MINUS);
+				assignment.setOperator(Assignment.Operator.MINUS_ASSIGN);
 				break;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.NOT :
-				prefixExpression.setOperator(PrefixExpression.Operator.NOT);
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MULTIPLY :
+				assignment.setOperator(Assignment.Operator.TIMES_ASSIGN);
 				break;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.TWIDDLE :
-				prefixExpression.setOperator(PrefixExpression.Operator.COMPLEMENT);
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.DIVIDE :
+				assignment.setOperator(Assignment.Operator.DIVIDE_ASSIGN);
+				break;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.AND :
+				assignment.setOperator(Assignment.Operator.BIT_AND_ASSIGN);
+				break;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.OR :
+				assignment.setOperator(Assignment.Operator.BIT_OR_ASSIGN);
+				break;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.XOR :
+				assignment.setOperator(Assignment.Operator.BIT_XOR_ASSIGN);
+				break;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.REMAINDER :
+				assignment.setOperator(Assignment.Operator.REMAINDER_ASSIGN);
+				break;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LEFT_SHIFT :
+				assignment.setOperator(Assignment.Operator.LEFT_SHIFT_ASSIGN);
+				break;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.RIGHT_SHIFT :
+				assignment.setOperator(Assignment.Operator.RIGHT_SHIFT_SIGNED_ASSIGN);
+				break;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.UNSIGNED_RIGHT_SHIFT :
+				assignment.setOperator(Assignment.Operator.RIGHT_SHIFT_UNSIGNED_ASSIGN);
+				break;
 		}
-		return prefixExpression;
+		assignment.setRightHandSide(convert(expression.expression));
+		return assignment;
+	}
+
+	public ConditionalExpression convert(org.eclipse.jdt.internal.compiler.ast.ConditionalExpression expression) {
+		ConditionalExpression conditionalExpression = this.ast.newConditionalExpression();
+		if (this.resolveBindings) {
+			recordNodes(conditionalExpression, expression);
+		}
+		conditionalExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+		conditionalExpression.setExpression(convert(expression.condition));
+		conditionalExpression.setThenExpression(convert(expression.valueIfTrue));
+		conditionalExpression.setElseExpression(convert(expression.valueIfFalse));
+		return conditionalExpression;
+	}
+
+	public ContinueStatement convert(org.eclipse.jdt.internal.compiler.ast.ContinueStatement statement)  {
+		ContinueStatement continueStatement = this.ast.newContinueStatement();
+		continueStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+		if (statement.label != null) {
+			SimpleName name = this.ast.newSimpleName(new String(statement.label));
+			retrieveIdentifierAndSetPositions(statement.sourceStart, statement.sourceEnd, name);
+			continueStatement.setLabel(name);
+		}
+		retrieveSemiColonPosition(continueStatement);
+		return continueStatement;
+	}
+	
+	public DoStatement convert(org.eclipse.jdt.internal.compiler.ast.DoStatement statement) {
+		DoStatement doStatement = this.ast.newDoStatement();
+		doStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+		doStatement.setExpression(convert(statement.condition));
+		doStatement.setBody(convert(statement.action));
+		retrieveSemiColonPosition(doStatement);
+		return doStatement;
+	}
+
+	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.DoubleLiteral expression) {
+		int length = expression.sourceEnd - expression.sourceStart + 1;	
+		int sourceStart = expression.sourceStart;
+		char[] tokens = new char[length];
+		System.arraycopy(this.compilationUnitSource, sourceStart, tokens, 0, length);
+		NumberLiteral literal = this.ast.newNumberLiteral(new String(tokens));
+		if (this.resolveBindings) {
+			this.recordNodes(literal, expression);
+		}
+		literal.setSourceRange(sourceStart, length);
+		removeLeadingAndTrailingCommentsFromLiteral(literal);
+		return literal;
+	}
+	
+	public EmptyStatement convert(org.eclipse.jdt.internal.compiler.ast.EmptyStatement statement) {
+		EmptyStatement emptyStatement = this.ast.newEmptyStatement();
+		emptyStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+		return emptyStatement;
+	}
+	
+	// field is an enum constant
+	public EnumConstantDeclaration convert(org.eclipse.jdt.internal.compiler.ast.FieldDeclaration enumConstant) {
+		checkCanceled();
+		EnumConstantDeclaration enumConstantDeclaration = this.ast.newEnumConstantDeclaration();
+		SimpleName typeName = this.ast.newSimpleName(new String(enumConstant.name));
+		typeName.setSourceRange(enumConstant.sourceStart, enumConstant.sourceEnd - enumConstant.sourceStart + 1);
+		enumConstantDeclaration.setName(typeName);
+		int declarationSourceStart = enumConstant.declarationSourceStart;
+		int declarationSourceEnd = enumConstant.declarationSourceEnd;
+		final org.eclipse.jdt.internal.compiler.ast.Expression initialization = enumConstant.initialization;
+		if (initialization != null) {
+			if (initialization instanceof QualifiedAllocationExpression) {
+				org.eclipse.jdt.internal.compiler.ast.TypeDeclaration anonymousType = ((QualifiedAllocationExpression) initialization).anonymousType;
+				if (anonymousType != null) {
+					AnonymousClassDeclaration anonymousClassDeclaration = this.ast.newAnonymousClassDeclaration();
+					int start = retrieveStartBlockPosition(anonymousType.sourceEnd, anonymousType.bodyEnd);
+					int end = retrieveRightBrace(anonymousType.bodyEnd, declarationSourceEnd);
+					anonymousClassDeclaration.setSourceRange(start, end - start + 1);
+					enumConstantDeclaration.setAnonymousClassDeclaration(anonymousClassDeclaration);
+					buildBodyDeclarations(anonymousType, anonymousClassDeclaration);
+					if (this.resolveBindings) {
+						recordNodes(anonymousClassDeclaration, anonymousType);
+						anonymousClassDeclaration.resolveBinding();
+					}
+					enumConstantDeclaration.setSourceRange(declarationSourceStart, end - declarationSourceStart + 1);
+				}
+			} else {
+				enumConstantDeclaration.setSourceRange(declarationSourceStart, declarationSourceEnd - declarationSourceStart + 1);
+			}
+			final org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = ((org.eclipse.jdt.internal.compiler.ast.AllocationExpression) initialization).arguments;
+			if (arguments != null) {
+				for (int i = 0, max = arguments.length; i < max; i++) {
+					enumConstantDeclaration.arguments().add(convert(arguments[i]));
+				}
+			}
+		} else {
+			enumConstantDeclaration.setSourceRange(declarationSourceStart, declarationSourceEnd - declarationSourceStart + 1);
+		}
+		if (this.resolveBindings) {
+			recordNodes(enumConstantDeclaration, enumConstant);
+			recordNodes(typeName, enumConstant);
+			enumConstantDeclaration.resolveVariable();
+		}
+		return enumConstantDeclaration;
+	}
+
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.EqualExpression expression) {
+		InfixExpression infixExpression = this.ast.newInfixExpression();
+		if (this.resolveBindings) {
+			recordNodes(infixExpression, expression);
+		}
+		Expression leftExpression = convert(expression.left);
+		infixExpression.setLeftOperand(leftExpression);
+		infixExpression.setRightOperand(convert(expression.right));
+		int startPosition = leftExpression.getStartPosition();
+		infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+		switch ((expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT) {
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL :
+				infixExpression.setOperator(InfixExpression.Operator.EQUALS);
+				break;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.NOT_EQUAL :
+				infixExpression.setOperator(InfixExpression.Operator.NOT_EQUALS);
+		}
+		return infixExpression;
+	
+	}
+	
+	public Statement convert(org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall statement) {
+		Statement newStatement;
+		int sourceStart = statement.sourceStart;
+		if (statement.isSuperAccess() || statement.isSuper()) {
+			SuperConstructorInvocation superConstructorInvocation = this.ast.newSuperConstructorInvocation();
+			if (statement.qualification != null) {
+				superConstructorInvocation.setExpression(convert(statement.qualification));
+			}
+			org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = statement.arguments;
+			if (arguments != null) {
+				int length = arguments.length;
+				for (int i = 0; i < length; i++) {
+					superConstructorInvocation.arguments().add(convert(arguments[i]));
+				}
+			}
+			if (statement.typeArguments != null) {
+				sourceStart = statement.typeArgumentsSourceStart;
+				switch(this.ast.apiLevel) {
+					case AST.JLS2 :
+						superConstructorInvocation.setFlags(superConstructorInvocation.getFlags() | ASTNode.MALFORMED);
+						break;
+					case AST.JLS3 :
+						for (int i = 0, max = statement.typeArguments.length; i < max; i++) {
+							superConstructorInvocation.typeArguments().add(convertType(statement.typeArguments[i]));
+						}
+						break;
+				}
+			}
+			newStatement = superConstructorInvocation;
+		} else {
+			ConstructorInvocation constructorInvocation = this.ast.newConstructorInvocation();
+			org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = statement.arguments;
+			if (arguments != null) {
+				int length = arguments.length;
+				for (int i = 0; i < length; i++) {
+					constructorInvocation.arguments().add(convert(arguments[i]));
+				}
+			}
+			if (statement.typeArguments != null) {
+				sourceStart = statement.typeArgumentsSourceStart;
+				switch(this.ast.apiLevel) {
+					case AST.JLS2 :
+						constructorInvocation.setFlags(constructorInvocation.getFlags() | ASTNode.MALFORMED);
+						break;
+					case AST.JLS3 :
+						for (int i = 0, max = statement.typeArguments.length; i < max; i++) {
+							constructorInvocation.typeArguments().add(convertType(statement.typeArguments[i]));
+						}
+					break;
+				}
+			}
+			newStatement = constructorInvocation;
+		}
+		newStatement.setSourceRange(sourceStart, statement.sourceEnd - sourceStart + 1);
+		retrieveSemiColonPosition(newStatement);
+		if (this.resolveBindings) {
+			recordNodes(newStatement, statement);
+		}
+		return newStatement;
+	}
+
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.Expression expression) {
+		if ((expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) != 0) {
+			return convertToParenthesizedExpression(expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.Annotation) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.Annotation) expression);
+		}		
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.CastExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.CastExpression) expression);
+		}
+		// switch between all types of expression
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.AllocationExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.AllocationExpression) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ArrayInitializer) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.ArrayInitializer) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.PrefixExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.PrefixExpression) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.PostfixExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.PostfixExpression) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.CompoundAssignment) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.CompoundAssignment) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.Assignment) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.Assignment) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.FalseLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.FalseLiteral) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.TrueLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.TrueLiteral) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.NullLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.NullLiteral) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.CharLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.CharLiteral) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.DoubleLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.DoubleLiteral) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.FloatLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.FloatLiteral) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.IntLiteralMinValue) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.IntLiteralMinValue) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.IntLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.IntLiteral) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.LongLiteralMinValue) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.LongLiteralMinValue) expression);
+		}				
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.LongLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.LongLiteral) expression);
+		}
+		if (expression instanceof StringLiteralConcatenation) {
+			return convert((StringLiteralConcatenation) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral) expression);
+		}	
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.StringLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.StringLiteral) expression);
+		}				
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression) expression);
+		}				
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression) expression);
+		}				
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.EqualExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.EqualExpression) expression);
+		}				
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.BinaryExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.BinaryExpression) expression);
+		}				
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression) expression);
+		}				
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.UnaryExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.UnaryExpression) expression);
+		}				
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ConditionalExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.ConditionalExpression) expression);
+		}				
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.MessageSend) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.MessageSend) expression);
+		}				
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.Reference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.Reference) expression);
+		}
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.TypeReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.TypeReference) expression);
+		}
+		return null;
+	}
+
+	public StringLiteral convert(org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral expression) {
+		expression.computeConstant();
+		StringLiteral literal = this.ast.newStringLiteral();
+		if (this.resolveBindings) {
+			this.recordNodes(literal, expression);
+		}
+		literal.setLiteralValue(expression.constant.stringValue());
+		literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+		return literal;
+	}
+
+	public BooleanLiteral convert(org.eclipse.jdt.internal.compiler.ast.FalseLiteral expression) {
+		BooleanLiteral literal = this.ast.newBooleanLiteral(false);
+		if (this.resolveBindings) {
+			this.recordNodes(literal, expression);
+		}
+		literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+		return literal;	
+	}
+	
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.FieldReference reference) {
+		if (reference.receiver.isSuper()) {
+			SuperFieldAccess superFieldAccess = this.ast.newSuperFieldAccess();
+			if (this.resolveBindings) {
+				recordNodes(superFieldAccess, reference);
+			}
+			if (reference.receiver instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) {
+				Name qualifier = convert((org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) reference.receiver);
+				superFieldAccess.setQualifier(qualifier);
+				if (this.resolveBindings) {
+					recordNodes(qualifier, reference.receiver);
+				}
+			}
+			SimpleName simpleName = this.ast.newSimpleName(new String(reference.token)); 
+			int sourceStart = (int)(reference.nameSourcePosition>>>32);
+			int length = (int)(reference.nameSourcePosition & 0xFFFFFFFF) - sourceStart + 1;
+			simpleName.setSourceRange(sourceStart, length);
+			superFieldAccess.setName(simpleName);
+			if (this.resolveBindings) {
+				recordNodes(simpleName, reference);
+			}
+			superFieldAccess.setSourceRange(reference.receiver.sourceStart, reference.sourceEnd - reference.receiver.sourceStart + 1);
+			return superFieldAccess;
+		} else {
+			FieldAccess fieldAccess = this.ast.newFieldAccess();
+			if (this.resolveBindings) {
+				recordNodes(fieldAccess, reference);
+			}
+			Expression receiver = convert(reference.receiver);
+			fieldAccess.setExpression(receiver);
+			SimpleName simpleName = this.ast.newSimpleName(new String(reference.token)); 
+			int sourceStart = (int)(reference.nameSourcePosition>>>32);
+			int length = (int)(reference.nameSourcePosition & 0xFFFFFFFF) - sourceStart + 1;
+			simpleName.setSourceRange(sourceStart, length);
+			fieldAccess.setName(simpleName);
+			if (this.resolveBindings) {
+				recordNodes(simpleName, reference);
+			}
+			fieldAccess.setSourceRange(receiver.getStartPosition(), reference.sourceEnd - receiver.getStartPosition() + 1);
+			return fieldAccess;
+		}
+	}
+
+	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.FloatLiteral expression) {
+		int length = expression.sourceEnd - expression.sourceStart + 1;	
+		int sourceStart = expression.sourceStart;
+		char[] tokens = new char[length];
+		System.arraycopy(this.compilationUnitSource, sourceStart, tokens, 0, length);
+		NumberLiteral literal = this.ast.newNumberLiteral(new String(tokens));
+		if (this.resolveBindings) {
+			this.recordNodes(literal, expression);
+		}
+		literal.setSourceRange(sourceStart, length);
+		removeLeadingAndTrailingCommentsFromLiteral(literal);
+		return literal;
+	}
+	
+	public Statement convert(ForeachStatement statement) {
+		switch(this.ast.apiLevel) {
+			case AST.JLS2 :
+				return createFakeEmptyStatement(statement);
+			case AST.JLS3 :
+				EnhancedForStatement enhancedForStatement = this.ast.newEnhancedForStatement();
+				enhancedForStatement.setParameter(convertToSingleVariableDeclaration(statement.elementVariable));
+				enhancedForStatement.setExpression(convert(statement.collection));
+				enhancedForStatement.setBody(convert(statement.action));
+				int start = statement.sourceStart;
+				int end = statement.sourceEnd;
+				enhancedForStatement.setSourceRange(start, end - start + 1);
+				return enhancedForStatement;
+			default:
+				return createFakeEmptyStatement(statement);
+		}
+	}
+	
+	public ForStatement convert(org.eclipse.jdt.internal.compiler.ast.ForStatement statement) {
+		ForStatement forStatement = this.ast.newForStatement();
+		forStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+		org.eclipse.jdt.internal.compiler.ast.Statement[] initializations = statement.initializations;
+		if (initializations != null) {
+			// we know that we have at least one initialization
+			if (initializations[0] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
+				VariableDeclarationExpression variableDeclarationExpression = convertToVariableDeclarationExpression((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) initializations[0]);
+				int initializationsLength = initializations.length;
+				for (int i = 1; i < initializationsLength; i++) {
+					variableDeclarationExpression.fragments().add(convertToVariableDeclarationFragment((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)initializations[i]));
+				}
+				if (initializationsLength != 1) {
+					int start = variableDeclarationExpression.getStartPosition();
+					int end = ((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) initializations[initializationsLength - 1]).declarationSourceEnd;
+					variableDeclarationExpression.setSourceRange(start, end - start + 1);
+				}
+				forStatement.initializers().add(variableDeclarationExpression);
+			} else {
+				int initializationsLength = initializations.length;
+				for (int i = 0; i < initializationsLength; i++) {
+					Expression initializer = convertToExpression(initializations[i]);
+					if (initializer != null) {
+						forStatement.initializers().add(initializer);
+					} else {
+						forStatement.setFlags(forStatement.getFlags() | ASTNode.MALFORMED);
+					}
+				}
+			}
+		}
+		if (statement.condition != null) {
+			forStatement.setExpression(convert(statement.condition));
+		}
+		org.eclipse.jdt.internal.compiler.ast.Statement[] increments = statement.increments;
+		if (increments != null) {
+			int incrementsLength = increments.length;
+			for (int i = 0; i < incrementsLength; i++) {
+				forStatement.updaters().add(convertToExpression(increments[i]));				
+			}
+		}
+		forStatement.setBody(convert(statement.action));
+		return forStatement;
+	}
+	
+	public IfStatement convert(org.eclipse.jdt.internal.compiler.ast.IfStatement statement) {
+		IfStatement ifStatement = this.ast.newIfStatement();
+		ifStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+		ifStatement.setExpression(convert(statement.condition));
+		ifStatement.setThenStatement(convert(statement.thenStatement));
+		if (statement.elseStatement != null) {
+			ifStatement.setElseStatement(convert(statement.elseStatement));
+		}
+		return ifStatement;
 	}
 	
 	public InstanceofExpression convert(org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression expression) {
@@ -1648,16 +1670,94 @@
 		return instanceOfExpression;
 	}
 
-	public ConditionalExpression convert(org.eclipse.jdt.internal.compiler.ast.ConditionalExpression expression) {
-		ConditionalExpression conditionalExpression = this.ast.newConditionalExpression();
+	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.IntLiteral expression) {
+		int length = expression.sourceEnd - expression.sourceStart + 1;	
+		int sourceStart = expression.sourceStart;
+		char[] tokens = new char[length];
+		System.arraycopy(this.compilationUnitSource, sourceStart, tokens, 0, length);
+		NumberLiteral literal = this.ast.newNumberLiteral(new String(tokens));
 		if (this.resolveBindings) {
-			recordNodes(conditionalExpression, expression);
+			this.recordNodes(literal, expression);
 		}
-		conditionalExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
-		conditionalExpression.setExpression(convert(expression.condition));
-		conditionalExpression.setThenExpression(convert(expression.valueIfTrue));
-		conditionalExpression.setElseExpression(convert(expression.valueIfFalse));
-		return conditionalExpression;
+		literal.setSourceRange(sourceStart, length);
+		removeLeadingAndTrailingCommentsFromLiteral(literal);
+		return literal;
+	}
+
+	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.IntLiteralMinValue expression) {
+		int length = expression.sourceEnd - expression.sourceStart + 1;	
+		int sourceStart = expression.sourceStart;
+		char[] tokens = new char[length];
+		System.arraycopy(this.compilationUnitSource, sourceStart, tokens, 0, length);
+		NumberLiteral literal = this.ast.newNumberLiteral(new String(tokens));
+		if (this.resolveBindings) {
+			this.recordNodes(literal, expression);
+		}
+		literal.setSourceRange(sourceStart, length);
+		removeLeadingAndTrailingCommentsFromLiteral(literal);
+		return literal;
+	}
+
+	public void convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, BodyDeclaration bodyDeclaration) {
+		if (bodyDeclaration.getJavadoc() == null) {
+			if (javadoc != null) {
+				if (this.commentMapper == null || !this.commentMapper.hasSameTable(this.commentsTable)) {
+					this.commentMapper = new DefaultCommentMapper(this.commentsTable);
+				}
+				Comment comment = this.commentMapper.getComment(javadoc.sourceStart);
+				if (comment != null && comment.isDocComment() && comment.getParent() == null) {
+					Javadoc docComment = (Javadoc) comment;
+					if (this.resolveBindings) {
+						recordNodes(docComment, javadoc);
+						// resolve member and method references binding
+						Iterator tags = docComment.tags().listIterator();
+						while (tags.hasNext()) {
+							recordNodes(javadoc, (TagElement) tags.next());
+						}
+					}
+					bodyDeclaration.setJavadoc(docComment);
+				}
+			}
+		}
+	}
+	
+	public LabeledStatement convert(org.eclipse.jdt.internal.compiler.ast.LabeledStatement statement) {
+		LabeledStatement labeledStatement = this.ast.newLabeledStatement();
+		labeledStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);	
+		org.eclipse.jdt.internal.compiler.ast.Statement body = statement.statement;
+		labeledStatement.setBody(convert(body));
+		SimpleName name = this.ast.newSimpleName(new String(statement.label));
+		retrieveIdentifierAndSetPositions(statement.sourceStart, statement.sourceEnd, name);
+		labeledStatement.setLabel(name);
+		return labeledStatement;
+	}
+
+	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.LongLiteral expression) {
+		int length = expression.sourceEnd - expression.sourceStart + 1;	
+		int sourceStart = expression.sourceStart;
+		char[] tokens = new char[length];
+		System.arraycopy(this.compilationUnitSource, sourceStart, tokens, 0, length);
+		NumberLiteral literal = this.ast.newNumberLiteral(new String(tokens));
+		if (this.resolveBindings) {
+			this.recordNodes(literal, expression);
+		}
+		literal.setSourceRange(sourceStart, length);
+		removeLeadingAndTrailingCommentsFromLiteral(literal);
+		return literal;
+	}
+
+	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.LongLiteralMinValue expression) {
+		int length = expression.sourceEnd - expression.sourceStart + 1;	
+		int sourceStart = expression.sourceStart;
+		char[] tokens = new char[length];
+		System.arraycopy(this.compilationUnitSource, sourceStart, tokens, 0, length);
+		NumberLiteral literal = this.ast.newNumberLiteral(new String(tokens));
+		if (this.resolveBindings) {
+			this.recordNodes(literal, expression);
+		}
+		literal.setSourceRange(sourceStart, length);
+		removeLeadingAndTrailingCommentsFromLiteral(literal);
+		return literal;
 	}
 
 	public Expression convert(MessageSend expression) {
@@ -1701,6 +1801,19 @@
 					superMethodInvocation.arguments().add(expri);
 				}
 			}
+			final TypeReference[] typeArguments = expression.typeArguments;
+			if (typeArguments != null) {
+				switch(this.ast.apiLevel) {
+					case AST.JLS2 :
+						superMethodInvocation.setFlags(superMethodInvocation.getFlags() | ASTNode.MALFORMED);
+						break;
+					case AST.JLS3 :
+						for (int i = 0, max = typeArguments.length; i < max; i++) {
+							superMethodInvocation.typeArguments().add(convertType(typeArguments[i]));
+						}
+						break;
+				}
+			}
 			expr = superMethodInvocation;
 		} else {
 			// returns a MethodInvocation
@@ -1745,6 +1858,19 @@
 			if (qualifier != null) {
 				sourceStart = qualifier.getStartPosition();
 			}
+			final TypeReference[] typeArguments = expression.typeArguments;
+			if (typeArguments != null) {
+				switch(this.ast.apiLevel) {
+					case AST.JLS2 :
+						methodInvocation.setFlags(methodInvocation.getFlags() | ASTNode.MALFORMED);
+						break;
+					case AST.JLS3 :
+						for (int i = 0, max = typeArguments.length; i < max; i++) {
+							methodInvocation.typeArguments().add(convertType(typeArguments[i]));
+						}
+						break;
+				}
+			}
 			expr = methodInvocation;
 		}
 		expr.setSourceRange(sourceStart, expression.sourceEnd - sourceStart + 1);	
@@ -1752,40 +1878,85 @@
 		return expr;
 	}
 
-	public Expression convert(org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression expression) {
-		InfixExpression infixExpression = this.ast.newInfixExpression();
+	public MarkerAnnotation convert(org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation annotation) {
+		MarkerAnnotation markerAnnotation = this.ast.newMarkerAnnotation();
+		setTypeNameForAnnotation(annotation, markerAnnotation);
+		int start = annotation.sourceStart;
+		int end = annotation.declarationSourceEnd;
+		markerAnnotation.setSourceRange(start, end - start + 1);
 		if (this.resolveBindings) {
-			recordNodes(infixExpression, expression);
+			recordNodes(markerAnnotation, annotation);
 		}
-		Expression leftExpression = convert(expression.left);
-		infixExpression.setLeftOperand(leftExpression);
-		infixExpression.setRightOperand(convert(expression.right));
-		infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_AND);
-		int startPosition = leftExpression.getStartPosition();
-		infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+		return markerAnnotation;
+	}
+
+	public MemberValuePair convert(org.eclipse.jdt.internal.compiler.ast.MemberValuePair memberValuePair) {
+		MemberValuePair pair = this.ast.newMemberValuePair();
+		SimpleName simpleName = this.ast.newSimpleName(new String(memberValuePair.name));
+		int start = memberValuePair.sourceStart;
+		int end = memberValuePair.sourceEnd;
+		simpleName.setSourceRange(start, end - start + 1);
+		pair.setName(simpleName);
+		pair.setValue(convert(memberValuePair.value));
+		start = memberValuePair.sourceStart;
+		end = memberValuePair.value.sourceEnd;
+		pair.setSourceRange(start, end - start + 1);
+		if (this.resolveBindings) {
+			recordNodes(simpleName, memberValuePair);
+		}
+		return pair;
+	}
+
+	public Name convert(org.eclipse.jdt.internal.compiler.ast.NameReference reference) {
+		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference) reference);
+		} else {
+			return convert((org.eclipse.jdt.internal.compiler.ast.SingleNameReference) reference);
+		}
+	}
+
+	public InfixExpression convert(StringLiteralConcatenation expression) {
+		expression.computeConstant();
+		InfixExpression infixExpression = this.ast.newInfixExpression();
+		infixExpression.setOperator(InfixExpression.Operator.PLUS);
+		org.eclipse.jdt.internal.compiler.ast.Expression[] stringLiterals = expression.literals;
+		infixExpression.setLeftOperand(convert(stringLiterals[0]));
+		infixExpression.setRightOperand(convert(stringLiterals[1]));
+		for (int i = 2; i < expression.counter; i++) {
+			infixExpression.extendedOperands().add(convert(stringLiterals[i]));
+		}
+		if (this.resolveBindings) {
+			this.recordNodes(infixExpression, expression);
+		}
+		infixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
 		return infixExpression;
-	
 	}
 	
-	public Expression convert(org.eclipse.jdt.internal.compiler.ast.EqualExpression expression) {
-		InfixExpression infixExpression = this.ast.newInfixExpression();
+	public NormalAnnotation convert(org.eclipse.jdt.internal.compiler.ast.NormalAnnotation annotation) {
+		NormalAnnotation normalAnnotation = this.ast.newNormalAnnotation();
+		setTypeNameForAnnotation(annotation, normalAnnotation);
+		org.eclipse.jdt.internal.compiler.ast.MemberValuePair[] memberValuePairs = annotation.memberValuePairs;
+		if (memberValuePairs != null) {
+			for (int i = 0, max = memberValuePairs.length; i < max; i++) {
+				normalAnnotation.values().add(convert(memberValuePairs[i]));
+			}
+		}
+		int start = annotation.sourceStart;
+		int end = annotation.declarationSourceEnd;
+		normalAnnotation.setSourceRange(start, end - start + 1);
 		if (this.resolveBindings) {
-			recordNodes(infixExpression, expression);
+			recordNodes(normalAnnotation, annotation);
 		}
-		Expression leftExpression = convert(expression.left);
-		infixExpression.setLeftOperand(leftExpression);
-		infixExpression.setRightOperand(convert(expression.right));
-		int startPosition = leftExpression.getStartPosition();
-		infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
-		switch ((expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT) {
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL :
-				infixExpression.setOperator(InfixExpression.Operator.EQUALS);
-				break;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.NOT_EQUAL :
-				infixExpression.setOperator(InfixExpression.Operator.NOT_EQUALS);
+		return normalAnnotation;
+	}
+
+	public org.eclipse.jdt.core.dom.NullLiteral convert(org.eclipse.jdt.internal.compiler.ast.NullLiteral expression) {
+		org.eclipse.jdt.core.dom.NullLiteral literal = this.ast.newNullLiteral();
+		if (this.resolveBindings) {
+			this.recordNodes(literal, expression);
 		}
-		return infixExpression;
-	
+		literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+		return literal;		
 	}
 
 	public Expression convert(org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression expression) {
@@ -1802,7 +1973,172 @@
 		return infixExpression;
 	}
 
+	public PostfixExpression convert(org.eclipse.jdt.internal.compiler.ast.PostfixExpression expression) {
+		PostfixExpression postfixExpression = this.ast.newPostfixExpression();
+		if (this.resolveBindings) {
+			recordNodes(postfixExpression, expression);
+		}
+		postfixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+		postfixExpression.setOperand(convert(expression.lhs));
+		switch (expression.operator) {
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
+				postfixExpression.setOperator(PostfixExpression.Operator.INCREMENT);
+				break;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
+				postfixExpression.setOperator(PostfixExpression.Operator.DECREMENT);
+				break;
+		}
+		return postfixExpression;
+	}
+
+	public PrefixExpression convert(org.eclipse.jdt.internal.compiler.ast.PrefixExpression expression) {
+		PrefixExpression prefixExpression = this.ast.newPrefixExpression();
+		if (this.resolveBindings) {
+			recordNodes(prefixExpression, expression);
+		}
+		prefixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+		prefixExpression.setOperand(convert(expression.lhs));
+		switch (expression.operator) {
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
+				prefixExpression.setOperator(PrefixExpression.Operator.INCREMENT);
+				break;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
+				prefixExpression.setOperator(PrefixExpression.Operator.DECREMENT);
+				break;
+		}
+		return prefixExpression;
+	}
+
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression allocation) {
+		ClassInstanceCreation classInstanceCreation = this.ast.newClassInstanceCreation();
+		if (allocation.enclosingInstance != null) {
+			classInstanceCreation.setExpression(convert(allocation.enclosingInstance));
+		}
+		switch(this.ast.apiLevel) {
+			case AST.JLS2 :
+				classInstanceCreation.setName(convert(allocation.type));
+				break;
+			case AST.JLS3 :
+				classInstanceCreation.setType(convertType(allocation.type));
+		}
+		org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = allocation.arguments;
+		if (arguments != null) {
+			int length = arguments.length;
+			for (int i = 0; i < length; i++) {
+				Expression argument = convert(arguments[i]);
+				if (this.resolveBindings) {
+					recordNodes(argument, arguments[i]);
+				}
+				classInstanceCreation.arguments().add(argument);
+			}
+		}
+		if (allocation.typeArguments != null) {
+			switch(this.ast.apiLevel) {
+				case AST.JLS2 :
+					classInstanceCreation.setFlags(classInstanceCreation.getFlags() | ASTNode.MALFORMED);
+					break;
+				case AST.JLS3 :
+					for (int i = 0, max = allocation.typeArguments.length; i < max; i++) {
+						classInstanceCreation.typeArguments().add(convertType(allocation.typeArguments[i]));
+					}
+			}			
+		}
+		if (allocation.anonymousType != null) {
+			int declarationSourceStart = allocation.sourceStart;
+			classInstanceCreation.setSourceRange(declarationSourceStart, allocation.anonymousType.bodyEnd - declarationSourceStart + 1);
+			AnonymousClassDeclaration anonymousClassDeclaration = this.ast.newAnonymousClassDeclaration();
+			int start = retrieveStartBlockPosition(allocation.anonymousType.sourceEnd, allocation.anonymousType.bodyEnd);
+			anonymousClassDeclaration.setSourceRange(start, allocation.anonymousType.bodyEnd - start + 1);
+			classInstanceCreation.setAnonymousClassDeclaration(anonymousClassDeclaration);
+			buildBodyDeclarations(allocation.anonymousType, anonymousClassDeclaration);
+			if (this.resolveBindings) {
+				recordNodes(classInstanceCreation, allocation.anonymousType);
+				recordNodes(anonymousClassDeclaration, allocation.anonymousType);
+				anonymousClassDeclaration.resolveBinding();
+			}
+			return classInstanceCreation;			
+		} else {
+			final int start = allocation.sourceStart;
+			classInstanceCreation.setSourceRange(start, allocation.sourceEnd - start + 1);
+			if (this.resolveBindings) {
+				recordNodes(classInstanceCreation, allocation);
+			}
+			removeTrailingCommentFromExpressionEndingWithAParen(classInstanceCreation);
+			return classInstanceCreation;
+		}
+	}
+
+	public Name convert(org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference nameReference) {
+		return setQualifiedNameNameAndSourceRanges(nameReference.tokens, nameReference.sourcePositions, nameReference);
+	}
+
+	public Name convert(org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference reference) {
+		return convert(reference.qualification);
+	}
+
+	public ThisExpression convert(org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference reference) {
+		ThisExpression thisExpression = this.ast.newThisExpression();
+		thisExpression.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
+		thisExpression.setQualifier(convert(reference.qualification));
+		if (this.resolveBindings) {
+			recordNodes(thisExpression, reference);
+			recordPendingThisExpressionScopeResolution(thisExpression);
+		}
+		return thisExpression;
+	}
+	
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.Reference reference) {
+		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.NameReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.NameReference) reference);
+		}
+		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.ThisReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.ThisReference) reference);
+		}
+		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.ArrayReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.ArrayReference) reference);
+		}
+		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.FieldReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.FieldReference) reference);
+		}
+		return null; // cannot be reached
+	}
+	
+	public ReturnStatement convert(org.eclipse.jdt.internal.compiler.ast.ReturnStatement statement) {
+		ReturnStatement returnStatement = this.ast.newReturnStatement();
+		returnStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);	
+		if (statement.expression != null) {
+			returnStatement.setExpression(convert(statement.expression));
+		}
+		retrieveSemiColonPosition(returnStatement);
+		return returnStatement;
+	}
+	
+	public SingleMemberAnnotation convert(org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation annotation) {
+		SingleMemberAnnotation singleMemberAnnotation = this.ast.newSingleMemberAnnotation();
+		setTypeNameForAnnotation(annotation, singleMemberAnnotation);
+		singleMemberAnnotation.setValue(convert(annotation.memberValue));
+		int start = annotation.sourceStart;
+		int end = annotation.declarationSourceEnd;
+		singleMemberAnnotation.setSourceRange(start, end - start + 1);
+		if (this.resolveBindings) {
+			recordNodes(singleMemberAnnotation, annotation);
+		}
+		return singleMemberAnnotation;
+	}
+
+	public SimpleName convert(org.eclipse.jdt.internal.compiler.ast.SingleNameReference nameReference) {
+		SimpleName name = this.ast.newSimpleName(new String(nameReference.token));		
+		if (this.resolveBindings) {
+			recordNodes(name, nameReference);
+		}
+		name.setSourceRange(nameReference.sourceStart, nameReference.sourceEnd - nameReference.sourceStart + 1);
+		return name;
+	}
+
 	public Statement convert(org.eclipse.jdt.internal.compiler.ast.Statement statement) {
+		if (statement instanceof ForeachStatement) {
+			return convert((ForeachStatement) statement);
+		}
 		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
 			return convertToVariableDeclarationStatement((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)statement);
 		}
@@ -1854,18 +2190,50 @@
 		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.TryStatement) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.TryStatement) statement);
 		}
-		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration 
-				&& (statement.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.IsLocalTypeMASK) != 0) {
-			TypeDeclarationStatement typeDeclarationStatement = this.ast.newTypeDeclarationStatement(convert((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) statement));
-			TypeDeclaration typeDecl = typeDeclarationStatement.getTypeDeclaration();
-			typeDeclarationStatement.setSourceRange(typeDecl.getStartPosition(), typeDecl.getLength());
-			return typeDeclarationStatement;
-		}
 		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
-			TypeDeclarationStatement typeDeclarationStatement = this.ast.newTypeDeclarationStatement(convert((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) statement));
-			TypeDeclaration typeDecl = typeDeclarationStatement.getTypeDeclaration();
-			typeDeclarationStatement.setSourceRange(typeDecl.getStartPosition(), typeDecl.getLength());
-			return typeDeclarationStatement;
+			ASTNode result = convert((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) statement);
+			switch(result.getNodeType()) {
+				case ASTNode.ENUM_DECLARATION:
+					switch(this.ast.apiLevel) {
+						case AST.JLS2 :
+							return createFakeEmptyStatement(statement);
+						case AST.JLS3 :
+							TypeDeclarationStatement typeDeclarationStatement = this.ast.newTypeDeclarationStatement((EnumDeclaration) result);
+							TypeDeclaration typeDecl = typeDeclarationStatement.getTypeDeclaration();
+							typeDeclarationStatement.setSourceRange(typeDecl.getStartPosition(), typeDecl.getLength());
+							return typeDeclarationStatement;
+					}
+					break;
+				case ASTNode.ANNOTATION_TYPE_DECLARATION :
+					switch(this.ast.apiLevel) {
+						case AST.JLS2 :
+							return createFakeEmptyStatement(statement);
+						case AST.JLS3 :
+							TypeDeclarationStatement typeDeclarationStatement = this.ast.newTypeDeclarationStatement((AnnotationTypeDeclaration) result);
+							TypeDeclaration typeDecl = typeDeclarationStatement.getTypeDeclaration();
+							typeDeclarationStatement.setSourceRange(typeDecl.getStartPosition(), typeDecl.getLength());
+							return typeDeclarationStatement;
+					}
+					break;
+				default:
+					TypeDeclaration typeDeclaration = (TypeDeclaration) result;
+					if (typeDeclaration == null) {
+						return createFakeEmptyStatement(statement);
+					} else {
+						TypeDeclarationStatement typeDeclarationStatement = this.ast.newTypeDeclarationStatement(typeDeclaration);
+						switch(this.ast.apiLevel) {
+							case AST.JLS2 :
+								TypeDeclaration typeDecl = typeDeclarationStatement.getTypeDeclaration();
+								typeDeclarationStatement.setSourceRange(typeDecl.getStartPosition(), typeDecl.getLength());					
+								break;
+							case AST.JLS3 :
+								AbstractTypeDeclaration typeDeclAST3 = typeDeclarationStatement.getDeclaration();
+								typeDeclarationStatement.setSourceRange(typeDeclAST3.getStartPosition(), typeDeclAST3.getLength());					
+								break;
+						}
+						return typeDeclarationStatement;
+					}
+			}
 		}
 		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.WhileStatement) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.WhileStatement) statement);
@@ -1877,207 +2245,24 @@
 			retrieveSemiColonPosition(stmt);
 			return stmt;
 		}
-		throw new IllegalArgumentException("Not yet implemented: convert(" + statement.getClass() + ")");//$NON-NLS-1$//$NON-NLS-2$
+		return createFakeEmptyStatement(statement);
 	}
 
-	public AssertStatement convert(org.eclipse.jdt.internal.compiler.ast.AssertStatement statement) {
-		AssertStatement assertStatement = this.ast.newAssertStatement();
-		int end = statement.assertExpression.sourceEnd + 1;
-		assertStatement.setExpression(convert(statement.assertExpression));
-		org.eclipse.jdt.internal.compiler.ast.Expression exceptionArgument = statement.exceptionArgument;
-		if (exceptionArgument != null) {
-			assertStatement.setMessage(convert(exceptionArgument));
-			end = exceptionArgument.sourceEnd + 1;
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.StringLiteral expression) {
+		if (expression instanceof StringLiteralConcatenation) {
+			return convert((StringLiteralConcatenation) expression);
 		}
-		int start = statement.sourceStart;
-		int sourceEnd = retrieveEndingSemiColonPosition(end, this.compilationUnitSource.length);
-		assertStatement.setSourceRange(start, sourceEnd - start + 1);
-		return assertStatement;
-	}
-
-	public Block convert(org.eclipse.jdt.internal.compiler.ast.Block statement) {
-		Block block = this.ast.newBlock();
-		if (statement.sourceEnd > 0) {
-			block.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
-		}
-		org.eclipse.jdt.internal.compiler.ast.Statement[] statements = statement.statements;
-		if (statements != null) {
-			int statementsLength = statements.length;
-			for (int i = 0; i < statementsLength; i++) {
-				if (statements[i] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
-					checkAndAddMultipleLocalDeclaration(statements, i, block.statements());
-				} else {
-					block.statements().add(convert(statements[i]));
-				}				
-			}
-		}
-		return block;
-	}
-	
-	public BreakStatement convert(org.eclipse.jdt.internal.compiler.ast.BreakStatement statement)  {
-		BreakStatement breakStatement = this.ast.newBreakStatement();
-		breakStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
-		if (statement.label != null) {
-			SimpleName name = this.ast.newSimpleName(new String(statement.label));
-			retrieveIdentifierAndSetPositions(statement.sourceStart, statement.sourceEnd, name);
-			breakStatement.setLabel(name);
-		}
-		retrieveSemiColonPosition(breakStatement);
-		return breakStatement;
-	}
-
-	public ContinueStatement convert(org.eclipse.jdt.internal.compiler.ast.ContinueStatement statement)  {
-		ContinueStatement continueStatement = this.ast.newContinueStatement();
-		continueStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
-		if (statement.label != null) {
-			SimpleName name = this.ast.newSimpleName(new String(statement.label));
-			retrieveIdentifierAndSetPositions(statement.sourceStart, statement.sourceEnd, name);
-			continueStatement.setLabel(name);
-		}
-		retrieveSemiColonPosition(continueStatement);
-		return continueStatement;
-	}
-		
-		
-	public SwitchCase convert(org.eclipse.jdt.internal.compiler.ast.CaseStatement statement) {
-		SwitchCase switchCase = this.ast.newSwitchCase();
-		org.eclipse.jdt.internal.compiler.ast.Expression constantExpression = statement.constantExpression;
-		if (constantExpression == null) {
-			switchCase.setExpression(null);
-		} else {
-			switchCase.setExpression(convert(constantExpression));
-		}
-		switchCase.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
-		retrieveColonPosition(switchCase);
-		return switchCase;
-	}
-	
-	public DoStatement convert(org.eclipse.jdt.internal.compiler.ast.DoStatement statement) {
-		DoStatement doStatement = this.ast.newDoStatement();
-		doStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
-		doStatement.setExpression(convert(statement.condition));
-		doStatement.setBody(convert(statement.action));
-		retrieveSemiColonPosition(doStatement);
-		return doStatement;
-	}
-	
-	public EmptyStatement convert(org.eclipse.jdt.internal.compiler.ast.EmptyStatement statement) {
-		EmptyStatement emptyStatement = this.ast.newEmptyStatement();
-		emptyStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
-		return emptyStatement;
-	}
-	
-	public Statement convert(org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall statement) {
-		Statement newStatement;
-		if (statement.isSuperAccess() || statement.isSuper()) {
-			SuperConstructorInvocation superConstructorInvocation = this.ast.newSuperConstructorInvocation();
-			if (statement.qualification != null) {
-				superConstructorInvocation.setExpression(convert(statement.qualification));
-			}
-			org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = statement.arguments;
-			if (arguments != null) {
-				int length = arguments.length;
-				for (int i = 0; i < length; i++) {
-					superConstructorInvocation.arguments().add(convert(arguments[i]));
-				}
-			}
-			newStatement = superConstructorInvocation;
-		} else {
-			ConstructorInvocation constructorInvocation = this.ast.newConstructorInvocation();
-			org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = statement.arguments;
-			if (arguments != null) {
-				int length = arguments.length;
-				for (int i = 0; i < length; i++) {
-					constructorInvocation.arguments().add(convert(arguments[i]));
-				}
-			}
-			newStatement = constructorInvocation;
-		}
-		newStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
-		retrieveSemiColonPosition(newStatement);
+		int length = expression.sourceEnd - expression.sourceStart + 1;	
+		int sourceStart = expression.sourceStart;
+		char[] tokens = new char[length];
+		System.arraycopy(this.compilationUnitSource, sourceStart, tokens, 0, length);
+		StringLiteral literal = this.ast.newStringLiteral();
 		if (this.resolveBindings) {
-			recordNodes(newStatement, statement);
+			this.recordNodes(literal, expression);
 		}
-		return newStatement;
-	}
-	
-	public ForStatement convert(org.eclipse.jdt.internal.compiler.ast.ForStatement statement) {
-		ForStatement forStatement = this.ast.newForStatement();
-		forStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
-		org.eclipse.jdt.internal.compiler.ast.Statement[] initializations = statement.initializations;
-		if (initializations != null) {
-			// we know that we have at least one initialization
-			if (initializations[0] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
-				VariableDeclarationExpression variableDeclarationExpression = convertToVariableDeclarationExpression((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) initializations[0]);
-				int initializationsLength = initializations.length;
-				for (int i = 1; i < initializationsLength; i++) {
-					variableDeclarationExpression.fragments().add(convertToVariableDeclarationFragment((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)initializations[i]));
-				}
-				if (initializationsLength != 1) {
-					int start = variableDeclarationExpression.getStartPosition();
-					int end = ((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) initializations[initializationsLength - 1]).declarationSourceEnd;
-					variableDeclarationExpression.setSourceRange(start, end - start + 1);
-				}
-				forStatement.initializers().add(variableDeclarationExpression);
-			} else {
-				int initializationsLength = initializations.length;
-				for (int i = 0; i < initializationsLength; i++) {
-					forStatement.initializers().add(convertToExpression(initializations[i]));
-				}
-			}
-		}
-		if (statement.condition != null) {
-			forStatement.setExpression(convert(statement.condition));
-		}
-		org.eclipse.jdt.internal.compiler.ast.Statement[] increments = statement.increments;
-		if (increments != null) {
-			int incrementsLength = increments.length;
-			for (int i = 0; i < incrementsLength; i++) {
-				forStatement.updaters().add(convertToExpression(increments[i]));				
-			}
-		}
-		forStatement.setBody(convert(statement.action));
-		return forStatement;
-	}
-	
-	public Expression convertToExpression(org.eclipse.jdt.internal.compiler.ast.Statement statement) {
-		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.Expression) {
-			return convert((org.eclipse.jdt.internal.compiler.ast.Expression) statement);
-		}
-		// unsupported
-		throw new IllegalArgumentException("Not yet implemented: convert(" + statement.getClass() + ")");//$NON-NLS-1$//$NON-NLS-2$
-	}
-	
-	public IfStatement convert(org.eclipse.jdt.internal.compiler.ast.IfStatement statement) {
-		IfStatement ifStatement = this.ast.newIfStatement();
-		ifStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
-		ifStatement.setExpression(convert(statement.condition));
-		ifStatement.setThenStatement(convert(statement.thenStatement));
-		if (statement.elseStatement != null) {
-			ifStatement.setElseStatement(convert(statement.elseStatement));
-		}
-		return ifStatement;
-	}
-	
-	public LabeledStatement convert(org.eclipse.jdt.internal.compiler.ast.LabeledStatement statement) {
-		LabeledStatement labeledStatement = this.ast.newLabeledStatement();
-		labeledStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);	
-		org.eclipse.jdt.internal.compiler.ast.Statement body = statement.statement;
-		labeledStatement.setBody(convert(body));
-		SimpleName name = this.ast.newSimpleName(new String(statement.label));
-		retrieveIdentifierAndSetPositions(statement.sourceStart, statement.sourceEnd, name);
-		labeledStatement.setLabel(name);
-		return labeledStatement;
-	}
-	
-	public ReturnStatement convert(org.eclipse.jdt.internal.compiler.ast.ReturnStatement statement) {
-		ReturnStatement returnStatement = this.ast.newReturnStatement();
-		returnStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);	
-		if (statement.expression != null) {
-			returnStatement.setExpression(convert(statement.expression));
-		}
-		retrieveSemiColonPosition(returnStatement);
-		return returnStatement;
+		literal.setEscapedValue(new String(tokens));
+		literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+		return literal;
 	}
 	
 	public SwitchStatement convert(org.eclipse.jdt.internal.compiler.ast.SwitchStatement statement) {
@@ -2102,6 +2287,25 @@
 		return synchronizedStatement;
 	}
 	
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.ThisReference reference) {
+		if (reference.isImplicitThis()) {
+			// There is no source associated with an implicit this
+			return null;
+		} else if (reference instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) reference);
+		} else if (reference instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference) reference);
+		}  else {
+			ThisExpression thisExpression = this.ast.newThisExpression();
+			thisExpression.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
+			if (this.resolveBindings) {
+				recordNodes(thisExpression, reference);
+				recordPendingThisExpressionScopeResolution(thisExpression);
+			}
+			return thisExpression;
+		}
+	}
+	
 	public ThrowStatement convert(org.eclipse.jdt.internal.compiler.ast.ThrowStatement statement) {
 		ThrowStatement throwStatement = this.ast.newThrowStatement();
 		throwStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);	
@@ -2109,6 +2313,15 @@
 		retrieveSemiColonPosition(throwStatement);
 		return throwStatement;
 	}
+		
+	public BooleanLiteral convert(org.eclipse.jdt.internal.compiler.ast.TrueLiteral expression) {
+		BooleanLiteral literal = this.ast.newBooleanLiteral(true);
+		if (this.resolveBindings) {
+			this.recordNodes(literal, expression);
+		}
+		literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+		return literal;		
+	}
 	
 	public TryStatement convert(org.eclipse.jdt.internal.compiler.ast.TryStatement statement) {
 		TryStatement tryStatement = this.ast.newTryStatement();
@@ -2135,6 +2348,157 @@
 		}
 		return tryStatement;
 	}
+
+	public ASTNode convert(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+		switch (typeDeclaration.kind()) {
+			case IGenericType.ENUM_DECL :
+				if (this.ast.apiLevel == AST.JLS2) {
+					return null;
+				} else {
+					return convertToEnumDeclaration(typeDeclaration);
+				}
+			case IGenericType.ANNOTATION_TYPE_DECL :
+				if (this.ast.apiLevel == AST.JLS2) {
+					return null;
+				} else {
+					return convertToAnnotationDeclaration(typeDeclaration);
+				}
+		}
+
+		checkCanceled();
+		TypeDeclaration typeDecl = this.ast.newTypeDeclaration();
+		if (typeDeclaration.modifiersSourceStart != -1) {
+			setModifiers(typeDecl, typeDeclaration);
+		}
+		typeDecl.setInterface(typeDeclaration.kind() == IGenericType.INTERFACE_DECL);
+		SimpleName typeName = this.ast.newSimpleName(new String(typeDeclaration.name));
+		typeName.setSourceRange(typeDeclaration.sourceStart, typeDeclaration.sourceEnd - typeDeclaration.sourceStart + 1);
+		typeDecl.setName(typeName);
+		typeDecl.setSourceRange(typeDeclaration.declarationSourceStart, typeDeclaration.bodyEnd - typeDeclaration.declarationSourceStart + 1);
+		
+		// need to set the superclass and super interfaces here since we cannot distinguish them at
+		// the type references level.
+		if (typeDeclaration.superclass != null) {
+			switch(this.ast.apiLevel) {
+				case AST.JLS2 :
+					typeDecl.setSuperclass(convert(typeDeclaration.superclass));
+					break;
+				case AST.JLS3 :
+					typeDecl.setSuperclassType(convertType(typeDeclaration.superclass));
+					break;
+			}
+		}
+		
+		org.eclipse.jdt.internal.compiler.ast.TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
+		if (superInterfaces != null) {
+			switch(this.ast.apiLevel) {
+				case AST.JLS2 :
+					for (int index = 0, length = superInterfaces.length; index < length; index++) {
+						typeDecl.superInterfaces().add(convert(superInterfaces[index]));
+					}
+					break;
+				case AST.JLS3 :
+					for (int index = 0, length = superInterfaces.length; index < length; index++) {
+						typeDecl.superInterfaceTypes().add(convertType(superInterfaces[index]));
+					}
+			}					
+		}
+		org.eclipse.jdt.internal.compiler.ast.TypeParameter[] typeParameters = typeDeclaration.typeParameters;
+		if (typeParameters != null) {
+			switch(this.ast.apiLevel) {
+				case AST.JLS2 :
+					typeDecl.setFlags(typeDecl.getFlags() | ASTNode.MALFORMED);
+					break;
+				case AST.JLS3 :
+					for (int index = 0, length = typeParameters.length; index < length; index++) {
+						typeDecl.typeParameters().add(convert(typeParameters[index]));
+					}
+			}
+		}
+		buildBodyDeclarations(typeDeclaration, typeDecl);
+		if (this.resolveBindings) {
+			recordNodes(typeDecl, typeDeclaration);
+			recordNodes(typeName, typeDeclaration);
+			typeDecl.resolveBinding();
+		}
+		return typeDecl;
+	}
+
+	public TypeParameter convert(org.eclipse.jdt.internal.compiler.ast.TypeParameter typeParameter) {
+		TypeParameter typeParameter2 = this.ast.newTypeParameter();
+		SimpleName simpleName = this.ast.newSimpleName(new String(typeParameter.name));
+		int start = typeParameter.sourceStart;
+		int end = typeParameter.sourceEnd;
+		simpleName.setSourceRange(start, end - start + 1);
+		typeParameter2.setName(simpleName);
+		final TypeReference superType = typeParameter.type;
+		end = typeParameter.declarationSourceEnd;
+		if (superType != null) {
+			Type type = convertType(superType);
+			typeParameter2.typeBounds().add(type);
+			end = type.getStartPosition() + type.getLength() - 1;
+		}
+		TypeReference[] bounds = typeParameter.bounds;
+		if (bounds != null) {
+			Type type = null;
+			for (int index = 0, length = bounds.length; index < length; index++) {
+				type = convertType(bounds[index]);
+				typeParameter2.typeBounds().add(type);
+				end = type.getStartPosition() + type.getLength() - 1;
+			}
+		}
+		start = typeParameter.declarationSourceStart;
+		end = retrieveClosingAngleBracketPosition(end);
+		typeParameter2.setSourceRange(start, end - start + 1);
+		if (this.resolveBindings) {
+			recordName(simpleName, typeParameter);
+			recordNodes(typeParameter2, typeParameter);
+			typeParameter2.resolveBinding();
+		}
+		return typeParameter2;
+	}
+	
+	public Name convert(org.eclipse.jdt.internal.compiler.ast.TypeReference typeReference) {
+		char[][] typeName = typeReference.getTypeName();
+		int length = typeName.length;
+		Name name = null;
+		if (length > 1) {
+			// QualifiedName
+			org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference qualifiedTypeReference = (org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) typeReference;
+			long[] positions = qualifiedTypeReference.sourcePositions;			
+			name = setQualifiedNameNameAndSourceRanges(typeName, positions, typeReference);
+		} else {
+			name = this.ast.newSimpleName(new String(typeName[0]));
+			name.setSourceRange(typeReference.sourceStart, typeReference.sourceEnd - typeReference.sourceStart + 1);
+		}
+		if (this.resolveBindings) {
+			recordNodes(name, typeReference);
+		}
+		return name;
+	}
+			
+	public PrefixExpression convert(org.eclipse.jdt.internal.compiler.ast.UnaryExpression expression) {
+		PrefixExpression prefixExpression = this.ast.newPrefixExpression();
+		if (this.resolveBindings) {
+			this.recordNodes(prefixExpression, expression);
+		}
+		prefixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+		prefixExpression.setOperand(convert(expression.expression));
+		switch ((expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT) {
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
+				prefixExpression.setOperator(PrefixExpression.Operator.PLUS);
+				break;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
+				prefixExpression.setOperator(PrefixExpression.Operator.MINUS);
+				break;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.NOT :
+				prefixExpression.setOperator(PrefixExpression.Operator.NOT);
+				break;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.TWIDDLE :
+				prefixExpression.setOperator(PrefixExpression.Operator.COMPLEMENT);
+		}
+		return prefixExpression;
+	}
 	
 	public WhileStatement convert(org.eclipse.jdt.internal.compiler.ast.WhileStatement statement) {
 		WhileStatement whileStatement = this.ast.newWhileStatement();
@@ -2145,7 +2509,639 @@
 		return whileStatement;
 	}
 	
-	private boolean isPrimitiveType(char[] name) {
+	public ImportDeclaration convertImport(org.eclipse.jdt.internal.compiler.ast.ImportReference importReference) {
+		ImportDeclaration importDeclaration = this.ast.newImportDeclaration();
+		boolean onDemand = importReference.onDemand;
+		char[][] tokens = importReference.tokens;
+		int length = importReference.tokens.length;
+		long[] positions = importReference.sourcePositions;
+		Name name = null;
+		if (length > 1) {
+			name = setQualifiedNameNameAndSourceRanges(tokens, positions, importReference);
+		} else {
+			name = this.ast.newSimpleName(new String(tokens[0]));
+			int start = (int)(positions[0]>>>32);
+			int end = (int)(positions[0] & 0xFFFFFFFF);
+			name.setSourceRange(start, end - start + 1);
+		}
+		importDeclaration.setSourceRange(importReference.declarationSourceStart, importReference.declarationEnd - importReference.declarationSourceStart + 1);
+		importDeclaration.setName(name);
+		importDeclaration.setOnDemand(onDemand);
+		int modifiers = importReference.modifiers;
+		if (modifiers != IConstants.AccDefault) {
+			switch(this.ast.apiLevel) {
+				case AST.JLS2 :
+					importDeclaration.setFlags(importDeclaration.getFlags() | ASTNode.MALFORMED);
+					break;
+				case AST.JLS3 :
+					if (modifiers == IConstants.AccStatic) {
+						importDeclaration.setStatic(true);
+					} else {
+						importDeclaration.setFlags(importDeclaration.getFlags() | ASTNode.MALFORMED);
+					}
+			}
+		}
+		if (this.resolveBindings) {
+			recordNodes(importDeclaration, importReference);
+		}
+		return importDeclaration;
+	}
+
+	public PackageDeclaration convertPackage(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration compilationUnitDeclaration) {
+		org.eclipse.jdt.internal.compiler.ast.ImportReference importReference = compilationUnitDeclaration.currentPackage;
+		PackageDeclaration packageDeclaration = this.ast.newPackageDeclaration();
+		char[][] tokens = importReference.tokens;
+		int length = importReference.tokens.length;
+		long[] positions = importReference.sourcePositions;
+		int start = (int)(positions[0]>>>32);
+		int end = (int)(positions[length - 1] & 0xFFFFFFFF);
+		Name name = null;
+		if (length > 1) {
+			name = setQualifiedNameNameAndSourceRanges(tokens, positions, importReference);
+		} else {
+			name = this.ast.newSimpleName(new String(tokens[0]));
+			name.setSourceRange(start, end - start + 1);
+		}
+		packageDeclaration.setSourceRange(importReference.declarationSourceStart, importReference.declarationEnd - importReference.declarationSourceStart + 1);
+		packageDeclaration.setName(name);
+		org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations = importReference.annotations;
+		if (annotations != null) {
+			switch(this.ast.apiLevel) {
+				case AST.JLS2 :
+					packageDeclaration.setFlags(packageDeclaration.getFlags() & ASTNode.MALFORMED);
+					break;
+				case AST.JLS3 :
+					for (int i = 0, max = annotations.length; i < max; i++) {
+						packageDeclaration.annotations().add(convert(annotations[i]));
+					}
+			}
+		}
+		if (this.resolveBindings) {
+			recordNodes(packageDeclaration, importReference);
+			recordNodes(name, compilationUnitDeclaration);
+		}
+		return packageDeclaration;
+	}
+	
+	private EnumDeclaration convertToEnumDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+		checkCanceled();
+		EnumDeclaration enumDeclaration2 = this.ast.newEnumDeclaration();
+		setModifiers(enumDeclaration2, typeDeclaration);
+		SimpleName typeName = this.ast.newSimpleName(new String(typeDeclaration.name));
+		typeName.setSourceRange(typeDeclaration.sourceStart, typeDeclaration.sourceEnd - typeDeclaration.sourceStart + 1);
+		enumDeclaration2.setName(typeName);
+		enumDeclaration2.setSourceRange(typeDeclaration.declarationSourceStart, typeDeclaration.bodyEnd - typeDeclaration.declarationSourceStart + 1);
+		
+		org.eclipse.jdt.internal.compiler.ast.TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
+		if (superInterfaces != null) {
+			for (int index = 0, length = superInterfaces.length; index < length; index++) {
+				enumDeclaration2.superInterfaceTypes().add(convertType(superInterfaces[index]));
+			}					
+		}
+		buildBodyDeclarations(typeDeclaration, enumDeclaration2);
+		if (this.resolveBindings) {
+			recordNodes(enumDeclaration2, typeDeclaration);
+			recordNodes(typeName, typeDeclaration);
+			enumDeclaration2.resolveBinding();
+		}
+		return enumDeclaration2;
+	}
+	public Expression convertToExpression(org.eclipse.jdt.internal.compiler.ast.Statement statement) {
+		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.Expression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.Expression) statement);
+		} else {
+			return null;
+		}
+	}
+
+	protected FieldDeclaration convertToFieldDeclaration(org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDecl) {
+		VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(fieldDecl);
+		FieldDeclaration fieldDeclaration = this.ast.newFieldDeclaration(variableDeclarationFragment);
+		if (this.resolveBindings) {
+			recordNodes(variableDeclarationFragment, fieldDecl);
+			variableDeclarationFragment.resolveBinding();
+		}
+		fieldDeclaration.setSourceRange(fieldDecl.declarationSourceStart, fieldDecl.declarationEnd - fieldDecl.declarationSourceStart + 1);
+		Type type = convertType(fieldDecl.type);
+		setTypeForField(fieldDeclaration, type, variableDeclarationFragment.getExtraDimensions());
+		setModifiers(fieldDeclaration, fieldDecl);
+		convert(fieldDecl.javadoc, fieldDeclaration);
+		return fieldDeclaration;
+	}
+
+	public ParenthesizedExpression convertToParenthesizedExpression(org.eclipse.jdt.internal.compiler.ast.Expression expression) {
+		ParenthesizedExpression parenthesizedExpression = this.ast.newParenthesizedExpression();
+		if (this.resolveBindings) {
+			recordNodes(parenthesizedExpression, expression);
+		}
+		parenthesizedExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+		adjustSourcePositionsForParent(expression);
+		trimWhiteSpacesAndComments(expression);
+		// decrement the number of parenthesis
+		int numberOfParenthesis = (expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedSHIFT;
+		expression.bits &= ~org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK;
+		expression.bits |= (numberOfParenthesis - 1) << org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedSHIFT;
+		parenthesizedExpression.setExpression(convert(expression));
+		return parenthesizedExpression;
+	}
+		
+	public Type convertToType(org.eclipse.jdt.internal.compiler.ast.NameReference reference) {
+		Name name = convert(reference);
+		SimpleType type = this.ast.newSimpleType(name);
+		type.setSourceRange(name.getStartPosition(), name.getLength());
+		if (this.resolveBindings) {
+			this.recordNodes(type, reference);
+		}
+		return type;
+	}
+	
+	protected VariableDeclarationExpression convertToVariableDeclarationExpression(org.eclipse.jdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
+		VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(localDeclaration);
+		VariableDeclarationExpression variableDeclarationExpression = this.ast.newVariableDeclarationExpression(variableDeclarationFragment);
+		if (this.resolveBindings) {
+			recordNodes(variableDeclarationFragment, localDeclaration);
+		}
+		variableDeclarationExpression.setSourceRange(localDeclaration.declarationSourceStart, localDeclaration.declarationSourceEnd - localDeclaration.declarationSourceStart + 1);
+		Type type = convertType(localDeclaration.type);
+		setTypeForVariableDeclarationExpression(variableDeclarationExpression, type, variableDeclarationFragment.getExtraDimensions());
+		if (localDeclaration.modifiersSourceStart != -1) {
+			setModifiers(variableDeclarationExpression, localDeclaration);
+		}
+		return variableDeclarationExpression;
+	}
+
+	protected SingleVariableDeclaration convertToSingleVariableDeclaration(LocalDeclaration localDeclaration) {
+		SingleVariableDeclaration variableDecl = this.ast.newSingleVariableDeclaration();
+		setModifiers(variableDecl, localDeclaration);
+		SimpleName name = this.ast.newSimpleName(new String(localDeclaration.name));
+		int start = localDeclaration.sourceStart;
+		int nameEnd = localDeclaration.sourceEnd;
+		name.setSourceRange(start, nameEnd - start + 1);
+		variableDecl.setName(name);
+		final int extraDimensions = retrieveExtraDimension(nameEnd + 1, localDeclaration.type.sourceEnd);
+		variableDecl.setExtraDimensions(extraDimensions);
+		Type type = convertType(localDeclaration.type);
+		int typeEnd = type.getStartPosition() + type.getLength() - 1;
+		int rightEnd = Math.max(typeEnd, localDeclaration.declarationSourceEnd);
+		/*
+		 * There is extra work to do to set the proper type positions
+		 * See PR http://bugs.eclipse.org/bugs/show_bug.cgi?id=23284
+		 */
+		setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions);
+		variableDecl.setSourceRange(localDeclaration.declarationSourceStart, rightEnd - localDeclaration.declarationSourceStart + 1);
+		if (this.resolveBindings) {
+			recordNodes(name, localDeclaration);
+			recordNodes(variableDecl, localDeclaration);
+			variableDecl.resolveBinding();
+		}
+		return variableDecl;
+	}
+	
+	protected VariableDeclarationFragment convertToVariableDeclarationFragment(org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration) {
+		VariableDeclarationFragment variableDeclarationFragment = this.ast.newVariableDeclarationFragment();
+		SimpleName name = this.ast.newSimpleName(new String(fieldDeclaration.name));
+		name.setSourceRange(fieldDeclaration.sourceStart, fieldDeclaration.sourceEnd - fieldDeclaration.sourceStart + 1);
+		variableDeclarationFragment.setName(name);
+		int end = retrievePositionBeforeNextCommaOrSemiColon(fieldDeclaration.sourceEnd, fieldDeclaration.declarationSourceEnd);
+		if (end == -1) {
+			variableDeclarationFragment.setSourceRange(fieldDeclaration.sourceStart, fieldDeclaration.declarationSourceEnd - fieldDeclaration.sourceStart + 1);
+			variableDeclarationFragment.setFlags(variableDeclarationFragment.getFlags() | ASTNode.MALFORMED);
+		} else {
+			variableDeclarationFragment.setSourceRange(fieldDeclaration.sourceStart, end - fieldDeclaration.sourceStart + 1);
+		}
+		if (fieldDeclaration.initialization != null) {
+			variableDeclarationFragment.setInitializer(convert(fieldDeclaration.initialization));
+		}
+		variableDeclarationFragment.setExtraDimensions(retrieveExtraDimension(fieldDeclaration.sourceEnd + 1, fieldDeclaration.declarationSourceEnd ));
+		if (this.resolveBindings) {
+			recordNodes(name, fieldDeclaration);
+			recordNodes(variableDeclarationFragment, fieldDeclaration);
+			variableDeclarationFragment.resolveBinding();
+		}
+		return variableDeclarationFragment;
+	}
+
+	protected VariableDeclarationFragment convertToVariableDeclarationFragment(org.eclipse.jdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
+		VariableDeclarationFragment variableDeclarationFragment = this.ast.newVariableDeclarationFragment();
+		SimpleName name = this.ast.newSimpleName(new String(localDeclaration.name));
+		name.setSourceRange(localDeclaration.sourceStart, localDeclaration.sourceEnd - localDeclaration.sourceStart + 1);
+		variableDeclarationFragment.setName(name);
+		int end = retrievePositionBeforeNextCommaOrSemiColon(localDeclaration.sourceEnd, this.compilationUnitSource.length);
+		if (end == -1) {
+			if (localDeclaration.initialization != null) {
+				variableDeclarationFragment.setSourceRange(localDeclaration.sourceStart, localDeclaration.initialization.sourceEnd - localDeclaration.sourceStart + 1);
+			} else {
+				variableDeclarationFragment.setSourceRange(localDeclaration.sourceStart, localDeclaration.sourceEnd - localDeclaration.sourceStart + 1);
+			}
+		} else {
+			variableDeclarationFragment.setSourceRange(localDeclaration.sourceStart, end - localDeclaration.sourceStart + 1);
+		}
+		if (localDeclaration.initialization != null) {
+			variableDeclarationFragment.setInitializer(convert(localDeclaration.initialization));
+		}
+		variableDeclarationFragment.setExtraDimensions(retrieveExtraDimension(localDeclaration.sourceEnd + 1, this.compilationUnitSource.length));
+		if (this.resolveBindings) {
+			recordNodes(variableDeclarationFragment, localDeclaration);
+			recordNodes(name, localDeclaration);
+			variableDeclarationFragment.resolveBinding();
+		}
+		return variableDeclarationFragment;
+	}
+
+	protected VariableDeclarationStatement convertToVariableDeclarationStatement(org.eclipse.jdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
+		VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(localDeclaration);
+		VariableDeclarationStatement variableDeclarationStatement = this.ast.newVariableDeclarationStatement(variableDeclarationFragment);
+		if (this.resolveBindings) {
+			recordNodes(variableDeclarationFragment, localDeclaration);
+		}
+		variableDeclarationStatement.setSourceRange(localDeclaration.declarationSourceStart, localDeclaration.declarationSourceEnd - localDeclaration.declarationSourceStart + 1);
+		Type type = convertType(localDeclaration.type);
+		setTypeForVariableDeclarationStatement(variableDeclarationStatement, type, variableDeclarationFragment.getExtraDimensions());
+		if (localDeclaration.modifiersSourceStart != -1) {
+			setModifiers(variableDeclarationStatement, localDeclaration);
+		}
+		return variableDeclarationStatement;
+	}
+
+	public Type convertType(TypeReference typeReference) {
+		if (typeReference instanceof Wildcard) {
+			Wildcard wildcard = (Wildcard) typeReference;
+			WildcardType wildcardType = this.ast.newWildcardType();
+			if (wildcard.bound != null) {
+				wildcardType.setBound(convertType(wildcard.bound), wildcard.kind == Wildcard.EXTENDS);
+			}
+			int start = wildcard.sourceStart;
+			int end = wildcard.sourceEnd;
+			wildcardType.setSourceRange(start, end - start + 1);
+			if (this.resolveBindings) {
+				recordNodes(wildcardType, typeReference);
+			}
+			return wildcardType;
+		}
+		Type type = null;				
+		int sourceStart = -1;
+		int length = 0;
+		int dimensions = typeReference.dimensions();
+		if (typeReference instanceof org.eclipse.jdt.internal.compiler.ast.SingleTypeReference) {
+			// this is either an ArrayTypeReference or a SingleTypeReference
+			char[] name = ((org.eclipse.jdt.internal.compiler.ast.SingleTypeReference) typeReference).getTypeName()[0];
+			sourceStart = typeReference.sourceStart;
+			length = typeReference.sourceEnd - typeReference.sourceStart + 1;
+			// need to find out if this is an array type of primitive types or not
+			if (isPrimitiveType(name)) {
+				int end = retrieveEndOfElementTypeNamePosition(sourceStart, sourceStart + length);
+				if (end == -1) {
+					end = sourceStart + length - 1;
+				}					
+				type = this.ast.newPrimitiveType(getPrimitiveTypeCode(name));
+				type.setSourceRange(sourceStart, end - sourceStart + 1);
+			} else if (typeReference instanceof ParameterizedSingleTypeReference) {
+				ParameterizedSingleTypeReference parameterizedSingleTypeReference = (ParameterizedSingleTypeReference) typeReference;
+				SimpleName simpleName = this.ast.newSimpleName(new String(name));
+				int end = retrieveEndOfElementTypeNamePosition(sourceStart, sourceStart + length);
+				if (end == -1) {
+					end = sourceStart + length - 1;
+				}
+				simpleName.setSourceRange(sourceStart, end - sourceStart + 1);
+				switch(this.ast.apiLevel) {
+					case AST.JLS2 :
+						type = this.ast.newSimpleType(simpleName);
+						type.setFlags(type.getFlags() | ASTNode.MALFORMED);
+						type.setSourceRange(sourceStart, end - sourceStart + 1);
+						if (this.resolveBindings) {
+							this.recordNodes(simpleName, typeReference);
+						}
+						break;
+					case AST.JLS3 :
+						SimpleType simpleType = this.ast.newSimpleType(simpleName);
+						simpleType.setSourceRange(simpleName.getStartPosition(), simpleName.getLength());
+						type = this.ast.newParameterizedType(simpleType);
+						TypeReference[] typeArguments = parameterizedSingleTypeReference.typeArguments;
+						if (typeArguments != null) {
+							Type type2 = null;
+							for (int i = 0, max = typeArguments.length; i < max; i++) {
+								type2 = convertType(typeArguments[i]);
+								((ParameterizedType) type).typeArguments().add(type2);
+								end = type2.getStartPosition() + type2.getLength() - 1;
+							}
+							end = retrieveClosingAngleBracketPosition(end + 1);
+							type.setSourceRange(sourceStart, end - sourceStart + 1);
+						} else {
+							type.setSourceRange(sourceStart, end - sourceStart + 1);
+						}
+						if (this.resolveBindings) {
+							this.recordNodes(simpleName, typeReference);
+							this.recordNodes(simpleType, typeReference);
+						}
+				}
+			} else {
+				SimpleName simpleName = this.ast.newSimpleName(new String(name));
+				// we need to search for the starting position of the first brace in order to set the proper length
+				// PR http://dev.eclipse.org/bugs/show_bug.cgi?id=10759
+				int end = retrieveEndOfElementTypeNamePosition(sourceStart, sourceStart + length);
+				if (end == -1) {
+					end = sourceStart + length - 1;
+				}
+				simpleName.setSourceRange(sourceStart, end - sourceStart + 1);
+				type = this.ast.newSimpleType(simpleName);
+				type.setSourceRange(sourceStart, end - sourceStart + 1);
+				if (this.resolveBindings) {
+					this.recordNodes(simpleName, typeReference);
+				}
+			}
+			if (dimensions != 0) {
+				type = this.ast.newArrayType(type, dimensions);
+				type.setSourceRange(sourceStart, length);
+				if (this.resolveBindings) {
+					// store keys for inner types
+					completeRecord((ArrayType) type, typeReference);
+				}
+			}
+		} else {
+			if (typeReference instanceof ParameterizedQualifiedTypeReference) {
+				ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference = (ParameterizedQualifiedTypeReference) typeReference;
+				char[][] tokens = parameterizedQualifiedTypeReference.tokens;
+				TypeReference[][] typeArguments = parameterizedQualifiedTypeReference.typeArguments;
+				long[] positions = parameterizedQualifiedTypeReference.sourcePositions;
+				sourceStart = (int)(positions[0]>>>32);
+				switch(this.ast.apiLevel) {
+					case AST.JLS2 : {
+							char[][] name = ((org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) typeReference).getTypeName();
+							int nameLength = name.length;
+							sourceStart = (int)(positions[0]>>>32);
+							length = (int)(positions[nameLength - 1] & 0xFFFFFFFF) - sourceStart + 1;
+							Name qualifiedName = this.setQualifiedNameNameAndSourceRanges(name, positions, typeReference);
+							type = this.ast.newSimpleType(qualifiedName);
+							type.setSourceRange(sourceStart, length);
+						}
+						break;
+					case AST.JLS3 :
+						if (typeArguments != null) {
+							int numberOfEnclosingType = 0;
+							for (int i = 0, max = typeArguments.length; i < max; i++) {
+								if (typeArguments[i] != null) {
+									numberOfEnclosingType++;
+								}
+							}
+							int startingIndex = 0;
+							int endingIndex = 0;
+							while (typeArguments[endingIndex] == null) {
+								endingIndex++;
+							}
+							Name name = null;
+							if (endingIndex - startingIndex == 0) {
+								name = this.ast.newSimpleName(new String(tokens[startingIndex]));
+								recordPendingNameScopeResolution(name);
+								int start = (int)(positions[startingIndex]>>>32);
+								int end = (int) positions[startingIndex];
+								name.setSourceRange(start, end - start + 1);
+							} else {
+								name = this.setQualifiedNameNameAndSourceRanges(tokens, positions, startingIndex, endingIndex, typeReference);
+							}
+							SimpleType simpleType = this.ast.newSimpleType(name);
+							int start = (int)(positions[startingIndex]>>>32);
+							int end = (int) positions[endingIndex];
+							simpleType.setSourceRange(start, end - start + 1);
+							ParameterizedType parameterizedType = this.ast.newParameterizedType(simpleType);
+							start = simpleType.getStartPosition();
+							end = start + simpleType.getLength() - 1;
+							for (int i = 0, max = typeArguments[endingIndex].length; i < max; i++) {
+								final Type type2 = convertType(typeArguments[endingIndex][i]);
+								parameterizedType.typeArguments().add(type2);
+								end = type2.getStartPosition() + type2.getLength() - 1;
+							}
+							end = retrieveClosingAngleBracketPosition(end + 1);
+							length = end + 1;
+							parameterizedType.setSourceRange(start, end - start + 1);
+							startingIndex = endingIndex + 1;
+							Type currentType = parameterizedType;
+							while(startingIndex < typeArguments.length) {
+								SimpleName simpleName = this.ast.newSimpleName(new String(tokens[startingIndex]));
+								start = (int)(positions[startingIndex]>>>32);
+								end = (int) positions[startingIndex];
+								simpleName.setSourceRange(start, end - start + 1);
+								recordPendingNameScopeResolution(simpleName);
+								QualifiedType qualifiedType = this.ast.newQualifiedType(currentType, simpleName);							
+								start = currentType.getStartPosition();
+								end = simpleName.getStartPosition() + simpleName.getLength() - 1;
+								qualifiedType.setSourceRange(start, end - start + 1);
+								if (typeArguments[startingIndex] != null) {
+									ParameterizedType parameterizedType2 = this.ast.newParameterizedType(qualifiedType);
+									for (int i = 0, max = typeArguments[startingIndex].length; i < max; i++) {
+										final Type type2 = convertType(typeArguments[startingIndex][i]);
+										parameterizedType2.typeArguments().add(type2);
+										end = type2.getStartPosition() + type2.getLength() - 1;
+									}
+									end = retrieveClosingAngleBracketPosition(end + 1);
+									length = end + 1;
+									parameterizedType2.setSourceRange(start, end - start + 1);							
+									currentType = parameterizedType2;
+								} else {
+									currentType = qualifiedType;
+								}
+								startingIndex++;
+							}
+							if (this.resolveBindings) {
+								this.recordNodes(currentType, typeReference);
+							}
+							type = currentType;
+							length -= sourceStart;
+						}
+				}
+			} else {
+				char[][] name = ((org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) typeReference).getTypeName();
+				int nameLength = name.length;
+				long[] positions = ((org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) typeReference).sourcePositions;
+				sourceStart = (int)(positions[0]>>>32);
+				length = (int)(positions[nameLength - 1] & 0xFFFFFFFF) - sourceStart + 1;
+				Name qualifiedName = this.setQualifiedNameNameAndSourceRanges(name, positions, typeReference);
+				type = this.ast.newSimpleType(qualifiedName);
+				type.setSourceRange(sourceStart, length);
+			}
+
+			if (dimensions != 0) {
+				type = this.ast.newArrayType(type, dimensions);
+				if (this.resolveBindings) {
+					completeRecord((ArrayType) type, typeReference);
+				}
+				int end = retrieveEndOfDimensionsPosition(sourceStart+length, this.compilationUnitSource.length);
+				if (end != -1) {
+					type.setSourceRange(sourceStart, end - sourceStart + 1);
+				} else {
+					type.setSourceRange(sourceStart, length);
+				}
+			}
+		}
+		if (this.resolveBindings) {
+			this.recordNodes(type, typeReference);
+		}
+		return type;
+	}
+
+	protected Comment createComment(int[] positions) {
+		// Create comment node
+		Comment comment = null;
+		int start = positions[0];
+		int end = positions[1];
+		if (positions[1]>0) { // Javadoc comments have positive end position
+			this.ast.newJavadoc();
+			Javadoc docComment = this.docParser.parse(positions);
+			if (docComment == null) return null;
+			comment = docComment;
+		} else {
+			end = -end;
+			if (positions[0]>0) { // Block comment have positive start position
+				comment = this.ast.newBlockComment();
+			} else { // Line comment have negative start and end position
+				start = -start;
+				comment = this.ast.newLineComment();
+			}
+			comment.setSourceRange(start, end - start);
+		}
+		return comment;
+	}
+	
+	protected Statement createFakeEmptyStatement(org.eclipse.jdt.internal.compiler.ast.Statement statement) {
+		EmptyStatement emptyStatement = this.ast.newEmptyStatement();
+		emptyStatement.setFlags(emptyStatement.getFlags() | ASTNode.MALFORMED);
+		int start = statement.sourceStart;
+		int end = statement.sourceEnd;
+		emptyStatement.setSourceRange(start, end - start + 1);
+		return emptyStatement;
+	}
+	/**
+	 * @return a new modifier
+	 */
+	private Modifier createModifier(ModifierKeyword keyword) {
+		Modifier modifier;
+		modifier = this.ast.newModifier(keyword);
+		int start = this.scanner.getCurrentTokenStartPosition();
+		int end = this.scanner.getCurrentTokenEndPosition();
+		modifier.setSourceRange(start, end - start + 1);
+		return modifier;
+	}
+	
+	protected InfixExpression.Operator getOperatorFor(int operatorID) {
+		switch (operatorID) {
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL :
+				return InfixExpression.Operator.EQUALS;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LESS_EQUAL :
+				return InfixExpression.Operator.LESS_EQUALS;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.GREATER_EQUAL :
+				return InfixExpression.Operator.GREATER_EQUALS;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.NOT_EQUAL :
+				return InfixExpression.Operator.NOT_EQUALS;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LEFT_SHIFT :
+				return InfixExpression.Operator.LEFT_SHIFT;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.RIGHT_SHIFT :
+				return InfixExpression.Operator.RIGHT_SHIFT_SIGNED;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.UNSIGNED_RIGHT_SHIFT :
+				return InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.OR_OR :
+				return InfixExpression.Operator.CONDITIONAL_OR;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.AND_AND :
+				return InfixExpression.Operator.CONDITIONAL_AND;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
+				return InfixExpression.Operator.PLUS;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
+				return InfixExpression.Operator.MINUS;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.REMAINDER :
+				return InfixExpression.Operator.REMAINDER;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.XOR :
+				return InfixExpression.Operator.XOR;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.AND :
+				return InfixExpression.Operator.AND;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MULTIPLY :
+				return InfixExpression.Operator.TIMES;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.OR :
+				return InfixExpression.Operator.OR;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.DIVIDE :
+				return InfixExpression.Operator.DIVIDE;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.GREATER :
+				return InfixExpression.Operator.GREATER;
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LESS :
+				return InfixExpression.Operator.LESS;
+		}
+		return null;
+	}
+	
+	protected PrimitiveType.Code getPrimitiveTypeCode(char[] name) {
+		switch(name[0]) {
+			case 'i' :
+				if (name.length == 3 && name[1] == 'n' && name[2] == 't') {
+					return PrimitiveType.INT;
+				}
+				break;
+			case 'l' :
+				if (name.length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g') {
+					return PrimitiveType.LONG;
+				}
+				break;
+			case 'd' :
+				if (name.length == 6
+					 && name[1] == 'o'
+					 && name[2] == 'u'
+					 && name[3] == 'b'
+					 && name[4] == 'l'
+					 && name[5] == 'e') {
+					return PrimitiveType.DOUBLE;
+				}
+				break;
+			case 'f' :
+				if (name.length == 5
+					 && name[1] == 'l'
+					 && name[2] == 'o'
+					 && name[3] == 'a'
+					 && name[4] == 't') {
+					return PrimitiveType.FLOAT;
+				}
+				break;
+			case 'b' :
+				if (name.length == 4
+					 && name[1] == 'y'
+					 && name[2] == 't'
+					 && name[3] == 'e') {
+					return PrimitiveType.BYTE;
+				} else
+					if (name.length == 7
+						 && name[1] == 'o'
+						 && name[2] == 'o'
+						 && name[3] == 'l'
+						 && name[4] == 'e'
+						 && name[5] == 'a'
+						 && name[6] == 'n') {
+					return PrimitiveType.BOOLEAN;
+				}
+				break;
+			case 'c' :
+				if (name.length == 4
+					 && name[1] == 'h'
+					 && name[2] == 'a'
+					 && name[3] == 'r') {
+					return PrimitiveType.CHAR;
+				}
+				break;
+			case 's' :
+				if (name.length == 5
+					 && name[1] == 'h'
+					 && name[2] == 'o'
+					 && name[3] == 'r'
+					 && name[4] == 't') {
+					return PrimitiveType.SHORT;
+				}
+				break;
+			case 'v' :
+				if (name.length == 4
+					 && name[1] == 'o'
+					 && name[2] == 'i'
+					 && name[3] == 'd') {
+					return PrimitiveType.VOID;
+				}
+		}
+		return null; // cannot be reached
+	}
+	
+	protected boolean isPrimitiveType(char[] name) {
 		switch(name[0]) {
 			case 'i' :
 				if (name.length == 3 && name[1] == 'n' && name[2] == 't') {
@@ -2222,839 +3218,103 @@
 		return false;
 	}
 	
-	private PrimitiveType.Code getPrimitiveTypeCode(char[] name) {
-		switch(name[0]) {
-			case 'i' :
-				if (name.length == 3 && name[1] == 'n' && name[2] == 't') {
-					return PrimitiveType.INT;
-				}
-				break;
-			case 'l' :
-				if (name.length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g') {
-					return PrimitiveType.LONG;
-				}
-				break;
-			case 'd' :
-				if (name.length == 6
-					 && name[1] == 'o'
-					 && name[2] == 'u'
-					 && name[3] == 'b'
-					 && name[4] == 'l'
-					 && name[5] == 'e') {
-					return PrimitiveType.DOUBLE;
-				}
-				break;
-			case 'f' :
-				if (name.length == 5
-					 && name[1] == 'l'
-					 && name[2] == 'o'
-					 && name[3] == 'a'
-					 && name[4] == 't') {
-					return PrimitiveType.FLOAT;
-				}
-				break;
-			case 'b' :
-				if (name.length == 4
-					 && name[1] == 'y'
-					 && name[2] == 't'
-					 && name[3] == 'e') {
-					return PrimitiveType.BYTE;
-				} else
-					if (name.length == 7
-						 && name[1] == 'o'
-						 && name[2] == 'o'
-						 && name[3] == 'l'
-						 && name[4] == 'e'
-						 && name[5] == 'a'
-						 && name[6] == 'n') {
-					return PrimitiveType.BOOLEAN;
-				}
-				break;
-			case 'c' :
-				if (name.length == 4
-					 && name[1] == 'h'
-					 && name[2] == 'a'
-					 && name[3] == 'r') {
-					return PrimitiveType.CHAR;
-				}
-				break;
-			case 's' :
-				if (name.length == 5
-					 && name[1] == 'h'
-					 && name[2] == 'o'
-					 && name[3] == 'r'
-					 && name[4] == 't') {
-					return PrimitiveType.SHORT;
-				}
-				break;
-			case 'v' :
-				if (name.length == 4
-					 && name[1] == 'o'
-					 && name[2] == 'i'
-					 && name[3] == 'd') {
-					return PrimitiveType.VOID;
-				}
+	private void lookupForScopes() {
+		if (this.pendingNameScopeResolution != null) {
+			for (Iterator iterator = this.pendingNameScopeResolution.iterator(); iterator.hasNext(); ) {
+				Name name = (Name) iterator.next();
+				this.ast.getBindingResolver().recordScope(name, lookupScope(name));
+			}
 		}
-		throw new IllegalArgumentException("Not a primitive type");//$NON-NLS-1$
+		if (this.pendingThisExpressionScopeResolution != null) {
+			for (Iterator iterator = this.pendingThisExpressionScopeResolution.iterator(); iterator.hasNext(); ) {
+				ThisExpression thisExpression = (ThisExpression) iterator.next();
+				this.ast.getBindingResolver().recordScope(thisExpression, lookupScope(thisExpression));
+			}
+		}
+		
 	}
 	
-	/*
-	 * This method is used to set the right end position for expression
-	 * statement. The actual AST nodes don't include the trailing semicolon.
-	 * This method fixes the length of the corresponding node.
-	 */
-	private void retrieveSemiColonPosition(ASTNode node) {
-		int start = node.getStartPosition();
-		int length = node.getLength();
-		int end = start + length;
-		int count = 0;
-		this.scanner.resetTo(end, this.compilationUnitSource.length);
-		try {
-			int token;
-			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNameSEMICOLON:
-						if (count == 0) {
-							node.setSourceRange(start, this.scanner.currentPosition - start);
-							return;
-						}
-						break;
-					case TerminalTokens.TokenNameLBRACE :
-						count++;
-						break;
-					case TerminalTokens.TokenNameRBRACE :
-						count--;
-						break;
-					case TerminalTokens.TokenNameLPAREN :
-						count++;
-						break;
-					case TerminalTokens.TokenNameRPAREN :
-						count--;
-						break;
-					case TerminalTokens.TokenNameLBRACKET :
-						count++;
-						break;
-					case TerminalTokens.TokenNameRBRACKET :
-						count--;
-				}
+	private BlockScope lookupScope(ASTNode node) {
+		ASTNode currentNode = node;
+		while(currentNode != null
+			&&!(currentNode instanceof MethodDeclaration)
+			&& !(currentNode instanceof Initializer)
+			&& !(currentNode instanceof FieldDeclaration)) {
+			currentNode = currentNode.getParent();
+		}
+		if (currentNode == null) {
+			return null;
+		}
+		if (currentNode instanceof Initializer) {
+			Initializer initializer = (Initializer) currentNode;
+			while(!(currentNode instanceof AbstractTypeDeclaration)) {
+				currentNode = currentNode.getParent();
 			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-	}
-
-	/**
-	 * This method is used to set the right end position for expression
-	 * statement. The actual AST nodes don't include the trailing semicolon.
-	 * This method fixes the length of the corresponding node.
-	 */
-	private void retrieveColonPosition(ASTNode node) {
-		int start = node.getStartPosition();
-		int length = node.getLength();
-		int end = start + length;
-		this.scanner.resetTo(end, this.compilationUnitSource.length);
-		try {
-			int token;
-			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNameCOLON:
-						node.setSourceRange(start, this.scanner.currentPosition - start);
-						return;
-				}
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-	}
-
-	private int retrieveEndingSemiColonPosition(int start, int end) {
-		int count = 0;
-		this.scanner.resetTo(start, end);
-		try {
-			int token;
-			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNameSEMICOLON:
-						if (count == 0) {
-							return this.scanner.currentPosition - 1;
-						}
-						break;
-					case TerminalTokens.TokenNameLBRACE :
-						count++;
-						break;
-					case TerminalTokens.TokenNameRBRACE :
-						count--;
-						break;
-					case TerminalTokens.TokenNameLPAREN :
-						count++;
-						break;
-					case TerminalTokens.TokenNameRPAREN :
-						count--;
-						break;
-					case TerminalTokens.TokenNameLBRACKET :
-						count++;
-						break;
-					case TerminalTokens.TokenNameRBRACKET :
-						count--;
-				}
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-		return -1;
-	}
-
-	/**
-	 * This method is used to retrieve the array dimension declared after the
-	 * name of a local or a field declaration.
-	 * For example:
-	 *    int i, j[] = null, k[][] = {{}};
-	 *    It should return 0 for i, 1 for j and 2 for k.
-	 * @return int the dimension found
-	 */
-	private int retrieveExtraDimension(int start, int end) {
-		this.scanner.resetTo(start, end);
-		int dimensions = 0;
-		try {
-			int token;
-			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNameRBRACKET://166 
-						dimensions++;
-						break;
-					case TerminalTokens.TokenNameLBRACE ://90						
-					case TerminalTokens.TokenNameCOMMA ://90
-					case TerminalTokens.TokenNameEQUAL ://167
-					case TerminalTokens.TokenNameSEMICOLON ://64
-					case TerminalTokens.TokenNameRPAREN : //86
-						return dimensions;
-				}
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-		return dimensions;
-	}
-
-	/**
-	 * This method is used to retrieve the ending position for a type declaration when the dimension is right after the type
-	 * name.
-	 * For example:
-	 *    int[] i; => return 5, but int i[] => return -1;
-	 * @return int the dimension found
-	 */
-	private int retrieveEndOfDimensionsPosition(int start, int end) {
-		this.scanner.resetTo(start, end);
-		int foundPosition = -1;
-		try {
-			int token;
-			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNameLBRACKET:
-					case TerminalTokens.TokenNameCOMMENT_BLOCK:
-					case TerminalTokens.TokenNameCOMMENT_JAVADOC:
-					case TerminalTokens.TokenNameCOMMENT_LINE:
-						break;
-					case TerminalTokens.TokenNameRBRACKET://166
-						foundPosition = this.scanner.currentPosition - 1;
-						break;
-					default:
-						return foundPosition;
-				}
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-		return foundPosition;
-	}
-
-	/**
-	 * This method is used to retrieve the starting position of the catch keyword.
-	 * @return int the dimension found, -1 if none
-	 */
-	private int retrieveStartingCatchPosition(int start, int end) {
-		this.scanner.resetTo(start, end);
-		try {
-			int token;
-			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNamecatch://225
-						return this.scanner.startPosition;
-				}
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-		return -1;
-	}
-
-	/**
-	 * This method is used to retrieve the position just before the left bracket.
-	 * @return int the dimension found, -1 if none
-	 */
-	private int retrieveEndOfElementTypeNamePosition(int start, int end) {
-		this.scanner.resetTo(start, end);
-		try {
-			int token;
-			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNameIdentifier:
-					case TerminalTokens.TokenNamebyte:
-					case TerminalTokens.TokenNamechar:
-					case TerminalTokens.TokenNamedouble:
-					case TerminalTokens.TokenNamefloat:
-					case TerminalTokens.TokenNameint:
-					case TerminalTokens.TokenNamelong:
-					case TerminalTokens.TokenNameshort:
-						return this.scanner.currentPosition - 1;
-				}
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-		return -1;
-	}
-
-	/**
-	 * This method is used to retrieve the position of the right bracket.
-	 * @return int the dimension found, -1 if none
-	 */
-	private int retrieveRightBracketPosition(int start, int end) {
-		this.scanner.resetTo(start, end);
-		try {
-			int token;
-			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNameRBRACKET:
-						return this.scanner.currentPosition - 1;
-				}
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-		return -1;
-	}
-
-	/**
-	 * This method is used to retrieve the position after the right parenthesis.
-	 * @return int the position found
-	 */
-	private int retrieveEndOfRightParenthesisPosition(int start, int end) {
-		this.scanner.resetTo(start, end);
-		try {
-			int token;
-			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNameRPAREN:
-						return this.scanner.currentPosition;
-				}
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-		return -1;
-	}
-
-	private int retrieveProperRightBracketPosition(int bracketNumber, int start, int end) {
-		this.scanner.resetTo(start, end);
-		try {
-			int token, count = 0;
-			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNameRBRACKET:
-						count++;
-						if (count == bracketNumber) {
-							return this.scanner.currentPosition - 1;
-						}
-				}
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-		return -1;
-	}
-	
-	/**
-	 * This method is used to retrieve the start position of the block.
-	 * @return int the dimension found, -1 if none
-	 */
-	private int retrieveStartBlockPosition(int start, int end) {
-		this.scanner.resetTo(start, end);
-		try {
-			int token;
-			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNameLBRACE://110
-						return this.scanner.startPosition;
-				}
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-		return -1;
-	}
-	
-	/**
-	 * This method is used to retrieve the start position of the block.
-	 * @return int the dimension found, -1 if none
-	 */
-	private int retrieveIdentifierEndPosition(int start, int end) {
-		this.scanner.resetTo(start, end);
-		try {
-			int token;
-			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNameIdentifier://110
-						return this.scanner.getCurrentTokenEndPosition();
-				}
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-		return -1;
-	}	
-	
-	/**
-	 * This method is used to retrieve the end position of the block.
-	 * @return int the dimension found, -1 if none
-	 */
-	private int retrieveEndBlockPosition(int start, int end) {
-		this.scanner.resetTo(start, end);
-		int count = 0;
-		try {
-			int token;
-			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNameLBRACE://110
-						count++;
-						break;
-					case TerminalTokens.TokenNameRBRACE://95
-						count--;
-						if (count == 0) {
-							return this.scanner.currentPosition - 1;
-						}
-				}
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-		return -1;
-	}
-
-	/**
-	 * This method is used to retrieve position before the next right brace or semi-colon.
-	 * @return int the position found.
-	 */
-	private int retrieveRightBraceOrSemiColonPosition(MethodDeclaration node, org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration methodDeclaration) {
-		int start = node.getStartPosition();
-		this.scanner.resetTo(start, methodDeclaration.declarationSourceEnd);
-		try {
-			int token;
-			int braceCounter = 0;
-			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNameLBRACE :
-						braceCounter++;
-						break;
-					case TerminalTokens.TokenNameRBRACE :
-						braceCounter--;
-						if (braceCounter == 0) {
-							return this.scanner.currentPosition;
-						}
-						break;
-					case TerminalTokens.TokenNameSEMICOLON :
-						if (braceCounter == 0) {
-							return this.scanner.currentPosition;
-						}
-				}
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-		return -1;
-	}
-
-	/**
-	 * This method is used to retrieve position before the next comma or semi-colon.
-	 * @return int the position found.
-	 */
-	private int retrievePositionBeforeNextCommaOrSemiColon(int start, int end) {
-		this.scanner.resetTo(start, end);
-		int braceCounter = 0;
-		try {
-			int token;
-			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNameLBRACE :
-						braceCounter++;
-						break;
-					case TerminalTokens.TokenNameRBRACE :
-						braceCounter--;
-						break;
-					case TerminalTokens.TokenNameLPAREN :
-						braceCounter++;
-						break;
-					case TerminalTokens.TokenNameRPAREN :
-						braceCounter--;
-						break;
-					case TerminalTokens.TokenNameLBRACKET :
-						braceCounter++;
-						break;
-					case TerminalTokens.TokenNameRBRACKET :
-						braceCounter--;
-						break;
-					case TerminalTokens.TokenNameCOMMA :
-					case TerminalTokens.TokenNameSEMICOLON :
-						if (braceCounter == 0) {
-							return this.scanner.startPosition - 1;
-						}
-				}
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-		return -1;
-	}
-	
-	private VariableDeclarationFragment convertToVariableDeclarationFragment(org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration) {
-		VariableDeclarationFragment variableDeclarationFragment = this.ast.newVariableDeclarationFragment();
-		SimpleName name = this.ast.newSimpleName(new String(fieldDeclaration.name));
-		name.setSourceRange(fieldDeclaration.sourceStart, fieldDeclaration.sourceEnd - fieldDeclaration.sourceStart + 1);
-		variableDeclarationFragment.setName(name);
-		int end = retrievePositionBeforeNextCommaOrSemiColon(fieldDeclaration.sourceEnd, fieldDeclaration.declarationSourceEnd);
-		if (end == -1) {
-			variableDeclarationFragment.setSourceRange(fieldDeclaration.sourceStart, fieldDeclaration.declarationSourceEnd - fieldDeclaration.sourceStart + 1);
-			variableDeclarationFragment.setFlags(variableDeclarationFragment.getFlags() | ASTNode.MALFORMED);
-		} else {
-			variableDeclarationFragment.setSourceRange(fieldDeclaration.sourceStart, end - fieldDeclaration.sourceStart + 1);
-		}
-		if (fieldDeclaration.initialization != null) {
-			variableDeclarationFragment.setInitializer(convert(fieldDeclaration.initialization));
-		}
-		variableDeclarationFragment.setExtraDimensions(retrieveExtraDimension(fieldDeclaration.sourceEnd + 1, fieldDeclaration.declarationSourceEnd ));
-		if (this.resolveBindings) {
-			recordNodes(name, fieldDeclaration);
-			recordNodes(variableDeclarationFragment, fieldDeclaration);
-			variableDeclarationFragment.resolveBinding();
-		}
-		return variableDeclarationFragment;
-	}
-
-	private VariableDeclarationFragment convertToVariableDeclarationFragment(org.eclipse.jdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
-		VariableDeclarationFragment variableDeclarationFragment = this.ast.newVariableDeclarationFragment();
-		SimpleName name = this.ast.newSimpleName(new String(localDeclaration.name));
-		name.setSourceRange(localDeclaration.sourceStart, localDeclaration.sourceEnd - localDeclaration.sourceStart + 1);
-		variableDeclarationFragment.setName(name);
-		int end = retrievePositionBeforeNextCommaOrSemiColon(localDeclaration.sourceEnd, this.compilationUnitSource.length);
-		if (end == -1) {
-			if (localDeclaration.initialization != null) {
-				variableDeclarationFragment.setSourceRange(localDeclaration.sourceStart, localDeclaration.initialization.sourceEnd - localDeclaration.sourceStart + 1);
-			} else {
-				variableDeclarationFragment.setSourceRange(localDeclaration.sourceStart, localDeclaration.sourceEnd - localDeclaration.sourceStart + 1);
-			}
-		} else {
-			variableDeclarationFragment.setSourceRange(localDeclaration.sourceStart, end - localDeclaration.sourceStart + 1);
-		}
-		if (localDeclaration.initialization != null) {
-			variableDeclarationFragment.setInitializer(convert(localDeclaration.initialization));
-		}
-		variableDeclarationFragment.setExtraDimensions(retrieveExtraDimension(localDeclaration.sourceEnd + 1, this.compilationUnitSource.length));
-		if (this.resolveBindings) {
-			recordNodes(variableDeclarationFragment, localDeclaration);
-			recordNodes(name, localDeclaration);
-			variableDeclarationFragment.resolveBinding();
-		}
-		return variableDeclarationFragment;
-	}
-
-	private FieldDeclaration convertToFieldDeclaration(org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDecl) {
-		VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(fieldDecl);
-		FieldDeclaration fieldDeclaration = this.ast.newFieldDeclaration(variableDeclarationFragment);
-		if (this.resolveBindings) {
-			recordNodes(variableDeclarationFragment, fieldDecl);
-			variableDeclarationFragment.resolveBinding();
-		}
-		fieldDeclaration.setSourceRange(fieldDecl.declarationSourceStart, fieldDecl.declarationEnd - fieldDecl.declarationSourceStart + 1);
-		Type type = convertType(fieldDecl.type);
-		setTypeForField(fieldDeclaration, type, variableDeclarationFragment.getExtraDimensions());
-		fieldDeclaration.setModifiers(fieldDecl.modifiers & org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers.AccJustFlag);
-		convert(fieldDecl.javadoc, fieldDeclaration);
-		return fieldDeclaration;
-	}
-
-	private VariableDeclarationStatement convertToVariableDeclarationStatement(org.eclipse.jdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
-		VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(localDeclaration);
-		VariableDeclarationStatement variableDeclarationStatement = this.ast.newVariableDeclarationStatement(variableDeclarationFragment);
-		if (this.resolveBindings) {
-			recordNodes(variableDeclarationFragment, localDeclaration);
-		}
-		variableDeclarationStatement.setSourceRange(localDeclaration.declarationSourceStart, localDeclaration.declarationSourceEnd - localDeclaration.declarationSourceStart + 1);
-		Type type = convertType(localDeclaration.type);
-		setTypeForVariableDeclarationStatement(variableDeclarationStatement, type, variableDeclarationFragment.getExtraDimensions());
-		variableDeclarationStatement.setModifiers(localDeclaration.modifiers & ~CompilerModifiers.AccBlankFinal);
-		return variableDeclarationStatement;
-	}
-	
-	private VariableDeclarationExpression convertToVariableDeclarationExpression(org.eclipse.jdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
-		VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(localDeclaration);
-		VariableDeclarationExpression variableDeclarationExpression = this.ast.newVariableDeclarationExpression(variableDeclarationFragment);
-		if (this.resolveBindings) {
-			recordNodes(variableDeclarationFragment, localDeclaration);
-		}
-		variableDeclarationExpression.setSourceRange(localDeclaration.declarationSourceStart, localDeclaration.declarationSourceEnd - localDeclaration.declarationSourceStart + 1);
-		Type type = convertType(localDeclaration.type);
-		setTypeForVariableDeclarationExpression(variableDeclarationExpression, type, variableDeclarationFragment.getExtraDimensions());
-		variableDeclarationExpression.setModifiers(localDeclaration.modifiers & ~CompilerModifiers.AccBlankFinal);
-		return variableDeclarationExpression;
-	}
-	
-	private void setTypeForField(FieldDeclaration fieldDeclaration, Type type, int extraDimension) {
-		if (extraDimension != 0) {
-			if (type.isArrayType()) {
-				ArrayType arrayType = (ArrayType) type;
-				int remainingDimensions = arrayType.getDimensions() - extraDimension;
-				if (remainingDimensions == 0)  {
-					// the dimensions are after the name so the type of the fieldDeclaration is a simpleType
-					Type elementType = arrayType.getElementType();
-					// cut the child loose from its parent (without creating garbage)
-					elementType.setParent(null, null);
-					this.ast.getBindingResolver().updateKey(type, elementType);
-					fieldDeclaration.setType(elementType);
+			if (currentNode instanceof TypeDeclaration
+				|| currentNode instanceof EnumDeclaration
+				|| currentNode instanceof AnnotationTypeDeclaration) {
+				org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDecl = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
+				if ((initializer.getModifiers() & Modifier.STATIC) != 0) {
+					return typeDecl.staticInitializerScope;
 				} else {
-					int start = type.getStartPosition();
-					int length = type.getLength();
-					ArrayType subarrayType = arrayType;
-					int index = extraDimension;
-					while (index > 0) {
-						subarrayType = (ArrayType) subarrayType.getComponentType();
-						index--;
-					}
-					int end = retrieveProperRightBracketPosition(remainingDimensions, start, start + length);
-					subarrayType.setSourceRange(start, end - start + 1);
-					// cut the child loose from its parent (without creating garbage)
-					subarrayType.setParent(null, null);
-					fieldDeclaration.setType(subarrayType);
-					updateInnerPositions(subarrayType, remainingDimensions);
-					this.ast.getBindingResolver().updateKey(type, subarrayType);
+					return typeDecl.initializerScope;
 				}
-			} else {
-				fieldDeclaration.setType(type);
 			}
-		} else {
-			if (type.isArrayType()) {
-				// update positions of the component types of the array type
-				int dimensions = ((ArrayType) type).getDimensions();
-				updateInnerPositions(type, dimensions);
+		} else if (currentNode instanceof FieldDeclaration) {
+			FieldDeclaration fieldDeclaration = (FieldDeclaration) currentNode;
+			while(!(currentNode instanceof AbstractTypeDeclaration)) {
+				currentNode = currentNode.getParent();
 			}
-			fieldDeclaration.setType(type);
-		}
-	}
-
-	private void updateInnerPositions(Type type, int dimensions) {
-		if (dimensions > 1) {
-			// need to set positions for intermediate array type see 42839
-			int start = type.getStartPosition();
-			int length = type.getLength();
-			Type currentComponentType = ((ArrayType) type).getComponentType();
-			int searchedDimension = dimensions - 1;
-			int rightBracketEndPosition = start;
-			while (currentComponentType.isArrayType()) {
-				rightBracketEndPosition = retrieveProperRightBracketPosition(searchedDimension, start, start + length);
-				currentComponentType.setSourceRange(start, rightBracketEndPosition - start + 1);
-				currentComponentType = ((ArrayType) currentComponentType).getComponentType();
-				searchedDimension--;
-			}		
-		}
-	}
-
-	private void setTypeForSingleVariableDeclaration(SingleVariableDeclaration singleVariableDeclaration, Type type, int extraDimension) {
-		if (extraDimension != 0) {
-			if (type.isArrayType()) {
-				ArrayType arrayType = (ArrayType) type;
-				int remainingDimensions = arrayType.getDimensions() - extraDimension;
-				if (remainingDimensions == 0)  {
-					// the dimensions are after the name so the type of the fieldDeclaration is a simpleType
-					Type elementType = arrayType.getElementType();
-					// cut the child loose from its parent (without creating garbage)
-					elementType.setParent(null, null);
-					this.ast.getBindingResolver().updateKey(type, elementType);
-					singleVariableDeclaration.setType(elementType);
+			if (currentNode instanceof TypeDeclaration
+					|| currentNode instanceof EnumDeclaration
+					|| currentNode instanceof AnnotationTypeDeclaration) {
+				org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDecl = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
+				if ((fieldDeclaration.getModifiers() & Modifier.STATIC) != 0) {
+					return typeDecl.staticInitializerScope;
 				} else {
-					int start = type.getStartPosition();
-					int length = type.getLength();
-					ArrayType subarrayType = arrayType;
-					int index = extraDimension;
-					while (index > 0) {
-						subarrayType = (ArrayType) subarrayType.getComponentType();
-						index--;
-					}
-					int end = retrieveProperRightBracketPosition(remainingDimensions, start, start + length);
-					subarrayType.setSourceRange(start, end - start + 1);
-					// cut the child loose from its parent (without creating garbage)
-					subarrayType.setParent(null, null);
-					updateInnerPositions(subarrayType, remainingDimensions);
-					singleVariableDeclaration.setType(subarrayType);
-					this.ast.getBindingResolver().updateKey(type, subarrayType);
+					return typeDecl.initializerScope;
 				}
-			} else {
-				singleVariableDeclaration.setType(type);
 			}
-		} else {
-			singleVariableDeclaration.setType(type);
 		}
+		AbstractMethodDeclaration abstractMethodDeclaration = (AbstractMethodDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
+		return abstractMethodDeclaration.scope;
 	}
 
-	private void setTypeForMethodDeclaration(MethodDeclaration methodDeclaration, Type type, int extraDimension) {
-		if (extraDimension != 0) {
-			if (type.isArrayType()) {
-				ArrayType arrayType = (ArrayType) type;
-				int remainingDimensions = arrayType.getDimensions() - extraDimension;
-				if (remainingDimensions == 0)  {
-					// the dimensions are after the name so the type of the fieldDeclaration is a simpleType
-					Type elementType = arrayType.getElementType();
-					// cut the child loose from its parent (without creating garbage)
-					elementType.setParent(null, null);
-					this.ast.getBindingResolver().updateKey(type, elementType);
-					methodDeclaration.setReturnType(elementType);
-				} else {
-					int start = type.getStartPosition();
-					int length = type.getLength();
-					ArrayType subarrayType = arrayType;
-					int index = extraDimension;
-					while (index > 0) {
-						subarrayType = (ArrayType) subarrayType.getComponentType();
-						index--;
+	protected void recordName(Name name, org.eclipse.jdt.internal.compiler.ast.ASTNode compilerNode) {
+		if (compilerNode != null) {
+			recordNodes(name, compilerNode);
+			if (compilerNode instanceof org.eclipse.jdt.internal.compiler.ast.TypeReference) {
+				org.eclipse.jdt.internal.compiler.ast.TypeReference typeRef = (org.eclipse.jdt.internal.compiler.ast.TypeReference) compilerNode;
+				if (name.isQualifiedName()) {
+					int count = 0;
+					SimpleName simpleName = null;
+					while (name.isQualifiedName()) {
+						simpleName = ((QualifiedName) name).getName();
+						recordNodes(simpleName, typeRef);
+						simpleName.index = count++;
+						name = ((QualifiedName) name).getQualifier();
+						name.index = count;
+						recordNodes(name, typeRef);
 					}
-					int end = retrieveProperRightBracketPosition(remainingDimensions, start, start + length);
-					subarrayType.setSourceRange(start, end - start + 1);
-					// cut the child loose from its parent (without creating garbage)
-					subarrayType.setParent(null, null);
-					updateInnerPositions(subarrayType, remainingDimensions);
-					methodDeclaration.setReturnType(subarrayType);
-					this.ast.getBindingResolver().updateKey(type, subarrayType);
-				}
-			} else {
-				methodDeclaration.setReturnType(type);
-			}
-		} else {
-			methodDeclaration.setReturnType(type);
-		}
-	}
-
-	private void setTypeForVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, Type type, int extraDimension) {
-		if (extraDimension != 0) {
-			if (type.isArrayType()) {
-				ArrayType arrayType = (ArrayType) type;
-				int remainingDimensions = arrayType.getDimensions() - extraDimension;
-				if (remainingDimensions == 0)  {
-					// the dimensions are after the name so the type of the fieldDeclaration is a simpleType
-					Type elementType = arrayType.getElementType();
-					// cut the child loose from its parent (without creating garbage)
-					elementType.setParent(null, null);
-					this.ast.getBindingResolver().updateKey(type, elementType);
-					variableDeclarationStatement.setType(elementType);
-				} else {
-					int start = type.getStartPosition();
-					int length = type.getLength();
-					ArrayType subarrayType = arrayType;
-					int index = extraDimension;
-					while (index > 0) {
-						subarrayType = (ArrayType) subarrayType.getComponentType();
-						index--;
-					}
-					int end = retrieveProperRightBracketPosition(remainingDimensions, start, start + length);
-					subarrayType.setSourceRange(start, end - start + 1);
-					// cut the child loose from its parent (without creating garbage)
-					subarrayType.setParent(null, null);
-					updateInnerPositions(subarrayType, remainingDimensions);
-					variableDeclarationStatement.setType(subarrayType);
-					this.ast.getBindingResolver().updateKey(type, subarrayType);
-				}
-			} else {
-				variableDeclarationStatement.setType(type);
-			}
-		} else {
-			variableDeclarationStatement.setType(type);
-		}
-	}
-
-	private void setTypeForVariableDeclarationExpression(VariableDeclarationExpression variableDeclarationExpression, Type type, int extraDimension) {
-		if (extraDimension != 0) {
-			if (type.isArrayType()) {
-				ArrayType arrayType = (ArrayType) type;
-				int remainingDimensions = arrayType.getDimensions() - extraDimension;
-				if (remainingDimensions == 0)  {
-					// the dimensions are after the name so the type of the fieldDeclaration is a simpleType
-					Type elementType = arrayType.getElementType();
-					// cut the child loose from its parent (without creating garbage)
-					elementType.setParent(null, null);
-					this.ast.getBindingResolver().updateKey(type, elementType);
-					variableDeclarationExpression.setType(elementType);
-				} else {
-					int start = type.getStartPosition();
-					int length = type.getLength();
-					ArrayType subarrayType = arrayType;
-					int index = extraDimension;
-					while (index > 0) {
-						subarrayType = (ArrayType) subarrayType.getComponentType();
-						index--;
-					}
-					int end = retrieveProperRightBracketPosition(remainingDimensions, start, start + length);
-					subarrayType.setSourceRange(start, end - start + 1);
-					// cut the child loose from its parent (without creating garbage)
-					subarrayType.setParent(null, null);
-					updateInnerPositions(subarrayType, remainingDimensions);
-					variableDeclarationExpression.setType(subarrayType);
-					this.ast.getBindingResolver().updateKey(type, subarrayType);
-				}
-			} else {
-				variableDeclarationExpression.setType(type);
-			}
-		} else {
-			variableDeclarationExpression.setType(type);
-		}
-	}
-
-	public void convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, BodyDeclaration bodyDeclaration) {
-		if (bodyDeclaration.getJavadoc() == null) {
-			if (javadoc != null) {
-				if (this.commentMapper == null || !this.commentMapper.hasSameTable(this.commentsTable)) {
-					this.commentMapper = new DefaultCommentMapper(this.commentsTable);
-				}
-				Comment comment = this.commentMapper.getComment(javadoc.sourceStart);
-				if (comment != null && comment.isDocComment() && comment.getParent() == null) {
-					Javadoc docComment = (Javadoc) comment;
-					if (this.resolveBindings) {
-						recordNodes(docComment, javadoc);
-						// resolve member and method references binding
-						Iterator tags = docComment.tags().listIterator();
-						while (tags.hasNext()) {
-							recordNodes(javadoc, (TagElement) tags.next());
-						}
-					}
-					bodyDeclaration.setJavadoc(docComment);
 				}
 			}
 		}
 	}
 	
-	private void recordNodes(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, TagElement tagElement) {
+	protected void recordNodes(ASTNode node, org.eclipse.jdt.internal.compiler.ast.ASTNode oldASTNode) {
+		this.ast.getBindingResolver().store(node, oldASTNode);
+	}
+	
+	protected void recordNodes(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, TagElement tagElement) {
 		Iterator fragments = tagElement.fragments().listIterator();
-		int size = tagElement.fragments().size();
-		int[] replaceIndex = new int[size];
-		int idx = 0;
 		while (fragments.hasNext()) {
 			ASTNode node = (ASTNode) fragments.next();
-			replaceIndex[idx] = 0;
 			if (node.getNodeType() == ASTNode.MEMBER_REF) {
 				MemberRef memberRef = (MemberRef) node;
 				Name name = memberRef.getName();
 				// get compiler node and record nodes
 				int start = name.getStartPosition();
 				org.eclipse.jdt.internal.compiler.ast.ASTNode compilerNode = javadoc.getNodeStartingAt(start);
-				if (compilerNode instanceof JavadocMessageSend) {
-					replaceIndex[idx] = 1;
-				}
 				if (compilerNode!= null) {
 					recordNodes(name, compilerNode);
 					recordNodes(node, compilerNode);
@@ -3139,72 +3399,20 @@
 				recordNodes(javadoc, (TagElement) node);
 			}
 		}
-		for (int i=0; i<size; i++) {
-			if (replaceIndex[i] == 1) {
-				MemberRef memberRef = (MemberRef) tagElement.fragments().remove(i);
-				MethodRef methodRef = this.ast.newMethodRef();
-				methodRef.setName((SimpleName)memberRef.getName().clone(this.ast));
-				if (memberRef.getQualifier() != null) {
-					methodRef.setQualifier((Name)memberRef.getQualifier().clone(this.ast));
-				}
-				methodRef.setSourceRange(memberRef.getStartPosition(), memberRef.getLength());
-				tagElement.fragments().add(i, methodRef);
-			}
-		}
 	}
 	
-	private void recordName(Name name, org.eclipse.jdt.internal.compiler.ast.ASTNode compilerNode) {
-		if (compilerNode != null) {
-			recordNodes(name, compilerNode);
-			if (compilerNode instanceof org.eclipse.jdt.internal.compiler.ast.TypeReference) {
-				org.eclipse.jdt.internal.compiler.ast.TypeReference typeRef = (org.eclipse.jdt.internal.compiler.ast.TypeReference) compilerNode;
-				if (name.isQualifiedName()) {
-					int count = 0;
-					SimpleName simpleName = null;
-					while (name.isQualifiedName()) {
-						simpleName = ((QualifiedName) name).getName();
-						recordNodes(simpleName, typeRef);
-						simpleName.index = count++;
-						name = ((QualifiedName) name).getQualifier();
-						name.index = count;
-						recordNodes(name, typeRef);
-					}
-				}
-			}
+	protected void recordPendingNameScopeResolution(Name name) {
+		if (this.pendingNameScopeResolution == null) {
+			this.pendingNameScopeResolution = new HashSet();
 		}
-	}
-
-
-	private Comment createComment(int[] positions) {
-		// Create comment node
-		Comment comment = null;
-		int start = positions[0];
-		int end = positions[1];
-		if (positions[1]>0) { // Javadoc comments have positive end position
-			this.ast.newJavadoc();
-			Javadoc docComment = this.docParser.parse(positions);
-			if (docComment == null) return null;
-			comment = docComment;
-		} else {
-			end = -end;
-			if (positions[0]>0) { // Block comment have positive start position
-				comment = this.ast.newBlockComment();
-			} else { // Line comment have negative start and end position
-				start = -start;
-				comment = this.ast.newLineComment();
-			}
-			comment.setSourceRange(start, end - start);
-		}
-		return comment;
-	}
-
-	void propagateErrors(ASTNode astNode, IProblem[] problems) {
-		ASTSyntaxErrorPropagator syntaxErrorPropagator = new ASTSyntaxErrorPropagator(problems);
-		astNode.accept(syntaxErrorPropagator);
+		this.pendingNameScopeResolution.add(name);
 	}
 	
-	private void recordNodes(ASTNode node, org.eclipse.jdt.internal.compiler.ast.ASTNode oldASTNode) {
-		this.ast.getBindingResolver().store(node, oldASTNode);
+	protected void recordPendingThisExpressionScopeResolution(ThisExpression thisExpression) {
+		if (this.pendingThisExpressionScopeResolution == null) {
+			this.pendingThisExpressionScopeResolution = new HashSet();
+		}
+		this.pendingThisExpressionScopeResolution.add(thisExpression);
 	}
 	
 	/**
@@ -3254,84 +3462,11 @@
 			// ignore
 		}
 	}
-	
-	private void adjustSourcePositionsForParent(org.eclipse.jdt.internal.compiler.ast.Expression expression) {
-		int start = expression.sourceStart;
-		int end = expression.sourceEnd;
-		int leftParentCount = 1;
-		int rightParentCount = 0;
-		this.scanner.resetTo(start, end);
-		try {
-			int token = this.scanner.getNextToken();
-			expression.sourceStart = this.scanner.currentPosition;
-			boolean stop = false;
-			while (!stop && ((token  = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF)) {
-				switch(token) {
-					case TerminalTokens.TokenNameLPAREN:
-						leftParentCount++;
-						break;
-					case TerminalTokens.TokenNameRPAREN:
-						rightParentCount++;
-						if (rightParentCount == leftParentCount) {
-							// we found the matching parenthesis
-							stop = true;
-						}
-				}
-			}
-			expression.sourceEnd = this.scanner.startPosition - 1;
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-	}
-
-	private void retrieveIdentifierAndSetPositions(int start, int end, Name name) {
-		this.scanner.resetTo(start, end);
-		int token;
-		try {
-			while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF)  {
-				if (token == TerminalTokens.TokenNameIdentifier) {
-					int startName = this.scanner.startPosition;
-					int endName = this.scanner.currentPosition - 1;
-					name.setSourceRange(startName, endName - startName + 1);
-					return;
-				}
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-	}
-	
-	/**
-	 * Remove potential trailing comment by settings the source end on the closing parenthesis
-	 */
-	private void removeTrailingCommentFromExpressionEndingWithAParen(ASTNode node) {
-		int start = node.getStartPosition();
-		this.scanner.resetTo(start, start + node.getLength());
-		int token;
-		int parenCounter = 0;
-		try {
-			while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF)  {
-				switch(token) {
-					case TerminalTokens.TokenNameLPAREN :
-						parenCounter++;
-						break;
-					case TerminalTokens.TokenNameRPAREN :
-						parenCounter--;
-						if (parenCounter == 0) {
-							int end = this.scanner.currentPosition - 1;
-							node.setSourceRange(start, end - start + 1);
-						}
-				}
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-	}
 
 	/**
 	 * Remove potential trailing comment by settings the source end on the closing parenthesis
 	 */
-	private void removeLeadingAndTrailingCommentsFromLiteral(ASTNode node) {
+	protected void removeLeadingAndTrailingCommentsFromLiteral(ASTNode node) {
 		int start = node.getStartPosition();
 		this.scanner.resetTo(start, start + node.getLength());
 		int token;
@@ -3360,116 +3495,1321 @@
 		}
 	}
 	
-	private void recordPendingThisExpressionScopeResolution(ThisExpression thisExpression) {
-		if (this.pendingThisExpressionScopeResolution == null) {
-			this.pendingThisExpressionScopeResolution = new HashSet();
-		}
-		this.pendingThisExpressionScopeResolution.add(thisExpression);
-	}
-	
-	private void recordPendingNameScopeResolution(Name name) {
-		if (this.pendingNameScopeResolution == null) {
-			this.pendingNameScopeResolution = new HashSet();
-		}
-		this.pendingNameScopeResolution.add(name);
-	}
-	
-	private void lookupForScopes() {
-		if (this.pendingNameScopeResolution != null) {
-			for (Iterator iterator = this.pendingNameScopeResolution.iterator(); iterator.hasNext(); ) {
-				Name name = (Name) iterator.next();
-				this.ast.getBindingResolver().recordScope(name, lookupScope(name));
+	/**
+	 * Remove potential trailing comment by settings the source end on the closing parenthesis
+	 */
+	protected void removeTrailingCommentFromExpressionEndingWithAParen(ASTNode node) {
+		int start = node.getStartPosition();
+		this.scanner.resetTo(start, start + node.getLength());
+		int token;
+		int parenCounter = 0;
+		try {
+			while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF)  {
+				switch(token) {
+					case TerminalTokens.TokenNameLPAREN :
+						parenCounter++;
+						break;
+					case TerminalTokens.TokenNameRPAREN :
+						parenCounter--;
+						if (parenCounter == 0) {
+							int end = this.scanner.currentPosition - 1;
+							node.setSourceRange(start, end - start + 1);
+						}
+				}
 			}
+		} catch(InvalidInputException e) {
+			// ignore
 		}
-		if (this.pendingThisExpressionScopeResolution != null) {
-			for (Iterator iterator = this.pendingThisExpressionScopeResolution.iterator(); iterator.hasNext(); ) {
-				ThisExpression thisExpression = (ThisExpression) iterator.next();
-				this.ast.getBindingResolver().recordScope(thisExpression, lookupScope(thisExpression));
-			}
-		}
-		
-	}
-	
-	private BlockScope lookupScope(ASTNode node) {
-		ASTNode currentNode = node;
-		while(currentNode != null
-			&&!(currentNode instanceof MethodDeclaration)
-			&& !(currentNode instanceof Initializer)
-			&& !(currentNode instanceof FieldDeclaration)) {
-			currentNode = currentNode.getParent();
-		}
-		if (currentNode == null) {
-			return null;
-		}
-		if (currentNode instanceof Initializer) {
-			Initializer initializer = (Initializer) currentNode;
-			while(!(currentNode instanceof TypeDeclaration)) {
-				currentNode = currentNode.getParent();
-			}
-			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDecl = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
-			if ((initializer.getModifiers() & Modifier.STATIC) != 0) {
-				return typeDecl.staticInitializerScope;
-			} else {
-				return typeDecl.initializerScope;
-			}
-		} else if (currentNode instanceof FieldDeclaration) {
-			FieldDeclaration fieldDeclaration = (FieldDeclaration) currentNode;
-			while(!(currentNode instanceof TypeDeclaration)) {
-				currentNode = currentNode.getParent();
-			}
-			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDecl = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
-			if ((fieldDeclaration.getModifiers() & Modifier.STATIC) != 0) {
-				return typeDecl.staticInitializerScope;
-			} else {
-				return typeDecl.initializerScope;
-			}
-		}
-		AbstractMethodDeclaration abstractMethodDeclaration = (AbstractMethodDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
-		return abstractMethodDeclaration.scope;
 	}
 
-	private InfixExpression.Operator getOperatorFor(int operatorID) {
-		switch (operatorID) {
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL :
-				return InfixExpression.Operator.EQUALS;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LESS_EQUAL :
-				return InfixExpression.Operator.LESS_EQUALS;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.GREATER_EQUAL :
-				return InfixExpression.Operator.GREATER_EQUALS;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.NOT_EQUAL :
-				return InfixExpression.Operator.NOT_EQUALS;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LEFT_SHIFT :
-				return InfixExpression.Operator.LEFT_SHIFT;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.RIGHT_SHIFT :
-				return InfixExpression.Operator.RIGHT_SHIFT_SIGNED;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.UNSIGNED_RIGHT_SHIFT :
-				return InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.OR_OR :
-				return InfixExpression.Operator.CONDITIONAL_OR;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.AND_AND :
-				return InfixExpression.Operator.CONDITIONAL_AND;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
-				return InfixExpression.Operator.PLUS;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
-				return InfixExpression.Operator.MINUS;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.REMAINDER :
-				return InfixExpression.Operator.REMAINDER;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.XOR :
-				return InfixExpression.Operator.XOR;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.AND :
-				return InfixExpression.Operator.AND;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MULTIPLY :
-				return InfixExpression.Operator.TIMES;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.OR :
-				return InfixExpression.Operator.OR;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.DIVIDE :
-				return InfixExpression.Operator.DIVIDE;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.GREATER :
-				return InfixExpression.Operator.GREATER;
-			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LESS :
-				return InfixExpression.Operator.LESS;
+	/**
+	 * This method is used to retrieve the end position of the block.
+	 * @return int the dimension found, -1 if none
+	 */
+	protected int retrieveClosingAngleBracketPosition(int start) {
+		this.scanner.resetTo(start, this.scanner.eofPosition);
+		this.scanner.returnOnlyGreater = true;
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameGREATER:
+						return this.scanner.currentPosition - 1;
+					default:
+						return start;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
 		}
-		return null;
+		this.scanner.returnOnlyGreater = false;
+		return start;
+	}
+
+	/**
+	 * This method is used to set the right end position for expression
+	 * statement. The actual AST nodes don't include the trailing semicolon.
+	 * This method fixes the length of the corresponding node.
+	 */
+	protected void retrieveColonPosition(ASTNode node) {
+		int start = node.getStartPosition();
+		int length = node.getLength();
+		int end = start + length;
+		this.scanner.resetTo(end, this.compilationUnitSource.length);
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameCOLON:
+						node.setSourceRange(start, this.scanner.currentPosition - start);
+						return;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+	}
+	/**
+	 * This method is used to retrieve the start position of the Ellipsis
+	 */
+	protected int retrieveEllipsisStartPosition(int start, int end) {
+		this.scanner.resetTo(start, end);
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameELLIPSIS:
+						return this.scanner.startPosition - 1;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return -1;
+	
+	}
+	/**
+	 * This method is used to retrieve the end position of the block.
+	 * @return int the dimension found, -1 if none
+	 */
+	protected int retrieveEndBlockPosition(int start, int end) {
+		this.scanner.resetTo(start, end);
+		int count = 0;
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameLBRACE://110
+						count++;
+						break;
+					case TerminalTokens.TokenNameRBRACE://95
+						count--;
+						if (count == 0) {
+							return this.scanner.currentPosition - 1;
+						}
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return -1;
+	}
+
+	protected int retrieveEndingSemiColonPosition(int start, int end) {
+		int count = 0;
+		this.scanner.resetTo(start, end);
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameSEMICOLON:
+						if (count == 0) {
+							return this.scanner.currentPosition - 1;
+						}
+						break;
+					case TerminalTokens.TokenNameLBRACE :
+						count++;
+						break;
+					case TerminalTokens.TokenNameRBRACE :
+						count--;
+						break;
+					case TerminalTokens.TokenNameLPAREN :
+						count++;
+						break;
+					case TerminalTokens.TokenNameRPAREN :
+						count--;
+						break;
+					case TerminalTokens.TokenNameLBRACKET :
+						count++;
+						break;
+					case TerminalTokens.TokenNameRBRACKET :
+						count--;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return -1;
+	}
+
+	/**
+	 * This method is used to retrieve the ending position for a type declaration when the dimension is right after the type
+	 * name.
+	 * For example:
+	 *    int[] i; => return 5, but int i[] => return -1;
+	 * @return int the dimension found
+	 */
+	protected int retrieveEndOfDimensionsPosition(int start, int end) {
+		this.scanner.resetTo(start, end);
+		int foundPosition = -1;
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameLBRACKET:
+					case TerminalTokens.TokenNameCOMMENT_BLOCK:
+					case TerminalTokens.TokenNameCOMMENT_JAVADOC:
+					case TerminalTokens.TokenNameCOMMENT_LINE:
+						break;
+					case TerminalTokens.TokenNameRBRACKET://166
+						foundPosition = this.scanner.currentPosition - 1;
+						break;
+					default:
+						return foundPosition;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return foundPosition;
+	}
+
+	/**
+	 * This method is used to retrieve the position just before the left bracket.
+	 * @return int the dimension found, -1 if none
+	 */
+	protected int retrieveEndOfElementTypeNamePosition(int start, int end) {
+		this.scanner.resetTo(start, end);
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameIdentifier:
+					case TerminalTokens.TokenNamebyte:
+					case TerminalTokens.TokenNamechar:
+					case TerminalTokens.TokenNamedouble:
+					case TerminalTokens.TokenNamefloat:
+					case TerminalTokens.TokenNameint:
+					case TerminalTokens.TokenNamelong:
+					case TerminalTokens.TokenNameshort:
+						return this.scanner.currentPosition - 1;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return -1;
+	}
+
+	/**
+	 * This method is used to retrieve the position after the right parenthesis.
+	 * @return int the position found
+	 */
+	protected int retrieveEndOfRightParenthesisPosition(int start, int end) {
+		this.scanner.resetTo(start, end);
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameRPAREN:
+						return this.scanner.currentPosition;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return -1;
+	}
+
+	/**
+	 * This method is used to retrieve the array dimension declared after the
+	 * name of a local or a field declaration.
+	 * For example:
+	 *    int i, j[] = null, k[][] = {{}};
+	 *    It should return 0 for i, 1 for j and 2 for k.
+	 * @return int the dimension found
+	 */
+	protected int retrieveExtraDimension(int start, int end) {
+		this.scanner.resetTo(start, end);
+		int dimensions = 0;
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameRBRACKET://166 
+						dimensions++;
+						break;
+					case TerminalTokens.TokenNameLBRACE ://90						
+					case TerminalTokens.TokenNameCOMMA ://90
+					case TerminalTokens.TokenNameEQUAL ://167
+					case TerminalTokens.TokenNameSEMICOLON ://64
+					case TerminalTokens.TokenNameRPAREN : //86
+						return dimensions;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return dimensions;
+	}
+
+	protected void retrieveIdentifierAndSetPositions(int start, int end, Name name) {
+		this.scanner.resetTo(start, end);
+		int token;
+		try {
+			while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF)  {
+				if (token == TerminalTokens.TokenNameIdentifier) {
+					int startName = this.scanner.startPosition;
+					int endName = this.scanner.currentPosition - 1;
+					name.setSourceRange(startName, endName - startName + 1);
+					return;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+	}
+	
+	/**
+	 * This method is used to retrieve the start position of the block.
+	 * @return int the dimension found, -1 if none
+	 */
+	protected int retrieveIdentifierEndPosition(int start, int end) {
+		this.scanner.resetTo(start, end);
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameIdentifier://110
+						return this.scanner.getCurrentTokenEndPosition();
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return -1;
+	}	
+
+	/**
+	 * This method is used to retrieve position before the next comma or semi-colon.
+	 * @return int the position found.
+	 */
+	protected int retrievePositionBeforeNextCommaOrSemiColon(int start, int end) {
+		this.scanner.resetTo(start, end);
+		int braceCounter = 0;
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameLBRACE :
+						braceCounter++;
+						break;
+					case TerminalTokens.TokenNameRBRACE :
+						braceCounter--;
+						break;
+					case TerminalTokens.TokenNameLPAREN :
+						braceCounter++;
+						break;
+					case TerminalTokens.TokenNameRPAREN :
+						braceCounter--;
+						break;
+					case TerminalTokens.TokenNameLBRACKET :
+						braceCounter++;
+						break;
+					case TerminalTokens.TokenNameRBRACKET :
+						braceCounter--;
+						break;
+					case TerminalTokens.TokenNameCOMMA :
+					case TerminalTokens.TokenNameSEMICOLON :
+						if (braceCounter == 0) {
+							return this.scanner.startPosition - 1;
+						}
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return -1;
+	}
+
+	protected int retrieveProperRightBracketPosition(int bracketNumber, int start) {
+		this.scanner.resetTo(start, this.compilationUnitSource.length);
+		try {
+			int token, count = 0;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameRBRACKET:
+						count++;
+						if (count == bracketNumber) {
+							return this.scanner.currentPosition - 1;
+						}
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return -1;
+	}
+
+	/**
+	 * This method is used to retrieve position before the next right brace or semi-colon.
+	 * @return int the position found.
+	 */
+	protected int retrieveRightBraceOrSemiColonPosition(int start, int end) {
+		this.scanner.resetTo(start, end);
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameRBRACE :
+						return this.scanner.currentPosition - 1;
+					case TerminalTokens.TokenNameSEMICOLON :
+						return this.scanner.currentPosition - 1;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return -1;
+	}
+
+	/**
+	 * This method is used to retrieve position before the next right brace or semi-colon.
+	 * @return int the position found.
+	 */
+	protected int retrieveRightBrace(int start, int end) {
+		this.scanner.resetTo(start, end);
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameRBRACE :
+						return this.scanner.currentPosition - 1;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return -1;
+	}
+	
+	/**
+	 * This method is used to retrieve the position of the right bracket.
+	 * @return int the dimension found, -1 if none
+	 */
+	protected int retrieveRightBracketPosition(int start, int end) {
+		this.scanner.resetTo(start, end);
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameRBRACKET:
+						return this.scanner.currentPosition - 1;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return -1;
+	}
+	
+	/*
+	 * This method is used to set the right end position for expression
+	 * statement. The actual AST nodes don't include the trailing semicolon.
+	 * This method fixes the length of the corresponding node.
+	 */
+	protected void retrieveSemiColonPosition(ASTNode node) {
+		int start = node.getStartPosition();
+		int length = node.getLength();
+		int end = start + length;
+		int count = 0;
+		this.scanner.resetTo(end, this.compilationUnitSource.length);
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameSEMICOLON:
+						if (count == 0) {
+							node.setSourceRange(start, this.scanner.currentPosition - start);
+							return;
+						}
+						break;
+					case TerminalTokens.TokenNameLBRACE :
+						count++;
+						break;
+					case TerminalTokens.TokenNameRBRACE :
+						count--;
+						break;
+					case TerminalTokens.TokenNameLPAREN :
+						count++;
+						break;
+					case TerminalTokens.TokenNameRPAREN :
+						count--;
+						break;
+					case TerminalTokens.TokenNameLBRACKET :
+						count++;
+						break;
+					case TerminalTokens.TokenNameRBRACKET :
+						count--;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+	}
+	
+	/**
+	 * This method is used to retrieve the start position of the block.
+	 * @return int the dimension found, -1 if none
+	 */
+	protected int retrieveStartBlockPosition(int start, int end) {
+		this.scanner.resetTo(start, end);
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameLBRACE://110
+						return this.scanner.startPosition;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return -1;
+	}
+
+	/**
+	 * This method is used to retrieve the starting position of the catch keyword.
+	 * @return int the dimension found, -1 if none
+	 */
+	protected int retrieveStartingCatchPosition(int start, int end) {
+		this.scanner.resetTo(start, end);
+		try {
+			int token;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNamecatch://225
+						return this.scanner.startPosition;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return -1;
+	}
+	
+	public void setAST(AST ast) {
+		this.ast = ast;
+		this.docParser = new DocCommentParser(this.ast, this.scanner, this.insideComments);
+	}
+
+	protected void setModifiers(AnnotationTypeDeclaration typeDecl, org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+		this.scanner.resetTo(typeDeclaration.declarationSourceStart, typeDeclaration.sourceStart);
+		this.setModifiers(typeDecl, typeDeclaration.annotations);
+	}
+	
+	protected void setModifiers(AnnotationTypeMemberDeclaration annotationTypeMemberDecl, org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration annotationTypeMemberDeclaration) {
+		this.scanner.resetTo(annotationTypeMemberDeclaration.declarationSourceStart, annotationTypeMemberDeclaration.sourceStart);
+		this.setModifiers(annotationTypeMemberDecl, annotationTypeMemberDeclaration.annotations);
+	}
+
+	/**
+	 * @param bodyDeclaration
+	 */
+	protected void setModifiers(BodyDeclaration bodyDeclaration, org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations) {
+		try {
+			int token;
+			int indexInAnnotations = 0;
+			int eofPosition = this.scanner.eofPosition;
+			while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				IExtendedModifier modifier = null;
+				switch(token) {
+					case TerminalTokens.TokenNameabstract:
+						modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+						break;
+					case TerminalTokens.TokenNamepublic:
+						modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+						break;
+					case TerminalTokens.TokenNamestatic:
+						modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+						break;
+					case TerminalTokens.TokenNameprotected:
+						modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+						break;
+					case TerminalTokens.TokenNameprivate:
+						modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+						break;
+					case TerminalTokens.TokenNamefinal:
+						modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+						break;
+					case TerminalTokens.TokenNamenative:
+						modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+						break;
+					case TerminalTokens.TokenNamesynchronized:
+						modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+						break;
+					case TerminalTokens.TokenNametransient:
+						modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+						break;
+					case TerminalTokens.TokenNamevolatile:
+						modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+						break;
+					case TerminalTokens.TokenNamestrictfp:
+						modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD);
+						break;
+					case TerminalTokens.TokenNameAT :
+						// we have an annotation
+						if (annotations != null && indexInAnnotations < annotations.length) {
+							org.eclipse.jdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++];
+							modifier = convert(annotation);
+							this.scanner.resetTo(annotation.declarationSourceEnd + 1, eofPosition);
+						}
+						break;
+					case TerminalTokens.TokenNameCOMMENT_BLOCK :
+					case TerminalTokens.TokenNameCOMMENT_LINE :
+					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+						break;
+					default :
+						return;
+				}
+				if (modifier != null) {
+					bodyDeclaration.modifiers().add(modifier);
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+	}
+	
+	
+	protected void setModifiers(EnumDeclaration enumDeclaration, org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enumDeclaration2) {
+		this.scanner.resetTo(enumDeclaration2.declarationSourceStart, enumDeclaration2.sourceStart);
+		this.setModifiers(enumDeclaration, enumDeclaration2.annotations);
+	}
+	
+	/**
+	 * @param fieldDeclaration
+	 * @param fieldDecl
+	 */
+	protected void setModifiers(FieldDeclaration fieldDeclaration, org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDecl) {
+		switch(this.ast.apiLevel) {
+			case AST.JLS2 :
+				fieldDeclaration.setModifiers(fieldDecl.modifiers & CompilerModifiers.AccJustFlag);
+				if (fieldDecl.annotations != null) {
+					fieldDeclaration.setFlags(fieldDeclaration.getFlags() | ASTNode.MALFORMED);
+				}
+				break;
+			case AST.JLS3 :
+				this.scanner.resetTo(fieldDecl.declarationSourceStart, fieldDecl.sourceStart);
+				this.setModifiers(fieldDeclaration, fieldDecl.annotations);
+		}
+	}
+	
+	/**
+	 * @param initializer
+	 * @param oldInitializer
+	 */
+	protected void setModifiers(Initializer initializer, org.eclipse.jdt.internal.compiler.ast.Initializer oldInitializer) {
+		switch(this.ast.apiLevel) {
+			case AST.JLS2: 
+				initializer.setModifiers(oldInitializer.modifiers & CompilerModifiers.AccJustFlag);
+				if (oldInitializer.annotations != null) {
+					initializer.setFlags(initializer.getFlags() | ASTNode.MALFORMED);
+				}
+				break;
+			case AST.JLS3 :
+				this.scanner.resetTo(oldInitializer.declarationSourceStart, oldInitializer.bodyStart);
+				this.setModifiers(initializer, oldInitializer.annotations);
+		}
+	}
+	/**
+	 * @param methodDecl
+	 * @param methodDeclaration
+	 */
+	protected void setModifiers(MethodDeclaration methodDecl, AbstractMethodDeclaration methodDeclaration) {
+		switch(this.ast.apiLevel) {
+			case AST.JLS2 :
+				methodDecl.setModifiers(methodDeclaration.modifiers & CompilerModifiers.AccJustFlag);
+				if (methodDeclaration.annotations != null) {
+					methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED);
+				}
+				break;
+			case AST.JLS3 :
+				this.scanner.resetTo(methodDeclaration.declarationSourceStart, methodDeclaration.sourceStart);
+				this.setModifiers(methodDecl, methodDeclaration.annotations);
+		}
+	}
+
+	/**
+	 * @param variableDecl
+	 * @param argument
+	 */
+	protected void setModifiers(SingleVariableDeclaration variableDecl, Argument argument) {
+		switch(this.ast.apiLevel) {
+			case AST.JLS2 :
+				variableDecl.setModifiers(argument.modifiers & CompilerModifiers.AccJustFlag);
+				if (argument.annotations != null) {
+					variableDecl.setFlags(variableDecl.getFlags() | ASTNode.MALFORMED);
+				}
+				break;
+			case AST.JLS3 :
+				this.scanner.resetTo(argument.declarationSourceStart, argument.sourceStart);
+				org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations = argument.annotations;
+				int indexInAnnotations = 0;
+				try {
+					int token;
+					while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+						IExtendedModifier modifier = null;
+						switch(token) {
+							case TerminalTokens.TokenNameabstract:
+								modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamepublic:
+								modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamestatic:
+								modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+								break;
+							case TerminalTokens.TokenNameprotected:
+								modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+								break;
+							case TerminalTokens.TokenNameprivate:
+								modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamefinal:
+								modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamenative:
+								modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamesynchronized:
+								modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+								break;
+							case TerminalTokens.TokenNametransient:
+								modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamevolatile:
+								modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamestrictfp:
+								modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD);
+								break;
+							case TerminalTokens.TokenNameAT :
+								// we have an annotation
+								if (annotations != null && indexInAnnotations < annotations.length) {
+									org.eclipse.jdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++];
+									modifier = convert(annotation);
+									this.scanner.resetTo(annotation.declarationSourceEnd + 1, this.scanner.eofPosition);
+								}
+						}
+						if (modifier != null) {
+							variableDecl.modifiers().add(modifier);
+						}
+					}
+				} catch(InvalidInputException e) {
+					// ignore
+				}
+		}
+	}
+	
+	protected void setModifiers(SingleVariableDeclaration variableDecl, LocalDeclaration localDeclaration) {
+		switch(this.ast.apiLevel) {
+		case AST.JLS2 :
+			variableDecl.setModifiers(localDeclaration.modifiers & CompilerModifiers.AccJustFlag);
+			if (localDeclaration.annotations != null) {
+				variableDecl.setFlags(variableDecl.getFlags() | ASTNode.MALFORMED);
+			}
+			break;
+		case AST.JLS3 :
+			this.scanner.resetTo(localDeclaration.declarationSourceStart, localDeclaration.sourceStart);
+			org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations = localDeclaration.annotations;
+			int indexInAnnotations = 0;
+			try {
+				int token;
+				while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+					IExtendedModifier modifier = null;
+					switch(token) {
+						case TerminalTokens.TokenNameabstract:
+							modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+							break;
+						case TerminalTokens.TokenNamepublic:
+							modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+							break;
+						case TerminalTokens.TokenNamestatic:
+							modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+							break;
+						case TerminalTokens.TokenNameprotected:
+							modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+							break;
+						case TerminalTokens.TokenNameprivate:
+							modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+							break;
+						case TerminalTokens.TokenNamefinal:
+							modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+							break;
+						case TerminalTokens.TokenNamenative:
+							modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+							break;
+						case TerminalTokens.TokenNamesynchronized:
+							modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+							break;
+						case TerminalTokens.TokenNametransient:
+							modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+							break;
+						case TerminalTokens.TokenNamevolatile:
+							modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+							break;
+						case TerminalTokens.TokenNamestrictfp:
+							modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD);
+							break;
+						case TerminalTokens.TokenNameAT :
+							// we have an annotation
+							if (annotations != null && indexInAnnotations < annotations.length) {
+								org.eclipse.jdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++];
+								modifier = convert(annotation);
+								this.scanner.resetTo(annotation.declarationSourceEnd + 1, this.scanner.eofPosition);
+							}
+					}
+					if (modifier != null) {
+						variableDecl.modifiers().add(modifier);
+					}
+				}
+			} catch(InvalidInputException e) {
+				// ignore
+			}
+		}
+	}
+
+	/**
+	 * @param typeDecl
+	 * @param typeDeclaration
+	 */
+	protected void setModifiers(TypeDeclaration typeDecl, org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+		switch(this.ast.apiLevel) { 
+			case AST.JLS2 :
+				int modifiers = typeDeclaration.modifiers;
+				modifiers &= ~IConstants.AccInterface; // remove AccInterface flags
+				modifiers &= CompilerModifiers.AccJustFlag;
+				typeDecl.setModifiers(modifiers);
+				if (typeDeclaration.annotations != null) {
+					typeDecl.setFlags(typeDecl.getFlags() | ASTNode.MALFORMED);
+				}
+				break;
+			case AST.JLS3 :
+				this.scanner.resetTo(typeDeclaration.declarationSourceStart, typeDeclaration.sourceStart);
+				this.setModifiers(typeDecl, typeDeclaration.annotations);
+		}
+	}
+	
+	/**
+	 * @param variableDeclarationExpression
+	 * @param localDeclaration
+	 */
+	protected void setModifiers(VariableDeclarationExpression variableDeclarationExpression, LocalDeclaration localDeclaration) {
+		switch(this.ast.apiLevel) {
+			case AST.JLS2 :
+				int modifiers = localDeclaration.modifiers & CompilerModifiers.AccJustFlag;
+				modifiers &= ~CompilerModifiers.AccBlankFinal;
+				variableDeclarationExpression.setModifiers(modifiers);
+				if (localDeclaration.annotations != null) {
+					variableDeclarationExpression.setFlags(variableDeclarationExpression.getFlags() | ASTNode.MALFORMED);
+				}
+				break;
+			case AST.JLS3 :
+				this.scanner.resetTo(localDeclaration.declarationSourceStart, localDeclaration.sourceStart);
+				org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations = localDeclaration.annotations;
+				int indexInAnnotations = 0;
+				try {
+					int token;
+					while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+						IExtendedModifier modifier = null;
+						switch(token) {
+							case TerminalTokens.TokenNameabstract:
+								modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamepublic:
+								modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamestatic:
+								modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+								break;
+							case TerminalTokens.TokenNameprotected:
+								modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+								break;
+							case TerminalTokens.TokenNameprivate:
+								modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamefinal:
+								modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamenative:
+								modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamesynchronized:
+								modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+								break;
+							case TerminalTokens.TokenNametransient:
+								modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamevolatile:
+								modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamestrictfp:
+								modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD);
+								break;
+							case TerminalTokens.TokenNameAT :
+								// we have an annotation
+								if (annotations != null && indexInAnnotations < annotations.length) {
+									org.eclipse.jdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++];
+									modifier = convert(annotation);
+									this.scanner.resetTo(annotation.declarationSourceEnd + 1, this.scanner.eofPosition);
+								}
+						}
+						if (modifier != null) {
+							variableDeclarationExpression.modifiers().add(modifier);
+						}
+					}
+				} catch(InvalidInputException e) {
+					// ignore
+				}
+		}		
+	}
+
+	/**
+	 * @param variableDeclarationStatement
+	 * @param localDeclaration
+	 */
+	protected void setModifiers(VariableDeclarationStatement variableDeclarationStatement, LocalDeclaration localDeclaration) {
+		switch(this.ast.apiLevel) {
+			case AST.JLS2 :
+				int modifiers = localDeclaration.modifiers & CompilerModifiers.AccJustFlag;
+				modifiers &= ~CompilerModifiers.AccBlankFinal;
+				variableDeclarationStatement.setModifiers(modifiers);
+				if (localDeclaration.annotations != null) {
+					variableDeclarationStatement.setFlags(variableDeclarationStatement.getFlags() | ASTNode.MALFORMED);
+				}
+				break;
+			case AST.JLS3 :
+				this.scanner.resetTo(localDeclaration.declarationSourceStart, localDeclaration.sourceStart);
+				org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations = localDeclaration.annotations;
+				int indexInAnnotations = 0;
+				try {
+					int token;
+					while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+						IExtendedModifier modifier = null;
+						switch(token) {
+							case TerminalTokens.TokenNameabstract:
+								modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamepublic:
+								modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamestatic:
+								modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+								break;
+							case TerminalTokens.TokenNameprotected:
+								modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+								break;
+							case TerminalTokens.TokenNameprivate:
+								modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamefinal:
+								modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamenative:
+								modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamesynchronized:
+								modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+								break;
+							case TerminalTokens.TokenNametransient:
+								modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamevolatile:
+								modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+								break;
+							case TerminalTokens.TokenNamestrictfp:
+								modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD);
+								break;
+							case TerminalTokens.TokenNameAT :
+								// we have an annotation
+								if (annotations != null && indexInAnnotations < annotations.length) {
+									org.eclipse.jdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++];
+									modifier = convert(annotation);
+									this.scanner.resetTo(annotation.declarationSourceEnd + 1, this.scanner.eofPosition);
+								}
+						}
+						if (modifier != null) {
+							variableDeclarationStatement.modifiers().add(modifier);
+						}
+					}
+				} catch(InvalidInputException e) {
+					// ignore
+				}
+		}				
+	}
+
+	protected QualifiedName setQualifiedNameNameAndSourceRanges(char[][] typeName, long[] positions, org.eclipse.jdt.internal.compiler.ast.ASTNode node) {
+		int length = typeName.length;
+		SimpleName firstToken = this.ast.newSimpleName(new String(typeName[0]));
+		firstToken.index = length - 1;
+		int start0 = (int)(positions[0]>>>32);
+		int start = start0;
+		int end = (int)(positions[0] & 0xFFFFFFFF);
+		firstToken.setSourceRange(start, end - start + 1);
+		SimpleName secondToken = this.ast.newSimpleName(new String(typeName[1]));
+		secondToken.index = length - 2;
+		start = (int)(positions[1]>>>32);
+		end = (int)(positions[1] & 0xFFFFFFFF);
+		secondToken.setSourceRange(start, end - start + 1);
+		QualifiedName qualifiedName = this.ast.newQualifiedName(firstToken, secondToken);
+		if (this.resolveBindings) {
+			recordNodes(qualifiedName, node);
+			recordPendingNameScopeResolution(qualifiedName);
+			recordNodes(firstToken, node);
+			recordNodes(secondToken, node);
+			recordPendingNameScopeResolution(firstToken);
+			recordPendingNameScopeResolution(secondToken);
+		}
+		qualifiedName.index = length - 2;
+		qualifiedName.setSourceRange(start0, end - start0 + 1);
+		SimpleName newPart = null;
+		for (int i = 2; i < length; i++) {
+			newPart = this.ast.newSimpleName(new String(typeName[i]));
+			newPart.index = length - i - 1;
+			start = (int)(positions[i]>>>32);
+			end = (int)(positions[i] & 0xFFFFFFFF);
+			newPart.setSourceRange(start,  end - start + 1);
+			qualifiedName = this.ast.newQualifiedName(qualifiedName, newPart);
+			qualifiedName.index = newPart.index;
+			qualifiedName.setSourceRange(start0, end - start0 + 1);
+			if (this.resolveBindings) {
+				recordNodes(qualifiedName, node);
+				recordNodes(newPart, node);				
+				recordPendingNameScopeResolution(qualifiedName);
+				recordPendingNameScopeResolution(newPart);
+			}
+		}
+		QualifiedName name = qualifiedName;
+		if (this.resolveBindings) {
+			recordNodes(name, node);
+			recordPendingNameScopeResolution(name);
+		}
+		return name;
+	}
+	
+	protected QualifiedName setQualifiedNameNameAndSourceRanges(char[][] typeName, long[] positions, int startingIndex, int endingIndex, org.eclipse.jdt.internal.compiler.ast.ASTNode node) {
+		int length = endingIndex - startingIndex + 1;
+		SimpleName firstToken = this.ast.newSimpleName(new String(typeName[startingIndex]));
+		firstToken.index = startingIndex;
+		int start0 = (int)(positions[startingIndex]>>>32);
+		int start = start0;
+		int end = (int) positions[startingIndex];
+		firstToken.setSourceRange(start, end - start + 1);
+		SimpleName secondToken = this.ast.newSimpleName(new String(typeName[startingIndex + 1]));
+		secondToken.index = startingIndex + 1;
+		start = (int)(positions[startingIndex + 1]>>>32);
+		end = (int) positions[startingIndex + 1];
+		secondToken.setSourceRange(start, end - start + 1);
+		QualifiedName qualifiedName = this.ast.newQualifiedName(firstToken, secondToken);
+		if (this.resolveBindings) {
+			recordNodes(qualifiedName, node);
+			recordPendingNameScopeResolution(qualifiedName);
+			recordNodes(firstToken, node);
+			recordNodes(secondToken, node);
+			recordPendingNameScopeResolution(firstToken);
+			recordPendingNameScopeResolution(secondToken);
+		}
+		qualifiedName.index = startingIndex + 1;
+		qualifiedName.setSourceRange(start0, end - start0 + 1);
+		SimpleName newPart = null;
+		for (int i = 2; i < length; i++) {
+			newPart = this.ast.newSimpleName(new String(typeName[i]));
+			newPart.index = startingIndex + i;
+			start = (int)(positions[i]>>>32);
+			end = (int) positions[i];
+			newPart.setSourceRange(start,  end - start + 1);
+			qualifiedName = this.ast.newQualifiedName(qualifiedName, newPart);
+			qualifiedName.index = newPart.index;
+			qualifiedName.setSourceRange(start0, end - start0 + 1);
+			if (this.resolveBindings) {
+				recordNodes(qualifiedName, node);
+				recordNodes(newPart, node);				
+				recordPendingNameScopeResolution(qualifiedName);
+				recordPendingNameScopeResolution(newPart);
+			}
+		}
+		QualifiedName name = qualifiedName;
+		if (this.resolveBindings) {
+			recordNodes(name, node);
+			recordPendingNameScopeResolution(name);
+		}
+		return name;
+	}
+	
+	protected void setTypeNameForAnnotation(org.eclipse.jdt.internal.compiler.ast.Annotation compilerAnnotation, Annotation annotation) {
+		TypeReference typeReference = compilerAnnotation.type;
+		Name name;
+		if (typeReference instanceof QualifiedTypeReference) {
+			QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) typeReference;
+			char[][] tokens = qualifiedTypeReference.tokens;
+			long[] positions = qualifiedTypeReference.sourcePositions;
+			// QualifiedName
+			name = setQualifiedNameNameAndSourceRanges(tokens, positions, compilerAnnotation);
+		} else {
+			SingleTypeReference singleTypeReference = (SingleTypeReference) typeReference;
+			name = this.ast.newSimpleName(new String(singleTypeReference.token));
+			int start = singleTypeReference.sourceStart;
+			int end = singleTypeReference.sourceEnd;
+			name.setSourceRange(start, end - start + 1);
+		}
+		if (this.resolveBindings) {
+			recordNodes(name, compilerAnnotation);
+		}
+		annotation.setTypeName(name);
+	}
+	
+	protected void setTypeForField(FieldDeclaration fieldDeclaration, Type type, int extraDimension) {
+		if (extraDimension != 0) {
+			if (type.isArrayType()) {
+				ArrayType arrayType = (ArrayType) type;
+				int remainingDimensions = arrayType.getDimensions() - extraDimension;
+				if (remainingDimensions == 0)  {
+					// the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+					Type elementType = arrayType.getElementType();
+					// cut the child loose from its parent (without creating garbage)
+					elementType.setParent(null, null);
+					this.ast.getBindingResolver().updateKey(type, elementType);
+					fieldDeclaration.setType(elementType);
+				} else {
+					int start = type.getStartPosition();
+					ArrayType subarrayType = arrayType;
+					int index = extraDimension;
+					while (index > 0) {
+						subarrayType = (ArrayType) subarrayType.getComponentType();
+						index--;
+					}
+					int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+					subarrayType.setSourceRange(start, end - start + 1);
+					// cut the child loose from its parent (without creating garbage)
+					subarrayType.setParent(null, null);
+					fieldDeclaration.setType(subarrayType);
+					updateInnerPositions(subarrayType, remainingDimensions);
+					this.ast.getBindingResolver().updateKey(type, subarrayType);
+				}
+			} else {
+				fieldDeclaration.setType(type);
+			}
+		} else {
+			if (type.isArrayType()) {
+				// update positions of the component types of the array type
+				int dimensions = ((ArrayType) type).getDimensions();
+				updateInnerPositions(type, dimensions);
+			}
+			fieldDeclaration.setType(type);
+		}
+	}
+	
+	protected void setTypeForMethodDeclaration(MethodDeclaration methodDeclaration, Type type, int extraDimension) {
+		if (extraDimension != 0) {
+			if (type.isArrayType()) {
+				ArrayType arrayType = (ArrayType) type;
+				int remainingDimensions = arrayType.getDimensions() - extraDimension;
+				if (remainingDimensions == 0)  {
+					// the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+					Type elementType = arrayType.getElementType();
+					// cut the child loose from its parent (without creating garbage)
+					elementType.setParent(null, null);
+					this.ast.getBindingResolver().updateKey(type, elementType);
+					switch(this.ast.apiLevel) {
+						case AST.JLS2 :
+							methodDeclaration.setReturnType(elementType);
+							break;
+						case AST.JLS3 :
+							methodDeclaration.setReturnType2(elementType);
+						break;
+					}
+				} else {
+					int start = type.getStartPosition();
+					ArrayType subarrayType = arrayType;
+					int index = extraDimension;
+					while (index > 0) {
+						subarrayType = (ArrayType) subarrayType.getComponentType();
+						index--;
+					}
+					int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+					subarrayType.setSourceRange(start, end - start + 1);
+					// cut the child loose from its parent (without creating garbage)
+					subarrayType.setParent(null, null);
+					updateInnerPositions(subarrayType, remainingDimensions);
+					switch(this.ast.apiLevel) {
+						case AST.JLS2 :
+							methodDeclaration.setReturnType(subarrayType);
+							break;
+						case AST.JLS3 :
+							methodDeclaration.setReturnType2(subarrayType);
+						break;
+					}
+					this.ast.getBindingResolver().updateKey(type, subarrayType);
+				}
+			} else {
+				switch(this.ast.apiLevel) {
+					case AST.JLS2 :
+						methodDeclaration.setReturnType(type);
+						break;
+					case AST.JLS3 :
+						methodDeclaration.setReturnType2(type);
+					break;
+				}
+			}
+		} else {
+			switch(this.ast.apiLevel) {
+				case AST.JLS2 :
+					methodDeclaration.setReturnType(type);
+					break;
+				case AST.JLS3 :
+					methodDeclaration.setReturnType2(type);
+				break;
+			}
+		}
+	}
+	
+	protected void setTypeForMethodDeclaration(AnnotationTypeMemberDeclaration annotationTypeMemberDeclaration, Type type, int extraDimension) {
+		annotationTypeMemberDeclaration.setType(type);
+	}
+
+	protected void setTypeForSingleVariableDeclaration(SingleVariableDeclaration singleVariableDeclaration, Type type, int extraDimension) {
+		if (extraDimension != 0) {
+			if (type.isArrayType()) {
+				ArrayType arrayType = (ArrayType) type;
+				int remainingDimensions = arrayType.getDimensions() - extraDimension;
+				if (remainingDimensions == 0)  {
+					// the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+					Type elementType = arrayType.getElementType();
+					// cut the child loose from its parent (without creating garbage)
+					elementType.setParent(null, null);
+					this.ast.getBindingResolver().updateKey(type, elementType);
+					singleVariableDeclaration.setType(elementType);
+				} else {
+					int start = type.getStartPosition();
+					ArrayType subarrayType = arrayType;
+					int index = extraDimension;
+					while (index > 0) {
+						subarrayType = (ArrayType) subarrayType.getComponentType();
+						index--;
+					}
+					int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+					subarrayType.setSourceRange(start, end - start + 1);
+					// cut the child loose from its parent (without creating garbage)
+					subarrayType.setParent(null, null);
+					updateInnerPositions(subarrayType, remainingDimensions);
+					singleVariableDeclaration.setType(subarrayType);
+					this.ast.getBindingResolver().updateKey(type, subarrayType);
+				}
+			} else {
+				singleVariableDeclaration.setType(type);
+			}
+		} else {
+			singleVariableDeclaration.setType(type);
+		}
+	}
+
+	protected void setTypeForVariableDeclarationExpression(VariableDeclarationExpression variableDeclarationExpression, Type type, int extraDimension) {
+		if (extraDimension != 0) {
+			if (type.isArrayType()) {
+				ArrayType arrayType = (ArrayType) type;
+				int remainingDimensions = arrayType.getDimensions() - extraDimension;
+				if (remainingDimensions == 0)  {
+					// the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+					Type elementType = arrayType.getElementType();
+					// cut the child loose from its parent (without creating garbage)
+					elementType.setParent(null, null);
+					this.ast.getBindingResolver().updateKey(type, elementType);
+					variableDeclarationExpression.setType(elementType);
+				} else {
+					int start = type.getStartPosition();
+					ArrayType subarrayType = arrayType;
+					int index = extraDimension;
+					while (index > 0) {
+						subarrayType = (ArrayType) subarrayType.getComponentType();
+						index--;
+					}
+					int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+					subarrayType.setSourceRange(start, end - start + 1);
+					// cut the child loose from its parent (without creating garbage)
+					subarrayType.setParent(null, null);
+					updateInnerPositions(subarrayType, remainingDimensions);
+					variableDeclarationExpression.setType(subarrayType);
+					this.ast.getBindingResolver().updateKey(type, subarrayType);
+				}
+			} else {
+				variableDeclarationExpression.setType(type);
+			}
+		} else {
+			variableDeclarationExpression.setType(type);
+		}
+	}
+
+	protected void setTypeForVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, Type type, int extraDimension) {
+		if (extraDimension != 0) {
+			if (type.isArrayType()) {
+				ArrayType arrayType = (ArrayType) type;
+				int remainingDimensions = arrayType.getDimensions() - extraDimension;
+				if (remainingDimensions == 0)  {
+					// the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+					Type elementType = arrayType.getElementType();
+					// cut the child loose from its parent (without creating garbage)
+					elementType.setParent(null, null);
+					this.ast.getBindingResolver().updateKey(type, elementType);
+					variableDeclarationStatement.setType(elementType);
+				} else {
+					int start = type.getStartPosition();
+					ArrayType subarrayType = arrayType;
+					int index = extraDimension;
+					while (index > 0) {
+						subarrayType = (ArrayType) subarrayType.getComponentType();
+						index--;
+					}
+					int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+					subarrayType.setSourceRange(start, end - start + 1);
+					// cut the child loose from its parent (without creating garbage)
+					subarrayType.setParent(null, null);
+					updateInnerPositions(subarrayType, remainingDimensions);
+					variableDeclarationStatement.setType(subarrayType);
+					this.ast.getBindingResolver().updateKey(type, subarrayType);
+				}
+			} else {
+				variableDeclarationStatement.setType(type);
+			}
+		} else {
+			variableDeclarationStatement.setType(type);
+		}
+	}
+
+	protected void updateInnerPositions(Type type, int dimensions) {
+		if (dimensions > 1) {
+			// need to set positions for intermediate array type see 42839
+			int start = type.getStartPosition();
+			Type currentComponentType = ((ArrayType) type).getComponentType();
+			int searchedDimension = dimensions - 1;
+			int rightBracketEndPosition = start;
+			while (currentComponentType.isArrayType()) {
+				rightBracketEndPosition = retrieveProperRightBracketPosition(searchedDimension, start);
+				currentComponentType.setSourceRange(start, rightBracketEndPosition - start + 1);
+				currentComponentType = ((ArrayType) currentComponentType).getComponentType();
+				searchedDimension--;
+			}		
+		}
 	}
 }
 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
index 929359b..5892837 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
@@ -779,8 +779,11 @@
 				&& safeSubtreeMatch(node.getName(), o.getName())
 				&& safeSubtreeListMatch(node.arguments(), o.arguments())
 				&& safeSubtreeListMatch(
-					node.bodyDeclarations(),
-					o.bodyDeclarations()));
+					node.obsoleteBodyDeclarations(),
+					o.obsoleteBodyDeclarations()))
+				&& safeSubtreeMatch(
+					node.getAnonymousClassDeclaration(),
+					o.getAnonymousClassDeclaration());
 	}
 	
 	/**
@@ -808,6 +811,7 @@
 				&& safeSubtreeListMatch(node.modifiers(), o.modifiers())
 				&& safeSubtreeMatch(node.getName(), o.getName())
 				&& safeSubtreeListMatch(node.superInterfaceTypes(), o.superInterfaceTypes())
+				&& safeSubtreeListMatch(node.enumConstants(), o.enumConstants())
 				&& safeSubtreeListMatch(
 					node.bodyDeclarations(),
 					o.bodyDeclarations()));
@@ -1078,7 +1082,7 @@
 	 * When this parameter is <code>true</code>, the implementation
 	 * tests whether the other object is also a <code>Javadoc</code>
 	 * with structurally isomorphic child subtrees; the comment string 
-	 * ({@link Javadoc#getComment() Javadoc.getComment}) is ignored.
+	 * (<code>Javadoc.getComment()</code>) is ignored.
 	 * Conversely, when the parameter is <code>false</code>, the
 	 * implementation tests whether the other object is also a
 	 * <code>Javadoc</code> with exactly the same comment string; 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
index 71aacd0..faccc74 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
@@ -955,7 +955,7 @@
 	/**
 	 * An unmodifiable empty map (used to implement <code>properties()</code>).
 	 */
-	private static Map UNMODIFIABLE_EMPTY_MAP
+	private static final Map UNMODIFIABLE_EMPTY_MAP
 		= Collections.unmodifiableMap(new HashMap(1));
 	
 	/**
@@ -1057,22 +1057,22 @@
 	/** Internal convenience constant indicating that there is definite risk of cycles.
 	 * @since 3.0
 	 */ 
-	static boolean CYCLE_RISK = true;
+	static final boolean CYCLE_RISK = true;
 	
 	/** Internal convenience constant indicating that there is no risk of cycles.
 	 * @since 3.0
 	 */ 
-	static boolean NO_CYCLE_RISK = false;
+	static final boolean NO_CYCLE_RISK = false;
 	
 	/** Internal convenience constant indicating that a structural property is mandatory.
 	 * @since 3.0
 	 */ 
-	static boolean MANDATORY = true;
+	static final boolean MANDATORY = true;
 	
 	/** Internal convenience constant indicating that a structural property is optional.
 	 * @since 3.0
 	 */ 
-	static boolean OPTIONAL = false;
+	static final boolean OPTIONAL = false;
 	
 	/**
 	 * A specialized implementation of a list of ASTNodes. The
@@ -1702,51 +1702,47 @@
 	abstract List internalStructuralPropertiesForType(int apiLevel);
 	
 	/**
-	 * Global temp storage. Used in building structural property
-	 * list for AST node types.
-	 */
-	static List tempPDL = null;
-	
-	/**
 	 * Internal helper method that starts the building a list of
 	 * property descriptors for the given node type.
 	 * 
 	 * @param nodeClass the class for a concrete node type
+	 * @param propertyList empty list
 	 */
-	static void createPropertyList(Class nodeClass) {
-		tempPDL = new ArrayList(5);
+	static void createPropertyList(Class nodeClass, List propertyList) {
 		// stuff nodeClass at head of list for future ref
-		tempPDL.add(nodeClass);
+		propertyList.add(nodeClass);
 	}
 	
 	/**
 	 * Internal helper method that adding a property descriptor.
 	 * 
 	 * @param property the structural property descriptor
+	 * @param propertyList list beginning with the AST node class
+	 * followed by accumulated structural property descriptors
 	 */
-	static void addProperty(StructuralPropertyDescriptor property) {
-		Class nodeClass = (Class) tempPDL.get(0);
+	static void addProperty(StructuralPropertyDescriptor property, List propertyList) {
+		Class nodeClass = (Class) propertyList.get(0);
 		if (property.getNodeClass() != nodeClass) {
 			// easily made cut-and-paste mistake
 			throw new RuntimeException("Structural property descriptor has wrong node class!");  //$NON-NLS-1$
 		}
-		tempPDL.add(property);
+		propertyList.add(property);
 	}
-	
+		
 	/**
 	 * Internal helper method that completes the building of
 	 * a node type's structural property descriptor list.
 	 * 
+	 * @param propertyList list beginning with the AST node class
+	 * followed by accumulated structural property descriptors
 	 * @return unmodifiable list of structural property descriptors
 	 * (element type: <code>StructuralPropertyDescriptor</code>)
 	 */
-	static List reapPropertyList() {
-		tempPDL.remove(0); // remove nodeClass
+	static List reapPropertyList(List propertyList) {
+		propertyList.remove(0); // remove nodeClass
 		// compact
-		ArrayList a = new ArrayList(tempPDL.size());
-		a.addAll(tempPDL); 
-		// clear global
-		tempPDL = null;
+		ArrayList a = new ArrayList(propertyList.size());
+		a.addAll(propertyList); 
 		return Collections.unmodifiableList(a);
 	}
 	
@@ -2533,7 +2529,7 @@
 	 * where the source fragment corresponding to this node begins.
 	 * <p>
 	 * The parser supplies useful well-defined source ranges to the nodes it creates.
-	 * See {@link ASTParser} for details
+	 * See {@link ASTParser#setKind(int)} for details
 	 * on precisely where source ranges begin and end.
 	 * </p>
 	 * 
@@ -2551,7 +2547,7 @@
 	 * where the source fragment corresponding to this node ends.
 	 * <p>
 	 * The parser supplies useful well-defined source ranges to the nodes it creates.
-	 * See {@link ASTParser} methods for details
+	 * See {@link ASTParser#setKind(int)} methods for details
 	 * on precisely where source ranges begin and end.
 	 * </p>
 	 * 
@@ -2568,8 +2564,8 @@
 	 * Sets the source range of the original source file where the source
 	 * fragment corresponding to this node was found.
 	 * <p>
-	 * See {@link ASTParser} for details
-	 * on precisely where source ranges begin and end.
+	 * See {@link ASTParser#setKind(int)} for details
+	 * on precisely where source ranges are supposed to begin and end.
 	 * </p>
 	 * 
 	 * @param startPosition a 0-based character index, 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java
index c642c18..9e4bd86 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java
@@ -15,21 +15,21 @@
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.IClassFile;
 import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.WorkingCopyOwner;
-import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Statement;
-import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner;
+import org.eclipse.jdt.internal.core.PackageFragment;
 import org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil;
 import org.eclipse.jdt.internal.core.util.RecordedParsingInformation;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * A Java language parser for creating abstract syntax trees (ASTs).
@@ -579,6 +579,80 @@
    	   return result;
 	}
 	
+	/**
+     * Creates ASTs for a batch of compilation units.
+     * When bindings are being resolved, processing a
+     * batch of compilation units is more efficient because much
+     * of the work involved in resolving bindings can be shared.
+     * <p>
+     * When bindings are being resolved, all compilation units must
+     * come from the same Java project, which must be set beforehand
+     * with <code>setProject</code>.
+     * The compilation units are processed one at a time in no
+     * specified order. For each of the compilation units in turn,
+	 * <ul>
+	 * <li><code>ASTParser.createAST</code> is called to parse it
+	 * and create a corresponding AST. The calls to
+	 * <code>ASTParser.createAST</code> all employ the same settings.</li>
+	 * <li><code>ASTRequestor.acceptAST</code> is called passing
+	 * the compilation unit and the corresponding AST to 
+	 * <code>requestor</code>.
+	 * </li>
+	 * </ul> 
+     * Note only ASTs from the given compilation units are reported
+     * to the requestor. If additional compilation units are required to
+     * resolve the original ones, the corresponding ASTs are <b>not</b>
+     * reported to the requestor.
+     * </p>
+	 * <p>
+	 * Note also the following parser parameters are used, regardless of what
+	 * may have been specified:
+	 * <ul>
+	 * <li>The {@linkplain #setKind(int) parser kind} is <code>K_COMPILATION_UNIT</code></li>
+	 * <li>The {@linkplain #setSourceRange(int,int) source range} is <code>(0, -1)</code></li>
+	 * <li>The {@linkplain #setFocalPosition(int) focal position} is not set</li>
+	 * </ul>
+	 * </p>
+     * <p>
+     * The <code>bindingKeys</code> parameter specifies bindings keys
+     * ({@link IBinding#getKey()}) that are to be looked up. These keys may
+     * be for elements either inside or outside the set of compilation
+     * units being processed. When bindings are being resolved,
+     * the keys and corresponding bindings (or <code>null</code> if none) are
+     * passed to <code>ASTRequestor.acceptBinding</code>. Note that binding keys
+     * are looked up after all <code>ASTRequestor.acceptAST</code> callbacks
+     * have been made. No <code>ASTRequestor.acceptBinding</code> callbacks are
+     * made unless bindings are being resolved.
+     * </p>
+     * <p>
+     * A successful call to this method returns all settings to their
+     * default values so the object is ready to be reused.
+     * </p>
+     * 
+     * @param compilationUnits the compilation units to create ASTs for
+     * @param bindingKeys the binding keys to create bindings for
+     * @param requestor the AST requestor that collects abtract syntax trees and bindings
+	 * @param monitor the progress monitor used to report progress and request cancelation,
+	 *   or <code>null</code> if none
+	 * @exception IllegalStateException if the settings provided
+	 * are insufficient, contradictory, or otherwise unsupported
+	 * @since 3.1
+     */
+	public void createASTs(ICompilationUnit[] compilationUnits, String[] bindingKeys, ASTRequestor requestor, IProgressMonitor monitor) {
+		try {
+			if (this.resolveBindings) {
+				if (this.project == null)
+					throw new IllegalStateException("project not specified"); //$NON-NLS-1$
+				CompilationUnitResolver.resolve(compilationUnits, bindingKeys, requestor, this.apiLevel, this.compilerOptions, this.project, this.workingCopyOwner, monitor);
+			} else {
+				CompilationUnitResolver.parse(compilationUnits, requestor, this.apiLevel, this.compilerOptions, monitor);
+			}
+		} finally {
+	   	   // re-init defaults to allow reuse (and avoid leaking)
+	   	   initializeDefaults();
+		}
+	}
+	
 	private ASTNode internalCreateAST(IProgressMonitor monitor) {
 		boolean needToResolveBindings = this.resolveBindings;
 		switch(this.astKind) {
@@ -595,58 +669,35 @@
 			case K_COMPILATION_UNIT :
 				CompilationUnitDeclaration compilationUnitDeclaration = null;
 				try {
-					char[] source = null;
 					NodeSearcher searcher = null;
-					char[][] packageName = null;
-					String fileName = null;
+					org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = null;
 					if (this.compilationUnitSource != null) {
-						try {
-							source = this.compilationUnitSource.getSource().toCharArray();
-						} catch(JavaModelException e) {
-							// no source, then we cannot build anything
-							throw new IllegalStateException();
-						}
-						IPackageFragment packageFragment = (IPackageFragment)this.compilationUnitSource.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
-						if (packageFragment != null){
-							packageName = CharOperation.splitOn('.', packageFragment.getElementName().toCharArray());
-						}
-						fileName = this.compilationUnitSource.getElementName();
+						sourceUnit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) this.compilationUnitSource;
+						// use a BasicCompilation that caches the source instead of using the compilationUnitSource directly 
+						// (if it is a working copy, the source can change between the parse and the AST convertion)
+						// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=75632)
+						sourceUnit = new BasicCompilationUnit(sourceUnit.getContents(), sourceUnit.getPackageName(), new String(sourceUnit.getFileName()), this.project);
 					} else if (this.classFileSource != null) {
-						String sourceString = null;
 						try {
-							sourceString = this.classFileSource.getSource();
-						} catch (JavaModelException e) {
-							// nothing to do
-						}
-					
-						if (sourceString == null) {
-							throw new IllegalStateException();
-						}
-						source = sourceString.toCharArray();
-						try {
-							packageName = CharOperation.splitOn('.', this.classFileSource.getType().getPackageFragment().getElementName().toCharArray());
-							StringBuffer buffer = new StringBuffer(SuffixConstants.SUFFIX_STRING_java);
-							String classFileName = this.classFileSource.getElementName(); // this includes the trailing .class
-							buffer.insert(0, classFileName.toCharArray(), 0, classFileName.indexOf('.'));
-							fileName = String.valueOf(buffer);
+							String sourceString = this.classFileSource.getSource();
+							if (sourceString == null) {
+								throw new IllegalStateException();
+							}
+							PackageFragment packageFragment = (PackageFragment) this.classFileSource.getParent();
+							BinaryType type = (BinaryType) this.classFileSource.getType();
+							IBinaryType binaryType = (IBinaryType) type.getElementInfo();
+							String fileName = new String(binaryType.getFileName()); // file name is used to recreate the Java element, so it has to be the .class file name
+							sourceUnit = new BasicCompilationUnit(sourceString.toCharArray(), Util.toCharArrays(packageFragment.names), fileName, this.project);
 						} catch(JavaModelException e) {
-							needToResolveBindings = false;
+							// an error occured accessing the java element
+							throw new IllegalStateException();
 						}
 					} else if (this.rawSource != null) {
-						source = this.rawSource;
-						if (this.unitName == null || this.project == null || this.compilerOptions == null) {
-							needToResolveBindings = false;
-						} else {
-							fileName = this.unitName;
-							needToResolveBindings = true;
-						}
-					}
-					if (source == null) {
+						needToResolveBindings = this.unitName != null && this.project != null && this.compilerOptions != null;
+						sourceUnit = new BasicCompilationUnit(this.rawSource, null, this.unitName == null ? "" : this.unitName, this.project); //$NON-NLS-1$
+					} else {
 						throw new IllegalStateException();
 					}
-					if (this.sourceLength == -1) {
-						this.sourceLength = source.length;
-					}
 					if (this.partial) {
 						searcher = new NodeSearcher(this.focalPointPosition);
 					}
@@ -655,30 +706,35 @@
 							// parse and resolve
 							compilationUnitDeclaration = 
 								CompilationUnitResolver.resolve(
-									source,
-									packageName,
-									fileName,
+									sourceUnit,
 									this.project,
 									searcher,
 									this.compilerOptions,
-									false,
 									this.workingCopyOwner,
 									monitor);
 						} catch (JavaModelException e) {
 							compilationUnitDeclaration = CompilationUnitResolver.parse(
-									source,
+									sourceUnit,
 									searcher,
 									this.compilerOptions);
 							needToResolveBindings = false;
 						}
 					} else {
 						compilationUnitDeclaration = CompilationUnitResolver.parse(
-								source,
+								sourceUnit,
 								searcher,
 								this.compilerOptions);
 						needToResolveBindings = false;
 					}
-					return convert(monitor, compilationUnitDeclaration, source, needToResolveBindings);
+					return CompilationUnitResolver.convert(
+						compilationUnitDeclaration, 
+						sourceUnit.getContents(),
+						this.apiLevel, 
+						this.compilerOptions,
+						needToResolveBindings,
+						this.compilationUnitSource == null ? this.workingCopyOwner : this.compilationUnitSource.getOwner(),
+						needToResolveBindings ? new DefaultBindingResolver.BindingTables() : null, 
+						monitor);
 				} finally {
 					if (compilationUnitDeclaration != null && this.resolveBindings) {
 						compilationUnitDeclaration.cleanUp();
@@ -687,37 +743,7 @@
 		}
 		throw new IllegalStateException();
 	}
-
-	/**
-	 * @param monitor
-	 * @param compilationUnitDeclaration
-	 * @param source
-	 * @return
-	 */
-	private ASTNode convert(IProgressMonitor monitor, CompilationUnitDeclaration compilationUnitDeclaration, char[] source, boolean needToResolveBindings) {
-		BindingResolver resolver = null;
-		AST ast = AST.newAST(this.apiLevel);
-		ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
-		CompilationUnit compilationUnit = null;
-		if (AST.JLS2 == this.apiLevel) {
-			ASTConverter converter = new ASTConverter(this.compilerOptions, needToResolveBindings, monitor);
-			if (needToResolveBindings) {
-				resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope);
-			} else {
-				resolver = new BindingResolver();
-			}
-			ast.setBindingResolver(resolver);
-			converter.setAST(ast);
-			compilationUnit = converter.convert(compilationUnitDeclaration, source);
-			compilationUnit.setLineEndTable(compilationUnitDeclaration.compilationResult.lineSeparatorPositions);
-		} else {
-			throw new RuntimeException("J2SE 1.5 parser not implemented yet"); //$NON-NLS-1$
-		}
-		ast.setDefaultNodeFlag(0);
-		ast.setOriginalModificationCount(ast.modificationCount());
-		return compilationUnit;
-	}
-
+	
 	/**
 	 * Parses the given source between the bounds specified by the given offset (inclusive)
 	 * and the given length and creates and returns a corresponding abstract syntax tree.
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRequestor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRequestor.java
new file mode 100644
index 0000000..c0eedfe
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRequestor.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+
+/**
+ * An AST requestor handles ASTs for compilation units passed to
+ * <code>ASTParser.createASTs</code>.
+ * <p>
+ * <code>ASTRequestor.acceptAST</code> is called for each of the
+ * compilation units passed to <code>ASTParser.createASTs</code>.
+ * After all the compilation units have been processed, 
+ * <code>ASTRequestor.acceptBindings</code> is called for each
+ * of the binding keys passed to <code>ASTParser.createASTs</code>.
+ * </p>
+ * <p>
+ * This class is intended to be subclassed by clients.
+ * AST requestors are serially reusable, but neither reentrant nor
+ * thread-safe.
+ * </p>
+ * 
+ * @see ASTParser#createASTs(ICompilationUnit[], String[], ASTRequestor, org.eclipse.core.runtime.IProgressMonitor)
+ * @since 3.1
+ */
+public abstract class ASTRequestor {
+	
+	/**
+	 * The compilation unit resolver used to resolve bindings, or
+	 * <code>null</code> if none. Note that this field is non-null
+	 * only within the dynamic scope of a call to
+	 * <code>ASTParser.createASTs</code>.
+	 */
+	CompilationUnitResolver compilationUnitResolver = null;
+		
+	/**
+	 * Creates a new instance.
+	 */
+	protected ASTRequestor() {
+		// do nothing
+	}
+	
+	/**
+	 * Accepts an AST corresponding to the compilation unit.
+	 * That is, <code>ast</code> is an AST for <code>source</code>.
+	 * <p>
+	 * The default implementation of this method does nothing.
+	 * Clients should override to process the resulting AST.
+	 * </p>
+	 * 
+	 * @param source the compilation unit the ast is coming from
+	 * @param ast the requested abtract syntax tree
+	 */
+	public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
+		// do nothing
+	}
+	
+	/**
+	 * Accepts a binding corresponding to the binding key.
+	 * That is, <code>binding</code> is the binding for 
+	 * <code>bindingKey</code>; <code>binding</code> is <code>null</code>
+	 * if the key cannot be resolved.
+	 * <p>
+	 * The default implementation of this method does nothing.
+	 * Clients should override to process the resulting binding.
+	 * </p>
+	 * 
+	 * @param bindingKey the key of the requested binding
+	 * @param binding the requested binding, or <code>null</code> if none
+	 */
+	public void acceptBinding(String bindingKey, IBinding binding) {
+		// do nothing
+	}
+
+	/**
+	 * Resolves bindings for the given binding keys.
+	 * The given binding keys must have been obtained earlier
+	 * using {@link IBinding#getKey()}.
+	 * <p>
+	 * If a binding key cannot be resolved, <code>null</code> is put in the resulting array.
+	 * Bindings can only be resolved in the dynamic scope of a <code>ASTParser.createASTs</code>,
+	 * and only if <code>ASTParser.resolveBindings(true)</code> was specified.
+	 * </p>
+	 * <p>
+	 * Caveat: During an <code>acceptAST</code> callback, there are implementation 
+	 * limitations concerning the look up of binding keys representing local elements.
+	 * In some cases, the binding is unavailable, and <code>null</code> will be returned.
+	 * This is only an issue during an <code>acceptAST</code> callback, and only
+	 * when the binding key represents a local element (e.g., local variable,
+	 * local class, method declared in anonymous class). There is no such limitation
+	 * outside of <code>acceptAST</code> callbacks, or for top-level types and their
+	 * members even within <code>acceptAST</code> callbacks.
+	 * </p>
+	 * 
+	 * @param bindingKeys the binding keys to look up
+	 * @return a list of bindings paralleling the <code>bindingKeys</code> parameter,
+	 * with <code>null</code> entries for keys that could not be resolved
+	 */
+	public final IBinding[] createBindings(String[] bindingKeys) {
+		int length = bindingKeys.length;
+		IBinding[] result = new IBinding[length];
+		for (int i = 0; i < length; i++) {
+			result[i] = null;
+			if (this.compilationUnitResolver != null) {
+				result[i] = this.compilationUnitResolver.createBinding(bindingKeys[i]);
+			}
+		}
+		return result;
+	}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AbstractTypeDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AbstractTypeDeclaration.java
index 37fe9be..836ada7 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AbstractTypeDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AbstractTypeDeclaration.java
@@ -49,6 +49,17 @@
 	abstract ChildListPropertyDescriptor internalBodyDeclarationsProperty();
 
 	/**
+	 * Returns structural property descriptor for the "bodyDeclarations" property
+	 * of this node.
+	 * 
+	 * @return the property descriptor
+	 * @since 3.1
+	 */
+	public final ChildListPropertyDescriptor getBodyDeclarationsProperty() {
+		return internalBodyDeclarationsProperty();
+	}
+
+	/**
 	 * Returns structural property descriptor for the "name" property
 	 * of this node.
 	 * 
@@ -57,6 +68,17 @@
 	abstract ChildPropertyDescriptor internalNameProperty();
 	
 	/**
+	 * Returns structural property descriptor for the "name" property
+	 * of this node.
+	 * 
+	 * @return the property descriptor
+	 * @since 3.1
+	 */
+	public final ChildPropertyDescriptor getNameProperty() {
+		return internalNameProperty();
+	}
+	
+	/**
 	 * Creates and returns a structural property descriptor for the
 	 * "bodyDeclaration" property declared on the given concrete node type.
 	 * 
@@ -168,17 +190,18 @@
 	 * Returns whether this type declaration is a type member.
 	 * <p>
 	 * Note that this is a convenience method that simply checks whether
-	 * this node's parent is a type declaration node, an anonymous 
-	 * class declaration, or an enumeration constant declaration.
+	 * this node's parent is a type declaration node or an anonymous 
+	 * class declaration.
 	 * </p>
 	 * 
 	 * @return <code>true</code> if this type declaration is a child of
-	 *   a type declaration node, a class instance creation node, or an
-	 *   enum constant declaration, and <code>false</code> otherwise
+	 *   a type declaration node or an anonymous class declaration node,
+	 *   and <code>false</code> otherwise
 	 * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
 	 */
 	public boolean isMemberTypeDeclaration() {
 		ASTNode parent = getParent();
+		// TODO (jeem) - after 3.1 M4 remove mention of EnumConstantDeclaration
 		return (parent instanceof AbstractTypeDeclaration)
 			|| (parent instanceof AnonymousClassDeclaration)
 			|| (parent instanceof EnumConstantDeclaration);
@@ -200,6 +223,31 @@
 		return (parent instanceof TypeDeclarationStatement);
 	}
 	
+	/**
+	 * Resolves and returns the binding for the type declared in this type
+	 * declaration.
+	 * <p>
+	 * Note that bindings are generally unavailable unless requested when the
+	 * AST is being built.
+	 * </p>
+	 * 
+	 * @return the binding, or <code>null</code> if the binding cannot be 
+	 *    resolved
+	 * @since 3.1 Declared in 3.0 on the individual subclasses.
+	 */	
+	public final ITypeBinding resolveBinding() {
+		return internalResolveBinding();
+	}
+	
+	/**
+	 * Resolves and returns the binding for the type declared in this type
+	 * declaration. This method must be implemented by subclasses.
+	 * 
+	 * @return the binding, or <code>null</code> if the binding cannot be 
+	 *    resolved
+	 */	
+	abstract ITypeBinding internalResolveBinding();
+	
 	/* (omit javadoc for this method)
 	 * Method declared on ASTNode.
 	 */
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Annotation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Annotation.java
index 631d01e..35e9577 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Annotation.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Annotation.java
@@ -39,6 +39,17 @@
 	abstract ChildPropertyDescriptor internalTypeNameProperty();
 
 	/**
+	 * Returns structural property descriptor for the "typeName" property
+	 * of this node.
+	 * 
+	 * @return the property descriptor
+	 * @since 3.1
+	 */
+	public final ChildPropertyDescriptor getTypeNameProperty() {
+		return internalTypeNameProperty();
+	}
+
+	/**
 	 * Creates and returns a structural property descriptor for the
 	 * "typeName" property declared on the given concrete node type.
 	 * 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationTypeDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationTypeDeclaration.java
index 26b465a..1ebd236 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationTypeDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationTypeDeclaration.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -81,12 +82,13 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(AnnotationTypeDeclaration.class);
-		addProperty(JAVADOC_PROPERTY);
-		addProperty(MODIFIERS2_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(BODY_DECLARATIONS_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(5);
+		createPropertyList(AnnotationTypeDeclaration.class, properyList);
+		addProperty(JAVADOC_PROPERTY, properyList);
+		addProperty(MODIFIERS2_PROPERTY, properyList);
+		addProperty(NAME_PROPERTY, properyList);
+		addProperty(BODY_DECLARATIONS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
@@ -246,18 +248,10 @@
 		visitor.endVisit(this);
 	}
 	
-	/**
-	 * Resolves and returns the binding for the annotation type declared in
-	 * this annotation type declaration.
-	 * <p>
-	 * Note that bindings are generally unavailable unless requested when the
-	 * AST is being built.
-	 * </p>
-	 * 
-	 * @return the binding, or <code>null</code> if the binding cannot be 
-	 *    resolved
-	 */	
-	public ITypeBinding resolveBinding() {
+	/* (omit javadoc for this method)
+	 * Method declared on AsbtractTypeDeclaration.
+	 */
+	ITypeBinding internalResolveBinding() {
 		return this.ast.getBindingResolver().resolveType(this);
 	}
 	
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationTypeMemberDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationTypeMemberDeclaration.java
index d4e90d5..cf4df07 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationTypeMemberDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationTypeMemberDeclaration.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -86,13 +87,14 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(AnnotationTypeMemberDeclaration.class);
-		addProperty(JAVADOC_PROPERTY);
-		addProperty(MODIFIERS2_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(TYPE_PROPERTY);
-		addProperty(DEFAULT_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(6);
+		createPropertyList(AnnotationTypeMemberDeclaration.class, properyList);
+		addProperty(JAVADOC_PROPERTY, properyList);
+		addProperty(MODIFIERS2_PROPERTY, properyList);
+		addProperty(NAME_PROPERTY, properyList);
+		addProperty(TYPE_PROPERTY, properyList);
+		addProperty(DEFAULT_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
@@ -398,7 +400,7 @@
 	 * @return the binding, or <code>null</code> if the binding cannot be 
 	 *    resolved
 	 */	
-	public IVariableBinding resolveBinding() {
+	public IMethodBinding resolveBinding() {
 		return this.ast.getBindingResolver().resolveMember(this);
 	}
 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnonymousClassDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnonymousClassDeclaration.java
index f80a954..0664204 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnonymousClassDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnonymousClassDeclaration.java
@@ -10,11 +10,14 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Anonymous class declaration AST node type. This type of node appears
+ * Anonymous class declaration AST node type. For JLS2, this type of node appears
  * only as a child on a class instance creation expression.
+ * For JLS3, this type of node appears may also appear as the child of
+ * an enum constant declaration.
  *
  * <pre>
  * AnonymousClassDeclaration:
@@ -22,6 +25,7 @@
  * </pre>
  * 
  * @see ClassInstanceCreation
+ * @see EnumConstantDeclaration
  * @since 2.0
  */
 public class AnonymousClassDeclaration extends ASTNode {
@@ -41,9 +45,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(AnonymousClassDeclaration.class);
-		addProperty(BODY_DECLARATIONS_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(2);
+		createPropertyList(AnonymousClassDeclaration.class, properyList);
+		addProperty(BODY_DECLARATIONS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayAccess.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayAccess.java
index 23311bc..50e7090 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayAccess.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayAccess.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -47,10 +48,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(ArrayAccess.class);
-		addProperty(ARRAY_PROPERTY);
-		addProperty(INDEX_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(3);
+		createPropertyList(ArrayAccess.class, properyList);
+		addProperty(ARRAY_PROPERTY, properyList);
+		addProperty(INDEX_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayCreation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayCreation.java
index 5aeb4f8..5d7c423 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayCreation.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayCreation.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -75,11 +76,12 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(ArrayCreation.class);
-		addProperty(TYPE_PROPERTY);
-		addProperty(DIMENSIONS_PROPERTY);
-		addProperty(INITIALIZER_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(4);
+		createPropertyList(ArrayCreation.class, properyList);
+		addProperty(TYPE_PROPERTY, properyList);
+		addProperty(DIMENSIONS_PROPERTY, properyList);
+		addProperty(INITIALIZER_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayInitializer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayInitializer.java
index ad11222..b59851b 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayInitializer.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayInitializer.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -40,9 +41,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(ArrayInitializer.class);
-		addProperty(EXPRESSIONS_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(2);
+		createPropertyList(ArrayInitializer.class, properyList);
+		addProperty(EXPRESSIONS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java
index 371b24b..4986a27 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -42,9 +43,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(ArrayType.class);
-		addProperty(COMPONENT_TYPE_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(2);
+		createPropertyList(ArrayType.class, properyList);
+		addProperty(COMPONENT_TYPE_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AssertStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AssertStatement.java
index 9afe463..7cefb96 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AssertStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AssertStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -47,10 +48,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(AssertStatement.class);
-		addProperty(EXPRESSION_PROPERTY);
-		addProperty(MESSAGE_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(3);
+		createPropertyList(AssertStatement.class, properyList);
+		addProperty(EXPRESSION_PROPERTY, properyList);
+		addProperty(MESSAGE_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Assignment.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Assignment.java
index 5db1ff9..93d0339 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Assignment.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Assignment.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -174,11 +175,12 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(Assignment.class);
-		addProperty(LEFT_HAND_SIDE_PROPERTY);
-		addProperty(OPERATOR_PROPERTY);
-		addProperty(RIGHT_HAND_SIDE_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(4);
+		createPropertyList(Assignment.class, properyList);
+		addProperty(LEFT_HAND_SIDE_PROPERTY, properyList);
+		addProperty(OPERATOR_PROPERTY, properyList);
+		addProperty(RIGHT_HAND_SIDE_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingComparator.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingComparator.java
new file mode 100644
index 0000000..95f6c24
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingComparator.java
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ImportBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
+
+/**
+ * Internal helper class for comparing bindings.
+ * 
+ * @since 3.1
+ */
+class BindingComparator {
+	/**
+	 * @param bindings
+	 * @param otherBindings
+	 * @return true if both parameters are equals, false otherwise
+	 */
+	static boolean isEqual(TypeVariableBinding[] bindings, TypeVariableBinding[] otherBindings) {
+		if (bindings == null) {
+			return otherBindings == null;
+		} else if (otherBindings == null) {
+			return false;
+		} else {
+			int length = bindings.length;
+			int otherLength = otherBindings.length;
+			if (length != otherLength) {
+				return false;
+			}
+			for (int i = 0; i < length; i++) {
+				TypeVariableBinding typeVariableBinding = bindings[i];
+				TypeVariableBinding typeVariableBinding2 = otherBindings[i];
+				if (CharOperation.equals(typeVariableBinding.sourceName, typeVariableBinding2.sourceName)
+						&& isEqual(typeVariableBinding.declaringElement, typeVariableBinding2.declaringElement, false)
+						&& isEqual(typeVariableBinding.superclass, typeVariableBinding2.superclass, false)
+						&& isEqual(typeVariableBinding.superInterfaces, typeVariableBinding2.superInterfaces, false)) {
+					continue;
+				}
+				return false;
+			}
+			return true;
+		}
+	}
+	
+	/**
+	 * @param declaringElement
+	 * @param declaringElement2
+	 * @return true if both parameters are equals, false otherwise
+	 */
+	static boolean isEqual(Binding declaringElement, Binding declaringElement2, boolean checkTypeVariables) {
+		if (declaringElement instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+			if (!(declaringElement2 instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding)){
+				return false;
+			}
+			return isEqual((org.eclipse.jdt.internal.compiler.lookup.TypeBinding) declaringElement,
+					(org.eclipse.jdt.internal.compiler.lookup.TypeBinding) declaringElement2,
+					checkTypeVariables);
+		} else if (declaringElement instanceof org.eclipse.jdt.internal.compiler.lookup.MethodBinding) {
+			if (!(declaringElement2 instanceof org.eclipse.jdt.internal.compiler.lookup.MethodBinding)) {
+				return false;
+			}
+			return isEqual((org.eclipse.jdt.internal.compiler.lookup.MethodBinding) declaringElement,
+					(org.eclipse.jdt.internal.compiler.lookup.MethodBinding) declaringElement2,
+					checkTypeVariables);
+		} else if (declaringElement instanceof VariableBinding) {
+			if (!(declaringElement2 instanceof VariableBinding)) {
+				return false;
+			}
+			return isEqual((VariableBinding) declaringElement,
+					(VariableBinding) declaringElement2);
+		} else if (declaringElement instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding) {
+			if (!(declaringElement2 instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding)) {
+				return false;
+			}
+			org.eclipse.jdt.internal.compiler.lookup.PackageBinding packageBinding = (org.eclipse.jdt.internal.compiler.lookup.PackageBinding) declaringElement;
+			org.eclipse.jdt.internal.compiler.lookup.PackageBinding packageBinding2 = (org.eclipse.jdt.internal.compiler.lookup.PackageBinding) declaringElement2;
+			return CharOperation.equals(packageBinding.compoundName, packageBinding2.compoundName);
+		} else if (declaringElement instanceof ImportBinding) {
+			if (!(declaringElement2 instanceof ImportBinding)) {
+				return false;
+			}
+			ImportBinding importBinding = (ImportBinding) declaringElement;
+			ImportBinding importBinding2 = (ImportBinding) declaringElement2;
+			return importBinding.isStatic() == importBinding2.isStatic()
+				&& importBinding.onDemand == importBinding2.onDemand
+				&& CharOperation.equals(importBinding.compoundName, importBinding2.compoundName);
+		}
+		return false;
+	}
+	
+	static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding,
+			org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding2) {
+		return isEqual(methodBinding, methodBinding2, true);
+	}
+			
+	static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding,
+			org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding2,
+			boolean checkTypeVariables) {
+		if (checkTypeVariables) {
+			return (methodBinding == null && methodBinding2 == null)
+				|| (CharOperation.equals(methodBinding.selector, methodBinding2.selector)
+					&& isEqual(methodBinding.returnType, methodBinding2.returnType, false) 
+					&& isEqual(methodBinding.parameters, methodBinding2.parameters, false)
+					&& isEqual(methodBinding.thrownExceptions, methodBinding2.thrownExceptions, false)
+					&& isEqual(methodBinding.typeVariables, methodBinding2.typeVariables, false))
+					&& isEqual(methodBinding.declaringClass, methodBinding2.declaringClass, false);
+		}
+		return (methodBinding == null && methodBinding2 == null)
+			|| (CharOperation.equals(methodBinding.selector, methodBinding2.selector)
+				&& isEqual(methodBinding.returnType, methodBinding2.returnType, false) 
+				&& isEqual(methodBinding.parameters, methodBinding2.parameters, false)
+				&& isEqual(methodBinding.thrownExceptions, methodBinding2.thrownExceptions, false));
+	}
+
+	static boolean isEqual(VariableBinding variableBinding, VariableBinding variableBinding2) {
+		return variableBinding.modifiers == variableBinding2.modifiers
+				&& CharOperation.equals(variableBinding.name, variableBinding2.name)
+				&& isEqual(variableBinding.type, variableBinding2.type);
+	}
+
+	static boolean isEqual(FieldBinding fieldBinding, FieldBinding fieldBinding2) {
+		return fieldBinding.modifiers == fieldBinding2.modifiers
+				&& CharOperation.equals(fieldBinding.name, fieldBinding2.name)
+				&& isEqual(fieldBinding.type, fieldBinding2.type, false)
+				&& isEqual(fieldBinding.declaringClass, fieldBinding2.declaringClass, false);
+	}
+
+	/**
+	 * @param bindings
+	 * @param otherBindings
+	 * @return true if both parameters are equals, false otherwise
+	 */
+	static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] bindings, org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] otherBindings) {
+		return isEqual(bindings, otherBindings, true);
+	}
+	/**
+	 * @param bindings
+	 * @param otherBindings
+	 * @return true if both parameters are equals, false otherwise
+	 */
+	static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] bindings, org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] otherBindings, boolean checkTypeVariables) {
+		if (bindings == null) {
+			return otherBindings == null;
+		} else if (otherBindings == null) {
+			return false;
+		} else {
+			int length = bindings.length;
+			int otherLength = otherBindings.length;
+			if (length != otherLength) {
+				return false;
+			}
+			for (int i = 0; i < length; i++) {
+				if (!isEqual(bindings[i], otherBindings[i], checkTypeVariables)) {
+					return false;
+				}
+			}
+			return true;
+		}
+	}
+	static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding2, boolean checkTypeVariables) {
+		if (typeBinding == null) {
+			return typeBinding2 == null;
+		} else if (typeBinding2 == null) {
+			return false;
+		} else if (typeBinding.isBaseType()) {
+			// base type
+			if (!typeBinding2.isBaseType()) {
+				return false;
+			}
+			return typeBinding.id == typeBinding2.id;
+		} else if (typeBinding.isArrayType()) {
+			// array case
+			if (!typeBinding2.isArrayType()) {
+				return false;
+			}
+			return typeBinding.dimensions() == typeBinding2.dimensions()
+					&& isEqual(typeBinding.leafComponentType(), typeBinding2.leafComponentType(), checkTypeVariables);
+		} else {
+			// reference type
+			ReferenceBinding referenceBinding = (ReferenceBinding) typeBinding;
+			if (!(typeBinding2 instanceof ReferenceBinding)) {
+				return false;
+			}
+			ReferenceBinding referenceBinding2 = (ReferenceBinding) typeBinding2;
+			if (referenceBinding.isParameterizedType()) {
+				if (!referenceBinding2.isParameterizedType()) {
+					return false;
+				}
+				ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) referenceBinding;
+				ParameterizedTypeBinding parameterizedTypeBinding2 = (ParameterizedTypeBinding) referenceBinding2;
+				if (checkTypeVariables) {
+					if (!isEqual(parameterizedTypeBinding.arguments, parameterizedTypeBinding2.arguments, false)) {
+						return false;
+					}
+				}
+				return CharOperation.equals(referenceBinding.compoundName, referenceBinding2.compoundName)
+					&& (referenceBinding.isInterface() == referenceBinding2.isInterface())
+					&& (referenceBinding.isEnum() == referenceBinding2.isEnum())
+					&& (referenceBinding.isAnnotationType() == referenceBinding2.isAnnotationType())
+					&& (referenceBinding.modifiers == referenceBinding2.modifiers);
+			} else if (referenceBinding.isWildcard()) {
+				if (!referenceBinding2.isWildcard()) {
+					return false;
+				}
+				WildcardBinding wildcardBinding = (WildcardBinding) referenceBinding;
+				WildcardBinding wildcardBinding2 = (WildcardBinding) referenceBinding2;
+				return isEqual(wildcardBinding.bound, wildcardBinding2.bound)
+					&& wildcardBinding.kind == wildcardBinding2.kind;
+			} else if (referenceBinding.isGenericType()) {
+				if (!referenceBinding2.isGenericType()) {
+					return false;
+				}
+				if (checkTypeVariables) {
+					if (!isEqual(referenceBinding.typeVariables(), referenceBinding2.typeVariables(), false)) {
+						return false;
+					}
+				}
+				return CharOperation.equals(referenceBinding.compoundName, referenceBinding2.compoundName)
+					&& (referenceBinding.isGenericType() == referenceBinding2.isGenericType())
+					&& (referenceBinding.isRawType() == referenceBinding2.isRawType())
+					&& (referenceBinding.isInterface() == referenceBinding2.isInterface())
+					&& (referenceBinding.isEnum() == referenceBinding2.isEnum())
+					&& (referenceBinding.isAnnotationType() == referenceBinding2.isAnnotationType())
+					&& (referenceBinding.modifiers == referenceBinding2.modifiers);
+			} else if (referenceBinding instanceof TypeVariableBinding) {
+				if (!(referenceBinding2 instanceof TypeVariableBinding)) {
+					return false;
+				}
+				TypeVariableBinding typeVariableBinding = (TypeVariableBinding) referenceBinding;
+				TypeVariableBinding typeVariableBinding2 = (TypeVariableBinding) referenceBinding2;
+				if (checkTypeVariables) {
+					return CharOperation.equals(typeVariableBinding.sourceName, typeVariableBinding2.sourceName)
+						&& isEqual(typeVariableBinding.declaringElement, typeVariableBinding2.declaringElement, false)
+						&& isEqual(typeVariableBinding.superclass, typeVariableBinding2.superclass, false)
+						&& isEqual(typeVariableBinding.superInterfaces, typeVariableBinding2.superInterfaces, false);
+				} else {
+					return CharOperation.equals(typeVariableBinding.sourceName, typeVariableBinding2.sourceName);
+				}
+			} else {
+				return CharOperation.equals(referenceBinding.compoundName, referenceBinding2.compoundName)
+					&& (referenceBinding.isRawType() == referenceBinding2.isRawType())
+					&& (referenceBinding.isInterface() == referenceBinding2.isInterface())
+					&& (referenceBinding.isEnum() == referenceBinding2.isEnum())
+					&& (referenceBinding.isAnnotationType() == referenceBinding2.isAnnotationType())
+					&& (referenceBinding.modifiers == referenceBinding2.modifiers);
+			}
+		}
+	}
+	/**
+	 * @param typeBinding
+	 * @param typeBinding2
+	 * @return true if both parameters are equals, false otherwise
+	 */
+	static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding2) {
+		return isEqual(typeBinding, typeBinding2, true);
+	}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingKey.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingKey.java
new file mode 100644
index 0000000..525ed53
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingKey.java
@@ -0,0 +1,419 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+import org.eclipse.jdt.internal.compiler.lookup.BaseTypes;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
+
+/**
+ * Internal class.
+ * @since 3.1
+ */
+class BindingKey {
+	 char[][] compoundName;
+	 int dimension;
+	 BindingKeyScanner scanner;
+	 CompilationUnitResolver resolver;
+	 LookupEnvironment environment;
+	 
+	 BindingKey(String key, CompilationUnitResolver resolver) {
+	 	this.scanner = new BindingKeyScanner(key.toCharArray());
+	 	this.resolver = resolver;
+	 	this.environment = resolver.lookupEnvironment;
+	 	reset();
+	 }
+	 
+	 /*
+	  * If not already cached, computes and cache the compound name (pkg name + top level name) of this key.
+	  * Returns the package name if key is a pkg key.
+	  * Returns an empty array if malformed.
+	  * This key's scanner should be positioned on the package or type token.
+	  */
+	 char[][] compoundName() {
+	 	if (this.compoundName == null) {
+	 		switch(this.scanner.nextToken()) {
+	 			case BindingKeyScanner.PACKAGE:
+	 			case BindingKeyScanner.TYPE:
+		 			this.compoundName = CharOperation.splitOn('/', this.scanner.getTokenSource());
+		 			break;
+		 		case BindingKeyScanner.ARRAY:
+		 			this.dimension = this.scanner.getTokenSource().length;
+		 			if (this.scanner.nextToken() == BindingKeyScanner.TYPE)
+			 			this.compoundName = CharOperation.splitOn('/', this.scanner.getTokenSource());
+		 			else
+		 				// malformed key
+				 		this.compoundName = CharOperation.NO_CHAR_CHAR;
+		 			break;
+		 		default:
+			 		// malformed key
+			 		this.compoundName = CharOperation.NO_CHAR_CHAR;
+		 			break;
+	 		}
+	 	}
+	 	return this.compoundName;
+	 }
+	 
+	 /*
+	  * If the given dimension is greater than 0 returns an array binding for the given type binding.
+	  * Otherwise return the given type binding.
+	  * Returns null if the given type binding is null.
+	  */
+	 Binding getArrayBinding(int dim, TypeBinding binding) {
+	 	if (binding == null) return null;
+	 	if (dim == 0) return binding;
+		return this.environment.createArrayType(binding, dim);
+	}
+	
+	TypeBinding getBaseTypeBinding(char[] signature) {
+		switch (signature[0]) {
+			case 'I' :
+				return BaseTypes.IntBinding;
+			case 'Z' :
+				return BaseTypes.BooleanBinding;
+			case 'V' :
+				return BaseTypes.VoidBinding;
+			case 'C' :
+				return BaseTypes.CharBinding;
+			case 'D' :
+				return BaseTypes.DoubleBinding;
+			case 'B' :
+				return BaseTypes.ByteBinding;
+			case 'F' :
+				return BaseTypes.FloatBinding;
+			case 'J' :
+				return BaseTypes.LongBinding;
+			case 'S' :
+				return BaseTypes.ShortBinding;
+			default :
+				return null;
+		}
+	}
+	 
+	/*
+	 * Returns a binary binding corresonding to this key's compound name.
+	 * Returns null if not found.
+	 * This key's scanner should be positioned on the token after the top level type.
+	 */
+	Binding getBinaryBinding() {
+		TypeBinding binding = this.environment.getType(this.compoundName);
+		return getArrayBinding(this.dimension, binding);
+	}
+	 
+	 /*
+	  * Finds the compilation unit declaration corresponding to the key in the given lookup environment.
+	  * Returns null if no compilation unit declaration could be found.
+	  * This key's scanner should be positioned on the package token.
+	  */
+	 CompilationUnitDeclaration getCompilationUnitDeclaration() {
+		char[][] name = compoundName();
+		if (name.length == 0) return null;
+		ReferenceBinding binding = this.environment.getType(name);
+		if (!(binding instanceof SourceTypeBinding)) return null;
+		return ((SourceTypeBinding) binding).scope.compilationUnitScope().referenceContext;
+	 }
+	 
+	 /*
+	  * Returns the compiler binding corresponding to this key.
+	  * This key's scanner should be positioned on the top level type token.
+	  * Returns null otherwise.
+	  */
+	 Binding getCompilerBinding(CompilationUnitDeclaration parsedUnit) {
+	 	switch (this.scanner.token) {
+	 		case BindingKeyScanner.PACKAGE:
+	 			return new PackageBinding(this.compoundName, null, this.environment);
+	 		case BindingKeyScanner.TYPE:
+	 			if (this.compoundName.length == 1 && this.compoundName[0].length == 1) {
+	 				// case of base type
+		 			TypeBinding baseTypeBinding = getBaseTypeBinding(this.compoundName[0]);
+		 			if (baseTypeBinding != null) 
+	 					return getArrayBinding(this.dimension, baseTypeBinding);
+	 			}
+	 			if (parsedUnit == null) 
+	 				return getBinaryBinding();
+	 			char[] typeName = this.compoundName[this.compoundName.length-1];
+	 			int dim = this.dimension;
+	 			TypeBinding binding = getTypeBinding(parsedUnit, parsedUnit.types, typeName);
+	 			if (binding == null) return null;
+ 				TypeBinding typeBinding = null;
+ 				if (this.scanner.isAtParametersStart()) {
+					if (this.scanner.isAtTypeParameterStart())	 					
+	 					// generic type binding
+	 					typeBinding = getGenericTypeBinding((SourceTypeBinding) binding);
+	 				else if (this.scanner.isAtTypeStart() || this.scanner.isAtWildCardStart())
+ 						// parameterized type binding
+	 					typeBinding = getParameterizedTypeBinding((ReferenceBinding) binding, null/*no enclosing type*/); 
+ 				} else if (binding.typeVariables().length > 0)
+ 					// raw type binding
+ 					typeBinding = this.environment.createRawType((ReferenceBinding) binding, null/*no enclosing type*/);
+ 				else
+					// non-generic type binding
+					typeBinding = binding;
+	 			if (this.scanner.isAtFieldOrMethodStart()) {
+	 				switch (this.scanner.nextToken()) {
+		 				case BindingKeyScanner.FIELD:
+		 					return getFieldBinding(((ReferenceBinding) typeBinding).fields());
+		 				case BindingKeyScanner.METHOD:
+		 					MethodBinding methodBinding = getMethodBinding(((ReferenceBinding) typeBinding).methods());
+		 					if (this.scanner.isAtParametersStart())
+		 						// parameterized generic method binding
+		 						methodBinding = getParameterizedGenericMethodBinding(methodBinding);
+		 					if (this.scanner.isAtLocalVariableStart()) {
+		 						MethodScope methodScope = methodBinding.sourceMethod().scope;
+		 						return getLocalVariableBinding(methodScope);
+		 					} else
+		 						return methodBinding;
+	 				}
+	 				return null; // malformed key
+	 			} else {
+	 				return getArrayBinding(dim, typeBinding);
+	 			}
+	 	}
+	 	return null;
+	 }
+	 
+	 /*
+	  * Returns the compiler binding corresponding to this key.
+	  * Returns null is malformed.
+	  * This key's scanner should be positioned on the package token.
+	  */
+	 Binding getCompilerBinding() {
+		CompilationUnitDeclaration parsedUnit = getCompilationUnitDeclaration();
+		if (parsedUnit != null) {
+			char[] fileName = parsedUnit.compilationResult.getFileName();
+			// don't resolve a second time the same unit (this would create the same bindingd twice)
+			if (!this.resolver.requestedKeys.containsKey(fileName) && !this.resolver.requestedSources.containsKey(fileName))
+				this.resolver.process(parsedUnit, this.resolver.totalUnits+1);
+		}
+		return getCompilerBinding(parsedUnit);
+	 }
+
+	/*
+	 * Finds the field binding that corresponds to this key in the given field bindings.
+	 * Returns null if not found.
+	 * This key's scanner should be positioned on the field name.
+	 */
+	FieldBinding getFieldBinding(FieldBinding[] fields) {
+	 	if (fields == null) return null;
+	 	char[] fieldName = this.scanner.getTokenSource();
+	 	for (int i = 0, length = fields.length; i < length; i++) {
+			FieldBinding field = fields[i];
+			if (CharOperation.equals(fieldName, field.name)) 
+				return field;
+		}
+	 	return null;
+	 }
+	 
+	 /*
+	  * Ensures that the given generic type binding corresponds to this key.
+	  * This key's scanner should be positionned on the first type parameter name token.
+	  */
+	 SourceTypeBinding getGenericTypeBinding(SourceTypeBinding typeBinding) {
+	 	TypeVariableBinding[] typeVariableBindings = typeBinding.typeVariables();
+	 	for (int i = 0, length = typeVariableBindings.length; i < length; i++) {
+			TypeVariableBinding typeVariableBinding = typeVariableBindings[i];
+			if (this.scanner.nextToken() != BindingKeyScanner.TYPE)
+				return null;
+		 	char[] typeVariableName = this.scanner.getTokenSource();
+			if (!CharOperation.equals(typeVariableName, typeVariableBinding.sourceName()))
+				return null;
+		}
+	 	return typeBinding;
+	 }
+	 
+	 /*
+	  * Returns the string that this binding key wraps.
+	  */
+	 String getKey() {
+	 	return new String(this.scanner.source);
+	 }
+	 
+	 LocalVariableBinding getLocalVariableBinding(BlockScope scope) {
+	 	if (this.scanner.nextToken() != BindingKeyScanner.LOCAL_VAR)
+			return null; // malformed key
+		char[] varName = this.scanner.getTokenSource();
+		if (Character.isDigit(varName[0])) {
+			int index = Integer.parseInt(new String(varName));
+			if (index >= scope.subscopeCount)
+				return null; // malformed key
+			if (!this.scanner.isAtLocalVariableStart())
+				return null; // malformed key
+			return getLocalVariableBinding((BlockScope) scope.subscopes[index]);
+		} else {
+		 	for (int i = 0; i < scope.localIndex; i++) {
+				LocalVariableBinding local = scope.locals[i];
+				if (CharOperation.equals(varName, local.name))
+					return local;
+			}
+		}
+	 	return null;
+	 }
+	 
+	/*
+	 * Finds the method binding that corresponds to this key in the given method bindings.
+	 * Returns null if not found.
+	 * This key's scanner should be positioned on the selector token.
+	 */
+	 MethodBinding getMethodBinding(MethodBinding[] methods) {
+	 	if (methods == null) return null;
+	 	char[] selector = this.scanner.getTokenSource();
+	 	this.scanner.skipMethodSignature();
+	 	char[] signature = this.scanner.getTokenSource();
+	 	
+	 	nextMethod: for (int i = 0, methodLength = methods.length; i < methodLength; i++) {
+			MethodBinding method = methods[i];
+			if (CharOperation.equals(selector, method.selector) || (selector.length == 0 && method.isConstructor())) {
+				if (CharOperation.equals(signature, method.genericSignature()))
+					return method;
+				return method;
+			}
+		}
+	 	return null;
+	 }
+	 
+	 
+	 /*
+	  * Finds parameterized generic method binding that corresponds to this key.
+	  * This key's scanner should be positionned on the first type argument name token.
+	  */
+	 ParameterizedGenericMethodBinding getParameterizedGenericMethodBinding(MethodBinding methodBinding) {
+	 	int length = methodBinding.typeVariables().length;
+	 	TypeBinding[] arguments = new TypeBinding[length];
+	 	for (int i = 0; i < length; i++) {
+			reset();
+			Binding argument = getCompilerBinding();
+			if (argument == null) 
+				return null;
+			arguments[i] = (TypeBinding) argument;
+		}
+	 	return new ParameterizedGenericMethodBinding(methodBinding, arguments, this.environment);
+	 }
+	 
+	 /*
+	  * Finds parameterized type binding that corresponds to this key.
+	  * This key's scanner should be positionned on the first type argument name token.
+	  */
+	 ParameterizedTypeBinding getParameterizedTypeBinding(ReferenceBinding genericType, ReferenceBinding enclosingType) {
+	 	TypeVariableBinding[] typeVariableBindings = genericType.typeVariables();
+	 	int length = typeVariableBindings.length;
+	 	TypeBinding[] arguments = new TypeBinding[length];
+	 	for (int i = 0; i < length; i++) {
+	 		TypeBinding argument;
+	 		if (this.scanner.isAtWildCardStart()) {
+	 			argument = getWildCardBinding(genericType, i);
+	 		} else {
+				reset();
+				argument = (TypeBinding) getCompilerBinding();
+	 		}
+			if (argument == null) 
+				return this.environment.createRawType(genericType, enclosingType);
+			arguments[i] =argument;
+	 		
+		}
+	 	ParameterizedTypeBinding parameterizedTypeBinding = this.environment.createParameterizedType(genericType, arguments, enclosingType);
+	 	// skip ";>"
+	 	this.scanner.skipParametersEnd();
+	 	if (this.scanner.isAtMemberTypeStart() && this.scanner.nextToken() == BindingKeyScanner.TYPE) {
+	 		char[] typeName = this.scanner.getTokenSource();
+	 		ReferenceBinding memberType = genericType.getMemberType(typeName);
+	 		return getParameterizedTypeBinding(memberType, parameterizedTypeBinding);
+	 	} else {
+		 	return parameterizedTypeBinding;
+	 	}
+	 }
+	 
+	/*
+	 * Finds the type binding that corresponds to this key in the given type bindings.
+	 * Returns null if not found.
+	 * This key's scanner should be positioned on the type name token.
+	 */
+	 TypeBinding getTypeBinding(CompilationUnitDeclaration parsedUnit, TypeDeclaration[] types, char[] typeName) {
+	 	if (Character.isDigit(typeName[0])) {
+	 		// anonymous or local type
+	 		int nextToken = BindingKeyScanner.TYPE;
+	 		while (this.scanner.isAtMemberTypeStart()) 
+	 			nextToken = this.scanner.nextToken();
+	 		typeName = nextToken == BindingKeyScanner.END ? this.scanner.source : CharOperation.subarray(this.scanner.source, 0, this.scanner.index+1);
+	 		LocalTypeBinding[] localTypeBindings  = parsedUnit.localTypes;
+	 		for (int i = 0; i < parsedUnit.localTypeCount; i++)
+	 			if (CharOperation.equals(typeName, localTypeBindings[i].signature()))
+	 				return localTypeBindings[i];
+	 		return null;
+	 	} else {
+	 		// member type
+		 	if (types == null) return null;
+			for (int i = 0, length = types.length; i < length; i++) {
+				TypeDeclaration declaration = types[i];
+				if (CharOperation.equals(typeName, declaration.name)) {
+					if (this.scanner.isAtMemberTypeStart() && this.scanner.nextToken() == BindingKeyScanner.TYPE)
+						return getTypeBinding(parsedUnit, declaration.memberTypes, this.scanner.getTokenSource());
+					else
+						return declaration.binding;
+				}
+			}
+	 	}
+		return null;
+	 }
+	 
+	 TypeBinding getWildCardBinding(ReferenceBinding genericType, int rank) {
+	 	if (this.scanner.nextToken() != BindingKeyScanner.TYPE) return null;
+	 	char[] source = this.scanner.getTokenSource();
+	 	if (source.length == 0) return null; //malformed key
+	 	int kind = -1;
+	 	TypeBinding bound = null;
+	 	switch (source[0]) {
+		 	case '*':
+		 		kind = Wildcard.UNBOUND;
+		 		break;
+		 	case '+':
+		 		reset();
+		 		kind = Wildcard.EXTENDS;
+		 		bound = (TypeBinding) getCompilerBinding();
+		 		break;
+		 	case '-':
+		 		reset();
+		 		kind = Wildcard.SUPER;
+		 		bound = (TypeBinding) getCompilerBinding();
+		 		break;
+	 	}
+	 	if (kind == -1) return null; // malformed key
+ 		return this.environment.createWildcard(genericType, rank, bound, kind);
+	 }
+	 
+	 /*
+	  * Forget about this key's compound name and dimension.
+	  */
+	 void reset() {
+	 	this.compoundName = null;
+	 	this.dimension = 0;
+	 }
+	 
+	 public String toString() {
+		return getKey();
+	}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingKeyScanner.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingKeyScanner.java
new file mode 100644
index 0000000..9f45b2a
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingKeyScanner.java
@@ -0,0 +1,271 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+
+/**
+ * Internal class.
+ * @since 3.1
+ */
+class BindingKeyScanner {
+	
+	static final int START = -1;
+	static final int PACKAGE = 0;
+	static final int TYPE = 1;
+	static final int FIELD = 2;
+	static final int METHOD = 3;
+	static final int ARRAY = 4;
+	static final int TYPE_PARAMETER = 5;
+	static final int LOCAL_VAR = 6;
+	static final int END = 7;
+	
+	int index = 0, start;
+	char[] source;
+	int token = START;
+
+	BindingKeyScanner(char[] source) {
+		this.source = source;
+	}
+	
+	char[] getTokenSource() {
+		int length = this.index-this.start;
+		char[] result = new char[length];
+		System.arraycopy(this.source, this.start, result, 0, length);
+		return result;
+	}
+	
+	boolean isAtFieldOrMethodStart() {
+		return 
+			this.index+1 < this.source.length
+			&& this.source[this.index+1] == '.';
+	}
+	
+	boolean isAtLocalVariableStart() {
+		return 
+			this.index < this.source.length
+			&& this.source[this.index] == '#';
+	}
+	
+	boolean isAtMemberTypeStart() {
+		return 
+			this.index < this.source.length
+			&& (this.source[this.index] == '$'
+				|| (this.source[this.index] == '.' && this.source[this.index-1] == '>'));
+	}
+	
+	boolean isAtParametersStart() {
+		char currentChar;
+		return 
+			this.index > 0
+			&& this.index < this.source.length
+			&& ((currentChar = this.source[this.index]) == '<'
+				|| currentChar == '%');
+	}
+	
+	boolean isAtTypeParameterStart() {
+		return 
+			this.index+1 < this.source.length
+			&& this.source[this.index+1] == 'T';
+	}
+	
+	boolean isAtTypeStart() {
+		return this.index+1 < this.source.length && "LIZVCDBFJS[".indexOf(this.source[this.index+1]) != -1; //$NON-NLS-1$
+	}
+	
+	boolean isAtWildCardStart() {
+		return this.index+1 < this.source.length && "*+-".indexOf(this.source[this.index+1]) != -1; //$NON-NLS-1$
+	}
+	
+	int nextToken() {
+		int previousTokenEnd = this.index;
+		this.start = this.index;
+		int length = this.source.length;
+		while (this.index <= length) {
+			char currentChar = this.index == length ? Character.MIN_VALUE : this.source[this.index];
+			switch (currentChar) {
+				case 'B':
+				case 'C':
+				case 'D':
+				case 'F':
+				case 'I':
+				case 'J':
+				case 'S':
+				case 'V':
+				case 'Z':
+					// base type
+					if (this.index == previousTokenEnd) {
+						this.index++;
+						this.token = TYPE;
+						return this.token;
+					}
+					break;
+				case 'L':
+				case 'T':
+					if (this.index == previousTokenEnd) {
+						this.start = this.index+1;
+					}
+					break;
+				case ';':
+				case '$':
+					if (this.index == previousTokenEnd) {
+						this.start = this.index+1;
+						previousTokenEnd = this.start;
+					} else {
+						this.token = TYPE;
+						return this.token;
+					}
+					break;
+				case '.':
+				case '%':
+					this.start = this.index+1;
+					previousTokenEnd = this.start;
+					break;
+				case '[':
+					while (this.index < length && this.source[this.index] == '[')
+						this.index++;
+					this.token = ARRAY;
+					return this.token;
+				case '<':
+					if (this.index == previousTokenEnd) {
+						this.start = this.index+1;
+						previousTokenEnd = this.start;
+					} else if (this.start > 0) {
+						switch (this.source[this.start-1]) {
+							case '.':
+								if (this.source[this.start-2] == '>')
+									// case of member type where enclosing type is parameterized
+									this.token = TYPE;
+								else
+									this.token = METHOD;
+								return this.token;
+							default:
+								this.token = TYPE;
+								return this.token;
+						}
+					} 
+					break;
+				case '(':
+					this.token = METHOD;
+					return this.token;
+				case ')':
+					this.start = ++this.index;
+					this.token = END;
+					return this.token;
+				case ':':
+					this.token = TYPE_PARAMETER;
+					return this.token;
+				case '#':
+					if (this.index == previousTokenEnd) {
+						this.start = this.index+1;
+						previousTokenEnd = this.start;
+					} else {
+						this.token = LOCAL_VAR;
+						return this.token;
+					}
+					break;
+				case Character.MIN_VALUE:
+					switch (this.token) {
+						case START:
+							this.token = PACKAGE;
+							break;
+						case METHOD:
+						case LOCAL_VAR:
+							this.token = LOCAL_VAR;
+							break;
+						case TYPE:
+							if (this.index > this.start && this.source[this.start-1] == '.')
+								this.token = FIELD;
+							else
+								this.token = END;
+							break;
+						default:
+							this.token = END;
+							break;
+					}
+					return this.token;
+				case '*':
+				case '+':
+				case '-':
+					this.index++;
+					this.token = TYPE;
+					return this.token;
+			}
+			this.index++;
+		}
+		this.token = END;
+		return this.token;
+	}
+	
+	void skipMethodSignature() {
+		char currentChar;
+		while (this.index < this.source.length && (currentChar = this.source[this.index]) != '#' && currentChar != '%')
+			this.index++;
+	}
+	
+	void skipParametersEnd() {
+		while (this.index < this.source.length && this.source[this.index] != '>')
+			this.index++;
+		this.index++;
+	}
+	
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		switch (this.token) {
+			case START:
+				buffer.append("START: "); //$NON-NLS-1$
+				break;
+			case PACKAGE:
+				buffer.append("PACKAGE: "); //$NON-NLS-1$
+				break;
+			case TYPE:
+				buffer.append("TYPE: "); //$NON-NLS-1$
+				break;
+			case FIELD:
+				buffer.append("FIELD: "); //$NON-NLS-1$
+				break;
+			case METHOD:
+				buffer.append("METHOD: "); //$NON-NLS-1$
+				break;
+			case ARRAY:
+				buffer.append("ARRAY: "); //$NON-NLS-1$
+				break;
+			case TYPE_PARAMETER:
+				buffer.append("TYPE PARAMETER: "); //$NON-NLS-1$
+				break;
+			case LOCAL_VAR:
+				buffer.append("LOCAL VAR: "); //$NON-NLS-1$
+				break;
+			case END:
+				buffer.append("END: "); //$NON-NLS-1$
+				break;
+		}
+		if (this.index < 0) {
+			buffer.append("**"); //$NON-NLS-1$
+			buffer.append(this.source);
+		} else if (this.index <= this.source.length) {
+			buffer.append(CharOperation.subarray(this.source, 0, this.start));
+			buffer.append('*');
+			if (this.start <= this.index) {
+				buffer.append(CharOperation.subarray(this.source, this.start, this.index));
+				buffer.append('*');
+				buffer.append(CharOperation.subarray(this.source, this.index, this.source.length));
+			} else {
+				buffer.append('*');
+				buffer.append(CharOperation.subarray(this.source, this.start, this.source.length));
+			}
+		} else {
+			buffer.append(this.source);
+			buffer.append("**"); //$NON-NLS-1$
+		}
+		return buffer.toString();
+	}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java
index fb6b3d4..834c356 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java
@@ -12,6 +12,8 @@
 package org.eclipse.jdt.core.dom;
 
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
 
 /**
  * A binding resolver is an internal mechanism for figuring out the binding
@@ -25,7 +27,6 @@
  */
 class BindingResolver {
 	
-	protected long modificationCount;
 	/**
 	 * Creates a binding resolver.
 	 */
@@ -34,15 +35,6 @@
 	}
 
 	/**
-	 * Store the number of modifications done using the ast. This is used to validate
-	 * resolveBinding methods. If the number changed, all resolve bindings methods
-	 * simply return null.
-	 */
-	protected void storeModificationCount(long modificationCounter) {
-		this.modificationCount = modificationCounter;
-	}
-	
-	/**
 	 * Allows the user to store information about the given old/new pair of
 	 * AST nodes.
 	 * <p>
@@ -120,6 +112,16 @@
 	}
 
 	/**
+	 * Returns the compilation unit scope used by this binding resolver.
+	 * Returns <code>null</code> if none.
+	 * 
+	 * @return the compilation unit scope by this resolver, or <code>null</code> if none.
+	 */
+	public CompilationUnitScope scope() {
+		return null;
+	}
+	
+	/**
 	 * Resolves the given class or interface declaration and returns the binding
 	 * for it.
 	 * <p>
@@ -143,6 +145,29 @@
 	}
 	
 	/**
+	 * Resolves the given type parameter and returns the type binding for the
+	 * type parameter.
+	 * <p>
+	 * The implementation of <code>TypeParameter.resolveBinding</code> 
+	 * forwards to this method. How the declaration resolves is often a 
+	 * function of the context in which the declaration node is embedded as well
+	 * as the declaration subtree itself.
+	 * </p>
+	 * <p>
+	 * The default implementation of this method returns <code>null</code>.
+	 * Subclasses may reimplement.
+	 * </p>
+	 * 
+	 * @param typeParameter the type paramter of interest
+	 * @return the binding for the given type parameter, or <code>null</code>
+	 *    if no binding is available
+	 * @since 3.1
+	 */
+	ITypeBinding resolveTypeParameter(TypeParameter typeParameter) {
+		return null;
+	}
+	
+	/**
 	 * Resolves the given enum declaration and returns the binding
 	 * for it.
 	 * <p>
@@ -295,23 +320,6 @@
 	}
 	
 	/**
-	 * Resolves the loop variable of the given enhanced for statement and 
-	 * returns the binding for it.
-	 * <p>
-	 * The default implementation of this method returns <code>null</code>.
-	 * Subclasses may reimplement.
-	 * </p>
-	 * 
-	 * @param statement the enhanced for statement of interest
-	 * @return the binding for the loop variable for the given enhanced for
-	 *    statement, or <code>null</code> if no binding is available
-	 * @since 3.0
-	 */
-	IVariableBinding resolveVariable(EnhancedForStatement statement) {
-		return null;
-	}
-
-	/**
 	 * Resolves the given enum constant declaration and returns the binding for
 	 * the field.
 	 * <p>
@@ -351,7 +359,7 @@
 	 *    if no binding is available
 	 * @since 3.0
 	 */
-	IVariableBinding resolveMember(AnnotationTypeMemberDeclaration member) {
+	IMethodBinding resolveMember(AnnotationTypeMemberDeclaration member) {
 		return null;
 	}
 	
@@ -682,6 +690,16 @@
 	}
 	
 	/**
+	 * Returns the compiler lookup environment used by this binding resolver.
+	 * Returns <code>null</code> if none.
+	 * 
+	 * @return the lookup environment used by this resolver, or <code>null</code> if none.
+	 */
+	LookupEnvironment lookupEnvironment() {
+		return null;
+	}
+	
+	/**
 	 * Allows the user to update information about the given old/new pair of
 	 * AST nodes.
 	 * <p>
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Block.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Block.java
index cfe193e..c9afc2b 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Block.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Block.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -40,9 +41,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(Block.class);
-		addProperty(STATEMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(2);
+		createPropertyList(Block.class, properyList);
+		addProperty(STATEMENTS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BlockComment.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BlockComment.java
index 80b1ed3..583c9aa 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BlockComment.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BlockComment.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -41,8 +42,9 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(BlockComment.class);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(1);
+		createPropertyList(BlockComment.class, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BodyDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BodyDeclaration.java
index 8b4d8d6..28b614b 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BodyDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BodyDeclaration.java
@@ -80,7 +80,7 @@
 	
 	/**
 	 * Returns structural property descriptor for the "modifiers" property
-	 * of this node.
+	 * of this node as used in JLS2.
 	 * 
 	 * @return the property descriptor
 	 */
@@ -88,13 +88,25 @@
 
 	/**
 	 * Returns structural property descriptor for the "modifiers" property
-	 * of this node.
+	 * of this node as used in JLS3.
 	 * 
 	 * @return the property descriptor
 	 */
 	abstract ChildListPropertyDescriptor internalModifiers2Property();
 
 	/**
+	 * Returns structural property descriptor for the "modifiers" property
+	 * of this node as used in JLS3.
+	 * 
+	 * @return the property descriptor
+	 * @since 3.1
+	 */
+	public final ChildListPropertyDescriptor getModifiersProperty() {
+		// important: return property for AST.JLS3
+		return internalModifiers2Property();
+	}
+
+	/**
 	 * Returns structural property descriptor for the "javadoc" property
 	 * of this node.
 	 * 
@@ -103,6 +115,17 @@
 	abstract ChildPropertyDescriptor internalJavadocProperty();
 
 	/**
+	 * Returns structural property descriptor for the "javadoc" property
+	 * of this node.
+	 * 
+	 * @return the property descriptor
+	 * @since 3.1
+	 */
+	public final ChildPropertyDescriptor getJavadocProperty() {
+		return internalJavadocProperty();
+	}
+
+	/**
 	 * Creates and returns a structural property descriptor for the
 	 * "javadoc" property declared on the given concrete node type.
 	 * 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BooleanLiteral.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BooleanLiteral.java
index 39415a5..6a16ea2 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BooleanLiteral.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BooleanLiteral.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -41,9 +42,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(BooleanLiteral.class);
-		addProperty(BOOLEAN_VALUE_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(2);
+		createPropertyList(BooleanLiteral.class, properyList);
+		addProperty(BOOLEAN_VALUE_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BreakStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BreakStatement.java
index fff00bb..178e26b 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BreakStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BreakStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -40,9 +41,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(BreakStatement.class);
-		addProperty(LABEL_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(2);
+		createPropertyList(BreakStatement.class, properyList);
+		addProperty(LABEL_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CastExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CastExpression.java
index 5bbb22f..3643cc3 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CastExpression.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CastExpression.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -47,10 +48,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(CastExpression.class);
-		addProperty(TYPE_PROPERTY);
-		addProperty(EXPRESSION_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(3);
+		createPropertyList(CastExpression.class, properyList);
+		addProperty(TYPE_PROPERTY, properyList);
+		addProperty(EXPRESSION_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CatchClause.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CatchClause.java
index 79c3ce5..cca0527 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CatchClause.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CatchClause.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -47,10 +48,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(CatchClause.class);
-		addProperty(EXCEPTION_PROPERTY);
-		addProperty(BODY_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(3);
+		createPropertyList(CatchClause.class, properyList);
+		addProperty(EXCEPTION_PROPERTY, properyList);
+		addProperty(BODY_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CharacterLiteral.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CharacterLiteral.java
index bb695f1..c49e7be 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CharacterLiteral.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CharacterLiteral.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.eclipse.jdt.core.compiler.InvalidInputException;
@@ -39,9 +40,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(CharacterLiteral.class);
-		addProperty(ESCAPED_VALUE_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(2);
+		createPropertyList(CharacterLiteral.class, properyList);
+		addProperty(ESCAPED_VALUE_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ClassInstanceCreation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ClassInstanceCreation.java
index 51294e4..3b4fb0a 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ClassInstanceCreation.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ClassInstanceCreation.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -52,7 +53,7 @@
  * The first form is preferred when "A" is known to be a type (as opposed
  * to a package). However, a parser cannot always determine this. Clients
  * should be prepared to handle either rather than make assumptions.
- * (Note also that the first form became possible as of JLS2; only the second
+ * (Note also that the first form became possible as of JLS3; only the second
  * form existed in JLS2.)
  * </p>
  * 
@@ -120,20 +121,22 @@
 	private static final List PROPERTY_DESCRIPTORS_3_0;
 	
 	static {
-		createPropertyList(ClassInstanceCreation.class);
-		addProperty(EXPRESSION_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(ARGUMENTS_PROPERTY);
-		addProperty(ANONYMOUS_CLASS_DECLARATION_PROPERTY);
-		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList();
+		List properyList = new ArrayList(5);
+		createPropertyList(ClassInstanceCreation.class, properyList);
+		addProperty(EXPRESSION_PROPERTY, properyList);
+		addProperty(NAME_PROPERTY, properyList);
+		addProperty(ARGUMENTS_PROPERTY, properyList);
+		addProperty(ANONYMOUS_CLASS_DECLARATION_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
 		
-		createPropertyList(ClassInstanceCreation.class);
-		addProperty(EXPRESSION_PROPERTY);
-		addProperty(TYPE_ARGUMENTS_PROPERTY);
-		addProperty(TYPE_PROPERTY);
-		addProperty(ARGUMENTS_PROPERTY);
-		addProperty(ANONYMOUS_CLASS_DECLARATION_PROPERTY);
-		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList();
+		properyList = new ArrayList(6);
+		createPropertyList(ClassInstanceCreation.class, properyList);
+		addProperty(EXPRESSION_PROPERTY, properyList);
+		addProperty(TYPE_ARGUMENTS_PROPERTY, properyList);
+		addProperty(TYPE_PROPERTY, properyList);
+		addProperty(ARGUMENTS_PROPERTY, properyList);
+		addProperty(ANONYMOUS_CLASS_DECLARATION_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
index 6c91a95..aed0638 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
@@ -11,9 +11,9 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -81,11 +81,12 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(CompilationUnit.class);
-		addProperty(PACKAGE_PROPERTY);
-		addProperty(IMPORTS_PROPERTY);
-		addProperty(TYPES_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(4);
+		createPropertyList(CompilationUnit.class, properyList);
+		addProperty(PACKAGE_PROPERTY, properyList);
+		addProperty(IMPORTS_PROPERTY, properyList);
+		addProperty(TYPES_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
@@ -378,6 +379,7 @@
      * <li>annotation type member - an <code>AnnotationTypeMemberDeclaration</code></li>
      * <li>enum type - an <code>EnumDeclaration</code></li>
      * <li>enum constant - an <code>EnumConstantDeclaration</code></li>
+	 * <li>type variable - a <code>TypeParameter</code></li>
 	 * </ul>
 	 * </p>
 	 * <p>
@@ -426,6 +428,7 @@
      * <li>annotation type member - an <code>AnnotationTypeMemberDeclaration</code></li>
      * <li>enum type - an <code>EnumDeclaration</code></li>
      * <li>enum constant - an <code>EnumConstantDeclaration</code></li>
+	 * <li>type variable - a <code>TypeParameter</code></li>
 	 * </ul>
 	 * </p>
 	 * <p>
@@ -735,25 +738,7 @@
 			this.optionalCommentList = Collections.unmodifiableList(commentList);
 		}
 	}
-	
-	
-	/* (omit javadoc for this method)
-	 * Method declared on ASTNode.
-	 */
-	void appendDebugString(StringBuffer buffer) {
-		buffer.append("CompilationUnit"); //$NON-NLS-1$
-		// include the type names
-		buffer.append("["); //$NON-NLS-1$
-		for (Iterator it = types().iterator(); it.hasNext(); ) {
-			AbstractTypeDeclaration d = (AbstractTypeDeclaration) it.next();
-			buffer.append(d.getName().getIdentifier());
-			if (it.hasNext()) {
-				buffer.append(","); //$NON-NLS-1$
-			}
-		}
-		buffer.append("]"); //$NON-NLS-1$
-	}
-		
+
 	/* (omit javadoc for this method)
 	 * Method declared on ASTNode.
 	 */
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
index 5d40eb8..abf5207 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
@@ -14,13 +14,11 @@
 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.IJavaProject;
-//import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.WorkingCopyOwner;
-import org.eclipse.jdt.core.compiler.IProblem;
-import org.eclipse.jdt.internal.codeassist.ISearchRequestor;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.Compiler;
 import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
@@ -29,72 +27,42 @@
 import org.eclipse.jdt.internal.compiler.IProblemFactory;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.env.ISourceType;
-import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
 import org.eclipse.jdt.internal.compiler.parser.Parser;
-import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
-import org.eclipse.jdt.internal.core.BasicCompilationUnit;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
+import org.eclipse.jdt.internal.compiler.util.Util;
+import org.eclipse.jdt.internal.core.CancelableNameEnvironment;
+import org.eclipse.jdt.internal.core.CancelableProblemFactory;
 import org.eclipse.jdt.internal.core.JavaProject;
-import org.eclipse.jdt.internal.core.SearchableEnvironment;
+import org.eclipse.jdt.internal.core.NameLookup;
+import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
 import org.eclipse.jdt.internal.core.util.CommentRecorderParser;
 
 class CompilationUnitResolver extends Compiler {
 	
-	static class CancelableNameEnvironment extends SearchableEnvironment {
-		IProgressMonitor monitor;
-
-		CancelableNameEnvironment(JavaProject project, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException {
-			super(project, owner);
-			this.monitor = monitor;
-		}
-
-		private void checkCanceled() {
-			if (monitor != null && monitor.isCanceled()) 
-				throw new AbortCompilation(true/*silent*/, new OperationCanceledException());
-		}
-
-		public void findPackages(char[] prefix, ISearchRequestor requestor) {
-			checkCanceled();
-			super.findPackages(prefix, requestor);
-		}
-
-		public NameEnvironmentAnswer findType(char[] name, char[][] packageName) {
-			checkCanceled();
-			return super.findType(name, packageName);
-		}
-
-		public NameEnvironmentAnswer findType(char[][] compoundTypeName) {
-			checkCanceled();
-			return super.findType(compoundTypeName);
-		}
-
-		public void findTypes(char[] prefix, ISearchRequestor storage) {
-			checkCanceled();
-			super.findTypes(prefix, storage);
-		}
-	}
-
-	static class CancelableProblemFactory extends DefaultProblemFactory {
-		IProgressMonitor monitor;
-
-		CancelableProblemFactory(IProgressMonitor monitor) {
-			super();
-			this.monitor = monitor;
-		}
-
-		public IProblem createProblem(char[] originatingFileName, int problemId, String[] problemArguments, String[] messageArguments, int severity, int startPosition, int endPosition, int lineNumber) {
-			if (monitor != null && monitor.isCanceled()) 
-				throw new AbortCompilation(true/*silent*/, new OperationCanceledException());
-			return super.createProblem(originatingFileName, problemId, problemArguments, messageArguments, severity, startPosition, endPosition, lineNumber);
-		}
-	}
+	/*
+	 * The sources that were requested.
+	 * Map from file name (char[]) to ICompilationUnit.
+	 */
+	HashtableOfObject requestedSources;
+	
+	/*
+	 * The binding keys that were requested.
+	 * Map from file name (char[]) to BindingKey.
+	 */
+	HashtableOfObject requestedKeys;
+	
+	DefaultBindingResolver.BindingTables bindingTables;
 
 	/**
 	 * Answer a new CompilationUnitVisitor using the given name environment and compiler options.
@@ -144,25 +112,118 @@
 	/*
 	 * Add additional source types
 	 */
-	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
-		CompilationResult result =
-			new CompilationResult(sourceTypes[0].getFileName(), 1, 1, this.options.maxProblemsPerUnit);
-		// need to hold onto this
-		CompilationUnitDeclaration unit =
-			SourceTypeConverter.buildCompilationUnit(
-				sourceTypes,//sourceTypes[0] is always toplevel here
-				SourceTypeConverter.FIELD_AND_METHOD // need field and methods
-				| SourceTypeConverter.MEMBER_TYPE // need member types
-				| SourceTypeConverter.FIELD_INITIALIZATION, // need field initialization: see bug 40476
-				this.lookupEnvironment.problemReporter,
-				result);
-
-		if (unit != null) {
-			this.lookupEnvironment.buildTypeBindings(unit);
-			this.lookupEnvironment.completeTypeBindings(unit, true);
-		}
+	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+		// Need to reparse the entire source of the compilation unit so as to get source positions
+		// (case of processing a source that was not known by beginToCompile (e.g. when asking to createBinding))
+		SourceTypeElementInfo sourceType = (SourceTypeElementInfo) sourceTypes[0];
+		accept((org.eclipse.jdt.internal.compiler.env.ICompilationUnit) sourceType.getHandle().getCompilationUnit(), accessRestriction);
 	}
 
+	/**
+	 * Add the initial set of compilation units into the loop
+	 *  ->  build compilation unit declarations, their bindings and record their results.
+	 */
+	protected void beginToCompile(org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] sourceUnits, String[] bindingKeys) {
+		int sourceLength = sourceUnits.length;
+		int keyLength = bindingKeys.length;
+		int maxUnits = sourceLength + keyLength;
+		this.totalUnits = 0;
+		this.unitsToProcess = new CompilationUnitDeclaration[maxUnits];
+		int index = 0;
+
+		// walks the source units
+		this.requestedSources = new HashtableOfObject();
+		for (int i = 0; i < sourceLength; i++) {
+			org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = sourceUnits[i];
+			CompilationUnitDeclaration parsedUnit;
+			CompilationResult unitResult =
+				new CompilationResult(sourceUnit, index++, maxUnits, this.options.maxProblemsPerUnit);
+			try {
+				if (options.verbose) {
+					System.out.println(
+						Util.bind(
+							"compilation.request" , //$NON-NLS-1$
+							new String[] {
+								String.valueOf(index++ + 1),
+								String.valueOf(maxUnits),
+								new String(sourceUnit.getFileName())}));
+				}
+				// diet parsing for large collection of units
+				if (this.totalUnits < this.parseThreshold) {
+					parsedUnit = this.parser.parse(sourceUnit, unitResult);
+				} else {
+					parsedUnit = this.parser.dietParse(sourceUnit, unitResult);
+				}
+				// initial type binding creation
+				this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
+				addCompilationUnit(sourceUnit, parsedUnit);
+				this.requestedSources.put(unitResult.getFileName(), sourceUnit);
+			} finally {
+				sourceUnits[i] = null; // no longer hold onto the unit
+			}
+		}
+
+		// walk the binding keys
+		this.requestedKeys = new HashtableOfObject();
+		for (int i = 0; i < keyLength; i++) {
+			BindingKey bindingKey = new BindingKey(bindingKeys[i], this);
+			CompilationUnitDeclaration parsedUnit = bindingKey.getCompilationUnitDeclaration();
+			if (parsedUnit != null) {
+				this.requestedKeys.put(parsedUnit.compilationResult.getFileName(), bindingKey);
+			} else {
+				switch (bindingKey.scanner.token) {
+					case BindingKeyScanner.PACKAGE:
+						// package binding key
+						char[] pkgName = CharOperation.concatWith(bindingKey.compoundName(), '.');
+						this.requestedKeys.put(pkgName, bindingKey);
+						break;
+					case BindingKeyScanner.TYPE:
+						// base type binding
+						char[] key = bindingKey.scanner.source;
+						this.requestedKeys.put(key, bindingKey);
+						break;
+				}
+			}
+		}
+		
+		// binding resolution
+		lookupEnvironment.completeTypeBindings();
+	}
+	
+	IBinding createBinding(String key) {
+		if (this.bindingTables == null)
+			throw new RuntimeException("Cannot be called outside ASTParser#createASTs(...)"); //$NON-NLS-1$
+		BindingKey bindingKey = new BindingKey(key, this);
+		Binding compilerBinding = bindingKey.getCompilerBinding();
+		if (compilerBinding == null) return null;
+		DefaultBindingResolver resolver = new DefaultBindingResolver(this.lookupEnvironment, null/*no owner*/, this.bindingTables);
+		if (compilerBinding.kind() == Binding.ARRAY_TYPE) {
+			return new TypeBinding(resolver, (ArrayBinding) compilerBinding);
+		} else {
+			return resolver.getBinding(compilerBinding);
+		}
+	}
+	
+	public static ASTNode convert(CompilationUnitDeclaration compilationUnitDeclaration, char[] source, int apiLevel, Map options, boolean needToResolveBindings, WorkingCopyOwner owner, DefaultBindingResolver.BindingTables bindingTables, IProgressMonitor monitor) {
+		BindingResolver resolver = null;
+		AST ast = AST.newAST(apiLevel);
+		ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
+		CompilationUnit compilationUnit = null;
+		ASTConverter converter = new ASTConverter(options, needToResolveBindings, monitor);
+		if (needToResolveBindings) {
+			resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope, owner, bindingTables);
+		} else {
+			resolver = new BindingResolver();
+		}
+		ast.setBindingResolver(resolver);
+		converter.setAST(ast);
+		compilationUnit = converter.convert(compilationUnitDeclaration, source);
+		compilationUnit.setLineEndTable(compilationUnitDeclaration.compilationResult.lineSeparatorPositions);
+		ast.setDefaultNodeFlag(0);
+		ast.setOriginalModificationCount(ast.modificationCount());
+		return compilationUnit;
+	}
+	
 	/*
 	 *  Low-level API performing the actual compilation
 	 */
@@ -221,9 +282,46 @@
 		}
 	}	
 	
-	public static CompilationUnitDeclaration parse(char[] source, NodeSearcher nodeSearcher, Map settings) {
-		if (source == null) {
-			throw new IllegalArgumentException();
+	public static void parse(ICompilationUnit[] compilationUnits, ASTRequestor astRequestor, int apiLevel, Map options, IProgressMonitor monitor) {
+		CompilerOptions compilerOptions = new CompilerOptions(options);
+		Parser parser = new CommentRecorderParser(
+			new ProblemReporter(
+					DefaultErrorHandlingPolicies.proceedWithAllProblems(), 
+					compilerOptions, 
+					new DefaultProblemFactory()),
+			false);
+		for (int i = 0, length = compilationUnits.length; i < length; i++) {
+			org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) compilationUnits[i];
+			CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit);
+			CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, compilationResult);
+			
+			if (compilationUnitDeclaration.ignoreMethodBodies) {
+				compilationUnitDeclaration.ignoreFurtherInvestigation = true;
+				// if initial diet parse did not work, no need to dig into method bodies.
+				continue; 
+			}
+			
+			//fill the methods bodies in order for the code to be generated
+			//real parse of the method....
+			parser.scanner.setSource(compilationResult);
+			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
+			if (types != null) {
+				for (int j = types.length; --j >= 0;)
+					types[j].parseMethod(parser, compilationUnitDeclaration);
+			}
+			
+			// convert AST
+			ASTNode node = convert(compilationUnitDeclaration, sourceUnit.getContents(), apiLevel, options, false/*don't resolve binding*/, null/*no owner needed*/, null/*no binding table needed*/, monitor);
+			
+			
+			// accept AST
+			astRequestor.acceptAST(compilationUnits[i], (CompilationUnit) node);
+		}
+	}
+	
+	public static CompilationUnitDeclaration parse(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit, NodeSearcher nodeSearcher, Map settings) {
+		if (sourceUnit == null) {
+			throw new IllegalStateException();
 		}
 		CompilerOptions compilerOptions = new CompilerOptions(settings);
 		Parser parser = new CommentRecorderParser(
@@ -232,12 +330,8 @@
 					compilerOptions, 
 					new DefaultProblemFactory()),
 			false);
-		org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = 
-			new org.eclipse.jdt.internal.compiler.batch.CompilationUnit(
-				source, 
-				"", //$NON-NLS-1$
-				compilerOptions.defaultEncoding);
-		CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit));
+		CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit);
+		CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, compilationResult);
 		
 		if (compilationUnitDeclaration.ignoreMethodBodies) {
 			compilationUnitDeclaration.ignoreFurtherInvestigation = true;
@@ -246,6 +340,7 @@
 		}
 		
 		if (nodeSearcher != null) {
+			char[] source = sourceUnit.getContents();
 			int searchPosition = nodeSearcher.position;
 			if (searchPosition < 0 || searchPosition > source.length) {
 				// the position is out of range. There is no need to search for a node.
@@ -273,7 +368,7 @@
 		} else {
 			//fill the methods bodies in order for the code to be generated
 			//real parse of the method....
-			parser.scanner.setSource(source);
+			parser.scanner.setSource(compilationResult);
 			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
 			if (types != null) {
 				for (int i = types.length; --i >= 0;)
@@ -283,14 +378,49 @@
 		return compilationUnitDeclaration;
 	}
 
+	public static void resolve(
+		ICompilationUnit[] compilationUnits,
+		String[] bindingKeys,
+		ASTRequestor requestor,
+		int apiLevel,
+		Map options,
+		IJavaProject javaProject,
+		WorkingCopyOwner owner,
+		IProgressMonitor monitor) {
+	
+		CancelableNameEnvironment environment = null;
+		CancelableProblemFactory problemFactory = null;
+		try {
+			environment = new CancelableNameEnvironment(((JavaProject) javaProject), owner, monitor);
+			problemFactory = new CancelableProblemFactory(monitor);
+			CompilationUnitResolver resolver =
+				new CompilationUnitResolver(
+					environment,
+					getHandlingPolicy(),
+					options,
+					getRequestor(),
+					problemFactory);
+
+			resolver.resolve(compilationUnits, bindingKeys, requestor, apiLevel, options, owner, monitor);
+			if (NameLookup.VERBOSE)
+				System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
+		} catch (JavaModelException e) {
+			// project doesn't exist -> simple parse without resolving
+			parse(compilationUnits, requestor, apiLevel, options, monitor);
+		} finally {
+			if (environment != null) {
+				environment.monitor = null; // don't hold a reference to this external object
+			}
+			if (problemFactory != null) {
+				problemFactory.monitor = null; // don't hold a reference to this external object
+			}
+		}
+	}
 	public static CompilationUnitDeclaration resolve(
-		char[] source,
-		char[][] packageName,
-		String unitName,
+		org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
 		IJavaProject javaProject,
 		NodeSearcher nodeSearcher,
 		Map options,
-		boolean cleanUp,
 		WorkingCopyOwner owner,
 		IProgressMonitor monitor)
 		throws JavaModelException {
@@ -312,15 +442,13 @@
 			unit = 
 				resolver.resolve(
 					null, // no existing compilation unit declaration
-					new BasicCompilationUnit(
-						source,
-						packageName,
-						unitName,
-						javaProject),
+					sourceUnit,
 					nodeSearcher,
 					true, // method verification
 					true, // analyze code
 					true); // generate code					
+			if (NameLookup.VERBOSE)
+				System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
 			return unit;
 		} finally {
 			if (environment != null) {
@@ -329,9 +457,7 @@
 			if (problemFactory != null) {
 				problemFactory.monitor = null; // don't hold a reference to this external object
 			}
-			if (cleanUp && unit != null) {
-				unit.cleanUp();
-			}
+			// unit cleanup is done by caller
 		}
 	}
 	/*
@@ -376,6 +502,93 @@
 		}
 	}
 
+	private void resolve(ICompilationUnit[] compilationUnits, String[] bindingKeys, ASTRequestor astRequestor, int apiLevel, Map compilerOptions, WorkingCopyOwner owner, IProgressMonitor monitor) {
+	
+		// temporararily connect ourselves to the ASTResolver - must disconnect when done
+		astRequestor.compilationUnitResolver = this;
+		this.bindingTables = new DefaultBindingResolver.BindingTables();
+		CompilationUnitDeclaration unit = null;
+		int i = 0;
+		try {
+			int length = compilationUnits.length;
+			org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] sourceUnits = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[length];
+			System.arraycopy(compilationUnits, 0, sourceUnits, 0, length);
+			beginToCompile(sourceUnits, bindingKeys);
+			// process all units (some more could be injected in the loop by the lookup environment)
+			for (; i < this.totalUnits; i++) {
+				unit = this.unitsToProcess[i];
+				try {
+					process(unit, i);
+					
+					ICompilationUnit source = (ICompilationUnit) this.requestedSources.removeKey(unit.compilationResult.getFileName());
+					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*/, monitor);
+						BindingResolver resolver = new DefaultBindingResolver(unit.scope, owner, this.bindingTables);
+						ast.setBindingResolver(resolver);
+						converter.setAST(ast);
+						CompilationUnit compilationUnit = converter.convert(unit, contents);
+						compilationUnit.setLineEndTable(compilationResult.lineSeparatorPositions);
+						ast.setDefaultNodeFlag(0);
+						ast.setOriginalModificationCount(ast.modificationCount());
+						
+						// pass it to requestor
+						astRequestor.acceptAST(source, compilationUnit);
+					} 
+					
+					BindingKey bindingKey = (BindingKey) this.requestedKeys.removeKey(unit.compilationResult.getFileName());
+					if (bindingKey != null) {
+						Binding compilerBinding = bindingKey.getCompilerBinding(unit);
+						if (compilerBinding != null) {
+							DefaultBindingResolver resolver = new DefaultBindingResolver(unit.scope, owner, this.bindingTables);
+							IBinding binding = resolver.getBinding(compilerBinding);
+							
+							// pass it to requestor
+							if (binding != null)
+								astRequestor.acceptBinding(bindingKey.getKey(), binding);
+						}
+					}
+				} finally {
+					// cleanup compilation unit result
+					unit.cleanUp();
+				}
+				this.unitsToProcess[i] = null; // release reference to processed unit declaration
+				this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+			}
+			
+			// remaining binding keys
+			DefaultBindingResolver resolver = new DefaultBindingResolver(this.lookupEnvironment, owner, this.bindingTables);
+			Object[] keys = this.requestedKeys.valueTable;
+			for (int j = 0, keysLength = keys.length; j < keysLength; j++) {
+				BindingKey key = (BindingKey) keys[j];
+				if (key == null) continue;
+				Binding compilerBinding = key.getCompilerBinding();
+				if (compilerBinding != null) {
+					IBinding binding = resolver.getBinding(compilerBinding);
+					if (binding != null)
+						// pass it to requestor
+						astRequestor.acceptBinding(((BindingKey) this.requestedKeys.valueTable[j]).getKey(), binding);
+				}
+			}
+		} catch (AbortCompilation e) {
+			this.handleInternalException(e, unit);
+		} catch (Error e) {
+			this.handleInternalException(e, unit, null);
+			throw e; // rethrow
+		} catch (RuntimeException e) {
+			this.handleInternalException(e, unit, null);
+			throw e; // rethrow
+		} finally {
+			// disconnect ourselves from ast requestor
+            astRequestor.compilationUnitResolver = null;
+		}
+	}
+	
 	private CompilationUnitDeclaration resolve(
 			CompilationUnitDeclaration unit,
 			org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
@@ -394,7 +607,7 @@
 				unit = this.unitsToProcess[0];
 			} else {
 				// initial type binding creation
-				this.lookupEnvironment.buildTypeBindings(unit);
+				this.lookupEnvironment.buildTypeBindings(unit, null /*no access restriction*/);
 
 				// binding resolution
 				this.lookupEnvironment.completeTypeBindings();
@@ -409,6 +622,8 @@
 					
 					org.eclipse.jdt.internal.compiler.ast.ASTNode node = nodeSearcher.found;
 					
+					this.parser.scanner.setSource(unit.compilationResult);
+					
 		 			if (node != null) {
 						org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enclosingTypeDeclaration = nodeSearcher.enclosingType;
 		  				if (node instanceof AbstractMethodDeclaration) {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ConditionalExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ConditionalExpression.java
index c954a88..fe984b5 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ConditionalExpression.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ConditionalExpression.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -54,11 +55,12 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(ConditionalExpression.class);
-		addProperty(EXPRESSION_PROPERTY);
-		addProperty(THEN_EXPRESSION_PROPERTY);
-		addProperty(ELSE_EXPRESSION_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(4);
+		createPropertyList(ConditionalExpression.class, properyList);
+		addProperty(EXPRESSION_PROPERTY, properyList);
+		addProperty(THEN_EXPRESSION_PROPERTY, properyList);
+		addProperty(ELSE_EXPRESSION_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ConstructorInvocation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ConstructorInvocation.java
index cd4642d..6cb4532 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ConstructorInvocation.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ConstructorInvocation.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -62,14 +63,16 @@
 	private static final List PROPERTY_DESCRIPTORS_3_0;
 	
 	static {
-		createPropertyList(ConstructorInvocation.class);
-		addProperty(ARGUMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList();
+		List properyList = new ArrayList(2);
+		createPropertyList(ConstructorInvocation.class, properyList);
+		addProperty(ARGUMENTS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
 		
-		createPropertyList(ConstructorInvocation.class);
-		addProperty(TYPE_ARGUMENTS_PROPERTY);
-		addProperty(ARGUMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList();
+		properyList = new ArrayList(3);
+		createPropertyList(ConstructorInvocation.class, properyList);
+		addProperty(TYPE_ARGUMENTS_PROPERTY, properyList);
+		addProperty(ARGUMENTS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ContinueStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ContinueStatement.java
index 2a9ce72..06700aa 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ContinueStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ContinueStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -40,9 +41,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(ContinueStatement.class);
-		addProperty(LABEL_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(2);
+		createPropertyList(ContinueStatement.class, properyList);
+		addProperty(LABEL_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
index d1fe48e..392ccfa 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
@@ -14,6 +14,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import org.eclipse.jdt.core.WorkingCopyOwner;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
@@ -21,6 +22,7 @@
 import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
 import org.eclipse.jdt.internal.compiler.ast.ArrayReference;
 import org.eclipse.jdt.internal.compiler.ast.CharLiteral;
+import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
 import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
@@ -48,14 +50,15 @@
 import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
 import org.eclipse.jdt.internal.compiler.lookup.BaseTypes;
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.BindingIds;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
 import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
 
 /**
  * Internal class for resolving bindings using old ASTs.
@@ -71,15 +74,46 @@
  */
 class DefaultBindingResolver extends BindingResolver {
 	
-	private static final char[][] JAVA_LANG_STRINGBUFFER = new char[][] {"java".toCharArray(), "lang".toCharArray(), "StringBuffer".toCharArray()}; //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
-	private static final char[][] JAVA_LANG_EXCEPTION = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Exception".toCharArray()};//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
-
-	/**
-	 * This map is used to keep the correspondance between new bindings and the 
-	 * compiler bindings. This is an identity map. We should only create one object
-	 * for one binding.
+	/*
+	 * Holds on binding tables that can be shared by several ASTs.
 	 */
-	Map compilerBindingsToASTBindings;
+	static class BindingTables {
+	
+		/**
+		 * This map is used to get a binding from its binding key.
+		 */
+		Map bindingKeysToBindings;
+		/**
+		 * This map is used to keep the correspondance between new bindings and the 
+		 * compiler bindings. This is an identity map. We should only create one object
+		 * for one binding.
+		 */
+		Map compilerBindingsToASTBindings;
+		
+		BindingTables() {
+			this.compilerBindingsToASTBindings = new HashMap();
+			this.bindingKeysToBindings = new HashMap();
+		}
+	
+	}
+	private static final char[][] JAVA_LANG_EXCEPTION = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Exception".toCharArray()};//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+	
+	private static final char[][] JAVA_LANG_STRINGBUFFER = new char[][] {"java".toCharArray(), "lang".toCharArray(), "StringBuffer".toCharArray()}; //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+	
+	/**
+	 * This map is used to retrieve the corresponding block scope for a ast node
+	 */
+	Map astNodesToBlockScope;
+	
+	/**
+	 * This map is used to get an ast node from its binding (new binding)
+	 */
+	Map bindingsToAstNodes;
+	
+	/*
+	 * The shared binding tables accros ASTs.
+	 */
+	BindingTables bindingTables;
 	
 	/**
 	 * This map is used to retrieve an old ast node using the new ast node. This is not an
@@ -88,465 +122,259 @@
 	Map newAstToOldAst;
 	
 	/**
-	 * This map is used to get an ast node from its binding (new binding)
-	 */
-	Map bindingsToAstNodes;
-	
-	/**
-	 * This map is used to get an ast node from its binding key.
-	 */
-	Map bindingKeysToAstNodes;
-	
-	/**
-	 * This map is used to retrieve the corresponding block scope for a ast node
-	 */
-	Map astNodesToBlockScope;
-	
-	/**
 	 * Compilation unit scope
 	 */
 	private CompilationUnitScope scope;
 	
 	/**
-	 * Constructor for DefaultBindingResolver.
+	 * The working copy owner that defines the context in which this resolver is creating the bindings.
 	 */
-	DefaultBindingResolver() {
-		this.newAstToOldAst = new HashMap();
-		this.compilerBindingsToASTBindings = new HashMap();
-		this.bindingsToAstNodes = new HashMap();
-		this.astNodesToBlockScope = new HashMap();
-		this.bindingKeysToAstNodes = new HashMap();
-	}
+	WorkingCopyOwner workingCopyOwner;
 	
 	/**
 	 * Constructor for DefaultBindingResolver.
 	 */
-	DefaultBindingResolver(CompilationUnitScope scope) {
-		this();
+	DefaultBindingResolver(CompilationUnitScope scope, WorkingCopyOwner workingCopyOwner, BindingTables bindingTables) {
+		this.newAstToOldAst = new HashMap();
+		this.astNodesToBlockScope = new HashMap();
+		this.bindingsToAstNodes = new HashMap();
+		this.bindingTables = bindingTables;
 		this.scope = scope;
+		this.workingCopyOwner = workingCopyOwner;
 	}
-	
-	/*
-	 * Method declared on BindingResolver.
-	 */
-	synchronized IBinding resolveName(Name name) {
-		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(name);
-		int index = name.index;
-		if (node instanceof QualifiedNameReference) {
-			QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) node;
-			final char[][] tokens = qualifiedNameReference.tokens;
-			int qualifiedNameLength = tokens.length;
-			int indexInQualifiedName = qualifiedNameLength - index; // one-based
-			int indexOfFirstFieldBinding = qualifiedNameReference.indexOfFirstFieldBinding; // one-based
-			int otherBindingLength = qualifiedNameLength - indexOfFirstFieldBinding;
-			if (indexInQualifiedName < indexOfFirstFieldBinding) {
-				// a extra lookup is required
-				BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
-				Binding binding = null;
-				try {
-					if (internalScope == null) {
-						binding = this.scope.getTypeOrPackage(CharOperation.subarray(tokens, 0, indexInQualifiedName));
-					} else {
-						binding = internalScope.getTypeOrPackage(CharOperation.subarray(tokens, 0, indexInQualifiedName));
-					}
-				} catch (RuntimeException e) {
-					// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
-					// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
-					// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
-				}
-				if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding) {
-					return this.getPackageBinding((org.eclipse.jdt.internal.compiler.lookup.PackageBinding)binding);
-				} else if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
-					// it is a type
-					return this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)binding);
-				}
-			} else if (indexInQualifiedName == indexOfFirstFieldBinding) {
-				if (qualifiedNameReference.isTypeReference()) {
-					return this.getTypeBinding((ReferenceBinding)qualifiedNameReference.binding);
-				} else {
-					Binding binding = qualifiedNameReference.binding;
-					if (binding != null) {
-						if (binding.isValidBinding()) {
-							return this.getVariableBinding((org.eclipse.jdt.internal.compiler.lookup.VariableBinding) binding);				
-						} else {
-							if (binding instanceof ProblemFieldBinding) {
-								ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) binding;
-								switch(problemFieldBinding.problemId()) {
-									case ProblemReasons.NotVisible : 
-									case ProblemReasons.NonStaticReferenceInStaticContext :
-										ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
-										if (declaringClass != null) {
-											FieldBinding exactBinding = declaringClass.getField(tokens[tokens.length - 1], true /*resolve*/);
-											if (exactBinding != null) {
-												IVariableBinding variableBinding = (IVariableBinding) this.compilerBindingsToASTBindings.get(exactBinding);
-												if (variableBinding != null) {
-													return variableBinding;
-												}
-												variableBinding = new VariableBinding(this, exactBinding);
-												this.compilerBindingsToASTBindings.put(exactBinding, variableBinding);
-												return variableBinding;
-											}
-										}
-										break;
-								}
-							}
-						}
-					}
-				}
-			} else {
-				/* This is the case for a name which is part of a qualified name that
-				 * cannot be resolved. See PR 13063.
-				 */
-				if (qualifiedNameReference.otherBindings == null || (otherBindingLength - index - 1) < 0) {
-					return null;
-				} else {
-					return this.getVariableBinding(qualifiedNameReference.otherBindings[otherBindingLength - index - 1]);				
-				}
-			}
-		} else if (node instanceof QualifiedTypeReference) {
-			QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) node;
-			if (qualifiedTypeReference.resolvedType == null) {
-				return null;
-			}
-			if (index == 0) {
-				if (!qualifiedTypeReference.resolvedType.isValidBinding() && qualifiedTypeReference instanceof JavadocQualifiedTypeReference) {
-					JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) node;
-					if (typeRef.packageBinding != null) {
-						return getPackageBinding(typeRef.packageBinding);
-					}
-				}
-				return this.getTypeBinding(qualifiedTypeReference.resolvedType.leafComponentType());
-			} else {
-				int qualifiedTypeLength = qualifiedTypeReference.tokens.length;
-				int indexInQualifiedName = qualifiedTypeLength - index; // one-based
-				if (indexInQualifiedName >= 0) {
-					BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
-					Binding binding = null;
-					try {
-						if (internalScope == null) {
-							binding = this.scope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, indexInQualifiedName));
-						} else {
-							binding = internalScope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, indexInQualifiedName));
-						}
-					} catch (RuntimeException e) {
-						// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
-					}
-					if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding) {
-						return this.getPackageBinding((org.eclipse.jdt.internal.compiler.lookup.PackageBinding)binding);
-					} else if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
-						// it is a type
-						return this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)binding);
-					} else {
-						return null;
-					}
-				}
-			}
-		} else if (node instanceof ImportReference) {
-			ImportReference importReference = (ImportReference) node;
-			int importReferenceLength = importReference.tokens.length;
-			int indexInImportReference = importReferenceLength - index; // one-based
-			if (indexInImportReference >= 0) {
-				Binding binding = null;
-				try {
-					binding = this.scope.getTypeOrPackage(CharOperation.subarray(importReference.tokens, 0, indexInImportReference));
-				} catch (RuntimeException e) {
-					// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
-				}
-				if (binding != null) {
-					if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding) {
-						return this.getPackageBinding((org.eclipse.jdt.internal.compiler.lookup.PackageBinding)binding);
-					} else if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
-						// it is a type
-						return this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)binding);
-					} else {
-						return null;
-					}
-				}
-			}
-		} else if (node instanceof CompilationUnitDeclaration) {
-			CompilationUnitDeclaration compilationUnitDeclaration = (CompilationUnitDeclaration) node;
-			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
-			if (types == null || types.length == 0) {
-				return null;
-			}
-			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration type = types[0];
-			if (type != null) {
-				ITypeBinding typeBinding = this.getTypeBinding(type.binding);
-				if (typeBinding != null) {
-					return typeBinding.getPackage();
-				}
-			}
-		} else if (node instanceof AbstractMethodDeclaration) {
-			AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node;
-			if (methodDeclaration != null) {
-				IMethodBinding methodBinding = this.getMethodBinding(methodDeclaration.binding);
-				if (methodBinding != null) {
-					return methodBinding;
-				}
-			}
-		} else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
-			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
-			ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
-			if (typeBinding != null) {
-				return typeBinding;
-			}
-		} if (node instanceof SingleNameReference) {
-			SingleNameReference singleNameReference = (SingleNameReference) node;
-			if (singleNameReference.isTypeReference()) {
-				return this.getTypeBinding((ReferenceBinding)singleNameReference.binding);
-			} else {
-				// this is a variable or a field
-				Binding binding = singleNameReference.binding;
-				if (binding != null) {
-					if (binding.isValidBinding()) {
-						return this.getVariableBinding((org.eclipse.jdt.internal.compiler.lookup.VariableBinding) binding);				
-					} else {
-						/*
-						 * http://dev.eclipse.org/bugs/show_bug.cgi?id=24449
-						 */
-						if (binding instanceof ProblemFieldBinding) {
-							ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) binding;
-							switch(problemFieldBinding.problemId()) {
-								case ProblemReasons.NotVisible : 
-								case ProblemReasons.NonStaticReferenceInStaticContext :
-								case ProblemReasons.NonStaticReferenceInConstructorInvocation :
-									ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
-									FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
-									if (exactBinding != null) {
-										IVariableBinding variableBinding2 = (IVariableBinding) this.compilerBindingsToASTBindings.get(exactBinding);
-										if (variableBinding2 != null) {
-											return variableBinding2;
-										}
-										variableBinding2 = new VariableBinding(this, exactBinding);
-										this.compilerBindingsToASTBindings.put(exactBinding, variableBinding2);
-										return variableBinding2;
-									}
-									break;
-							}
-						}
-					}
-	 			}				
-			}
-		} else if (node instanceof QualifiedSuperReference) {
-			QualifiedSuperReference qualifiedSuperReference = (QualifiedSuperReference) node;
-			return this.getTypeBinding(qualifiedSuperReference.qualification.resolvedType);
-		} else if (node instanceof LocalDeclaration) {
-			return this.getVariableBinding(((LocalDeclaration)node).binding);
-		} else if (node instanceof FieldReference) {
-			return getVariableBinding(((FieldReference) node).binding);
-		} else if (node instanceof SingleTypeReference) {
-			SingleTypeReference singleTypeReference = (SingleTypeReference) node;
-			org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding = singleTypeReference.resolvedType;
-			if (binding != null) {
-				if (!binding.isValidBinding() && node instanceof JavadocSingleTypeReference) {
-					JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) node;
-					if (typeRef.packageBinding != null) {
-						return getPackageBinding(typeRef.packageBinding);
-					}
-				}
-				return this.getTypeBinding(binding.leafComponentType());
-			}
-		} else if (node instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) {
-			org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) node;
-			return this.getVariableBinding(fieldDeclaration.binding);
-		} else if (node instanceof MessageSend) {
-			MessageSend messageSend = (MessageSend) node;
-			return getMethodBinding(messageSend.binding);
-		} else if (node instanceof AllocationExpression) {
-			AllocationExpression allocation = (AllocationExpression) node;
-			return getMethodBinding(allocation.binding);
-		} else if (node instanceof ImplicitDocTypeReference) {
-			ImplicitDocTypeReference implicitRef = (ImplicitDocTypeReference) node;
-			return getTypeBinding(implicitRef.resolvedType);
-		}
-		return null;
+
+	DefaultBindingResolver(LookupEnvironment lookupEnvironment, WorkingCopyOwner workingCopyOwner, BindingTables bindingTables) {
+		this.newAstToOldAst = new HashMap();
+		this.astNodesToBlockScope = new HashMap();
+		this.bindingsToAstNodes = new HashMap();
+		this.bindingTables = bindingTables;
+		this.scope = new CompilationUnitScope(new CompilationUnitDeclaration(null, null, -1), lookupEnvironment);
+		this.workingCopyOwner = workingCopyOwner;
 	}
 
 	/*
 	 * Method declared on BindingResolver.
 	 */
-	synchronized ITypeBinding resolveType(Type type) {
-		// retrieve the old ast node
-		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(type);
-		org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding = null;
-		if (node != null) {
-			if (node instanceof TypeReference) {
-				TypeReference typeReference = (TypeReference) node;
-				binding = typeReference.resolvedType;
-			} else if (node instanceof SingleNameReference && ((SingleNameReference)node).isTypeReference()) {
-				binding = (org.eclipse.jdt.internal.compiler.lookup.TypeBinding) (((SingleNameReference)node).binding);
-			} else if (node instanceof QualifiedNameReference && ((QualifiedNameReference)node).isTypeReference()) {
-				binding = (org.eclipse.jdt.internal.compiler.lookup.TypeBinding) (((QualifiedNameReference)node).binding);
-			} else if (node instanceof ArrayAllocationExpression) {
-				binding = ((ArrayAllocationExpression) node).resolvedType;
-			}
-			if (binding != null) {
-				if (type.isArrayType()) {
-					ArrayType arrayType = (ArrayType) type;
-					if (binding.isArrayType()) {
-						ArrayBinding arrayBinding = (ArrayBinding) binding;
-						return getTypeBinding(this.scope.createArray(arrayBinding.leafComponentType, arrayType.getDimensions()));
-					} else {
-						return getTypeBinding(this.scope.createArray(binding, arrayType.getDimensions()));
-					}
-				} else {
-					if (binding.isArrayType()) {
-						ArrayBinding arrayBinding = (ArrayBinding) binding;
-						return getTypeBinding(arrayBinding.leafComponentType);
-					} else {
-						return getTypeBinding(binding);
-					}
+	synchronized ASTNode findDeclaringNode(IBinding binding) {
+		if (binding == null) {
+			return null;
+		}
+		return (ASTNode) this.bindingsToAstNodes.get(binding);
+	}
+	
+	synchronized ASTNode findDeclaringNode(String bindingKey) {
+		if (bindingKey == null) {
+			return null;
+		}
+		Object binding = this.bindingTables.bindingKeysToBindings.get(bindingKey);
+		if (binding == null) 
+			return null;
+		return (ASTNode) this.bindingsToAstNodes.get(binding);
+	}
+	
+	IBinding getBinding(org.eclipse.jdt.internal.compiler.lookup.Binding binding) {
+		switch (binding.kind()) {
+			case Binding.PACKAGE:
+				return getPackageBinding((org.eclipse.jdt.internal.compiler.lookup.PackageBinding) binding);
+			case Binding.TYPE:
+			case Binding.GENERIC_TYPE:
+			case Binding.PARAMETERIZED_TYPE:
+			case Binding.RAW_TYPE:
+				return getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding) binding);
+			case Binding.METHOD:
+				return getMethodBinding((org.eclipse.jdt.internal.compiler.lookup.MethodBinding) binding);
+			case Binding.FIELD:
+			case Binding.LOCAL:
+				return getVariableBinding((org.eclipse.jdt.internal.compiler.lookup.VariableBinding) binding);
+		}
+		return null;
+	}
+
+	synchronized org.eclipse.jdt.internal.compiler.ast.ASTNode getCorrespondingNode(ASTNode currentNode) {
+		return (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(currentNode);
+	} 
+	
+	/*
+	 * Method declared on BindingResolver.
+	 */
+	synchronized IMethodBinding getMethodBinding(org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding) {
+		if (methodBinding != null) {
+			if (methodBinding.isValidBinding()) {
+				IMethodBinding binding = (IMethodBinding) this.bindingTables.compilerBindingsToASTBindings.get(methodBinding);
+				if (binding != null) {
+					return binding;
+				}
+				binding = new MethodBinding(this, methodBinding);
+				this.bindingTables.compilerBindingsToASTBindings.put(methodBinding, binding);
+				return binding;
+			} else {
+				/*
+				 * http://dev.eclipse.org/bugs/show_bug.cgi?id=23597
+				 */
+				switch(methodBinding.problemId()) {
+					case ProblemReasons.NotVisible : 
+					case ProblemReasons.NonStaticReferenceInStaticContext :
+					case ProblemReasons.NonStaticReferenceInConstructorInvocation :
+						ReferenceBinding declaringClass = methodBinding.declaringClass;
+						if (declaringClass != null) {
+							org.eclipse.jdt.internal.compiler.lookup.MethodBinding exactBinding = declaringClass.getExactMethod(methodBinding.selector, methodBinding.parameters);
+							if (exactBinding != null) {
+								IMethodBinding binding = (IMethodBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
+								if (binding != null) {
+									return binding;
+								}
+								binding = new MethodBinding(this, exactBinding);
+								this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, binding);
+								return binding;
+							}
+						}
+						break;
 				}
 			}
-		} else if (type.isPrimitiveType()) {
-			/* Handle the void primitive type returned by getReturnType for a method declaration 
-			 * that is a constructor declaration. It prevents null from being returned
-			 */
-			if (((PrimitiveType) type).getPrimitiveTypeCode() == PrimitiveType.VOID) {
-				return this.getTypeBinding(BaseTypes.VoidBinding);
-			}
 		}
 		return null;
 	}
+	/*
+	 * Method declared on BindingResolver.
+	 */
+	synchronized IPackageBinding getPackageBinding(org.eclipse.jdt.internal.compiler.lookup.PackageBinding packageBinding) {
+		if (packageBinding == null || !packageBinding.isValidBinding()) {
+			return null;
+		}
+		IPackageBinding binding = (IPackageBinding) this.bindingTables.compilerBindingsToASTBindings.get(packageBinding);
+		if (binding != null) {
+			return binding;
+		}
+		binding = new PackageBinding(packageBinding);
+		this.bindingTables.compilerBindingsToASTBindings.put(packageBinding, binding);
+		return binding;
+	}
+		
+	/*
+	 * Method declared on BindingResolver.
+	 */
+	synchronized ITypeBinding getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.TypeBinding referenceBinding) {
+		if (referenceBinding == null) {
+			return null;
+		} else if (!referenceBinding.isValidBinding()) {
+			switch(referenceBinding.problemId()) {
+				case ProblemReasons.NotVisible : 
+				case ProblemReasons.NonStaticReferenceInStaticContext :
+					if (referenceBinding instanceof ProblemReferenceBinding) {
+						ProblemReferenceBinding problemReferenceBinding = (ProblemReferenceBinding) referenceBinding;
+						Binding binding2 = problemReferenceBinding.original;
+						if (binding2 != null && binding2 instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+							TypeBinding binding = (TypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(binding2);
+							if (binding != null) {
+								return binding;
+							}
+							binding = new TypeBinding(this, (org.eclipse.jdt.internal.compiler.lookup.TypeBinding) binding2);
+							this.bindingTables.compilerBindingsToASTBindings.put(binding2, binding);
+							return binding;
+						} 
+					}
+			}
+			return null;
+		} else {
+			TypeBinding binding = (TypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(referenceBinding);
+			if (binding != null) {
+				return binding;
+			}
+			binding = new TypeBinding(this, referenceBinding);
+			this.bindingTables.compilerBindingsToASTBindings.put(referenceBinding, binding);
+			return binding;
+		}
+	}
+	/*
+	 * Method declared on BindingResolver.
+	 */
+	synchronized IVariableBinding getVariableBinding(org.eclipse.jdt.internal.compiler.lookup.VariableBinding variableBinding) {
+ 		if (variableBinding != null) {
+	 		if (variableBinding.isValidBinding()) {
+				IVariableBinding binding = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(variableBinding);
+				if (binding != null) {
+					return binding;
+				}
+				binding = new VariableBinding(this, variableBinding);
+				this.bindingTables.compilerBindingsToASTBindings.put(variableBinding, binding);
+				return binding;
+	 		} else {
+				/*
+				 * http://dev.eclipse.org/bugs/show_bug.cgi?id=24449
+				 */
+				if (variableBinding instanceof ProblemFieldBinding) {
+					ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) variableBinding;
+					switch(problemFieldBinding.problemId()) {
+						case ProblemReasons.NotVisible : 
+						case ProblemReasons.NonStaticReferenceInStaticContext :
+						case ProblemReasons.NonStaticReferenceInConstructorInvocation :
+							ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
+							FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
+							if (exactBinding != null) {
+								IVariableBinding variableBinding2 = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
+								if (variableBinding2 != null) {
+									return variableBinding2;
+								}
+								variableBinding2 = new VariableBinding(this, exactBinding);
+								this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding2);
+								return variableBinding2;
+							}
+							break;
+					}
+				}
+	 		}
+ 		}
+		return null;
+	}
 	
 	/*
 	 * Method declared on BindingResolver.
 	 */
-	synchronized ITypeBinding resolveWellKnownType(String name) {
-		if (("boolean".equals(name))//$NON-NLS-1$
-			|| ("char".equals(name))//$NON-NLS-1$
-			|| ("byte".equals(name))//$NON-NLS-1$
-			|| ("short".equals(name))//$NON-NLS-1$
-			|| ("int".equals(name))//$NON-NLS-1$
-			|| ("long".equals(name))//$NON-NLS-1$
-			|| ("float".equals(name))//$NON-NLS-1$
-			|| ("double".equals(name))//$NON-NLS-1$
-			|| ("void".equals(name))) {//$NON-NLS-1$
-			return this.getTypeBinding(this.scope.getBaseType(name.toCharArray()));
-		} else if ("java.lang.Object".equals(name)) {//$NON-NLS-1$
-			return this.getTypeBinding(this.scope.getJavaLangObject());
-		} else if ("java.lang.String".equals(name)) {//$NON-NLS-1$
-			return this.getTypeBinding(this.scope.getJavaLangString());
-		} else if ("java.lang.StringBuffer".equals(name)) {//$NON-NLS-1$
-			return this.getTypeBinding(this.scope.getType(JAVA_LANG_STRINGBUFFER));
-		} else if ("java.lang.Throwable".equals(name)) {//$NON-NLS-1$
-			return this.getTypeBinding(this.scope.getJavaLangThrowable());
-		} else if ("java.lang.Exception".equals(name)) {//$NON-NLS-1$
-			return this.getTypeBinding(this.scope.getType(JAVA_LANG_EXCEPTION));
-		} else if ("java.lang.RuntimeException".equals(name)) {//$NON-NLS-1$
-			return this.getTypeBinding(this.scope.getJavaLangRuntimeException());
-		} else if ("java.lang.Error".equals(name)) {//$NON-NLS-1$
-			return this.getTypeBinding(this.scope.getJavaLangError());
-		} else if ("java.lang.Class".equals(name)) {//$NON-NLS-1$ 
-			return this.getTypeBinding(this.scope.getJavaLangClass());
-	    } else if ("java.lang.Cloneable".equals(name)) {//$NON-NLS-1$ 
-			return this.getTypeBinding(this.scope.getJavaLangCloneable());
-		} else if ("java.io.Serializable".equals(name)) {//$NON-NLS-1$ 
-			return this.getTypeBinding(this.scope.getJavaIoSerializable());
-		} else {
-			return null;
-		}
+	LookupEnvironment lookupEnvironment() {
+		return this.scope.environment();
 	}
-	/*
-	 * Method declared on BindingResolver.
+	
+	/**
+	 * @see org.eclipse.jdt.core.dom.BindingResolver#recordScope(ASTNode, BlockScope)
 	 */
-	synchronized ITypeBinding resolveType(TypeDeclaration type) {
-		final Object node = this.newAstToOldAst.get(type);
-		if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
-			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
-			if (typeDeclaration != null) {
-				ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
-				if (typeBinding == null) {
-					return null;
-				}
-				this.bindingsToAstNodes.put(typeBinding, type);
-				String key = typeBinding.getKey();
-				if (key != null) {
-					this.bindingKeysToAstNodes.put(key, type);				
-				}
-				return typeBinding;
-			}
+	synchronized void recordScope(ASTNode astNode, BlockScope blockScope) {
+		this.astNodesToBlockScope.put(astNode, blockScope);
+	}
+	
+	/*
+	 * @see BindingResolver#resolveConstructor(ClassInstanceCreation)
+	 */
+	synchronized IMethodBinding resolveConstructor(ClassInstanceCreation expression) {
+		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+		if (node != null && (node.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.IsAnonymousTypeMASK) != 0) {
+			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration anonymousLocalTypeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
+			return this.getMethodBinding(anonymousLocalTypeDeclaration.allocation.binding);
+		} else if (node instanceof AllocationExpression) {
+			return this.getMethodBinding(((AllocationExpression)node).binding);
 		}
 		return null;
 	}
+
 	/*
-	 * Method declared on BindingResolver.
+	 * @see BindingResolver#resolveConstructor(ConstructorInvocation)
 	 */
-	synchronized IMethodBinding resolveMethod(MethodDeclaration method) {
-		Object oldNode = this.newAstToOldAst.get(method);
-		if (oldNode instanceof AbstractMethodDeclaration) {
-			AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) oldNode;
-			if (methodDeclaration != null) {
-				IMethodBinding methodBinding = this.getMethodBinding(methodDeclaration.binding);
-				if (methodBinding == null) {
-					return null;
-				}
-				this.bindingsToAstNodes.put(methodBinding, method);
-				String key = methodBinding.getKey();
-				if (key != null) {
-					this.bindingKeysToAstNodes.put(key, method);				
-				}
-				return methodBinding;
-			}
+	synchronized IMethodBinding resolveConstructor(ConstructorInvocation expression) {
+		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+		if (node instanceof ExplicitConstructorCall) {
+			ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall) node;
+			return this.getMethodBinding(explicitConstructorCall.binding);
 		}
 		return null;
 	}
+
 	/*
-	 * Method declared on BindingResolver.
+	 * @see BindingResolver#resolveConstructor(SuperConstructorInvocation)
 	 */
-	synchronized IMethodBinding resolveMethod(MethodInvocation method) {
-		Object oldNode = this.newAstToOldAst.get(method);
-		if (oldNode instanceof MessageSend) {
-			MessageSend messageSend = (MessageSend) oldNode;
-			if (messageSend != null) {
-				return this.getMethodBinding(messageSend.binding);
-			}
-		}
-		return null;
-	}
-	/*
-	 * Method declared on BindingResolver.
-	 */
-	synchronized IMethodBinding resolveMethod(SuperMethodInvocation method) {
-		Object oldNode = this.newAstToOldAst.get(method);
-		if (oldNode instanceof MessageSend) {
-			MessageSend messageSend = (MessageSend) oldNode;
-			if (messageSend != null) {
-				return this.getMethodBinding(messageSend.binding);
-			}
-		}
-		return null;
-	}
-	/*
-	 * Method declared on BindingResolver.
-	 */
-	synchronized IVariableBinding resolveVariable(VariableDeclaration variable) {
-		final Object node = this.newAstToOldAst.get(variable);
-		if (node instanceof AbstractVariableDeclaration) {
-			AbstractVariableDeclaration abstractVariableDeclaration = (AbstractVariableDeclaration) node;
-			if (abstractVariableDeclaration instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) {
-				org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) abstractVariableDeclaration;
-				IVariableBinding variableBinding = this.getVariableBinding(fieldDeclaration.binding);
-				if (variableBinding == null) {
-					return null;
-				}
-				this.bindingsToAstNodes.put(variableBinding, variable);
-				String key = variableBinding.getKey();
-				if (key != null) {
-					this.bindingKeysToAstNodes.put(key, variable);				
-				}
-				return variableBinding;
-			}
-			IVariableBinding variableBinding = this.getVariableBinding(((LocalDeclaration) abstractVariableDeclaration).binding);
-			if (variableBinding == null) {
-				return null;
-			}
-			this.bindingsToAstNodes.put(variableBinding, variable);
-			String key = variableBinding.getKey();
-			if (key != null) {
-				this.bindingKeysToAstNodes.put(key, variable);				
-			}
-			return variableBinding;
+	synchronized IMethodBinding resolveConstructor(SuperConstructorInvocation expression) {
+		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+		if (node instanceof ExplicitConstructorCall) {
+			ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall) node;
+			return this.getMethodBinding(explicitConstructorCall.binding);
 		}
 		return null;
 	}
@@ -585,6 +413,8 @@
 					return (ITypeBinding) binding;
 				case IBinding.VARIABLE :
 					return ((IVariableBinding) binding).getType();
+				case IBinding.METHOD :
+					return ((IMethodBinding) binding).getReturnType();
 			}
 		} else if (expression instanceof ArrayInitializer) {
 			org.eclipse.jdt.internal.compiler.ast.ArrayInitializer oldAst = (org.eclipse.jdt.internal.compiler.ast.ArrayInitializer) this.newAstToOldAst.get(expression);
@@ -610,7 +440,8 @@
 		} else if (expression instanceof StringLiteral) {
 			return this.getTypeBinding(this.scope.getJavaLangString());
 		} else if (expression instanceof TypeLiteral) {
-			return this.getTypeBinding(this.scope.getJavaLangClass());
+			ClassLiteralAccess classLiteralAccess = (ClassLiteralAccess) this.newAstToOldAst.get(expression);
+			return this.getTypeBinding(classLiteralAccess.resolvedType);
 		} else if (expression instanceof BooleanLiteral) {
 			BooleanLiteral booleanLiteral = (BooleanLiteral) expression;
 			if (booleanLiteral.booleanValue()) {
@@ -688,6 +519,15 @@
 			if (type != null) {
 				return type.resolveBinding();
 			}
+		} else if (expression instanceof MarkerAnnotation) {
+			org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation markerAnnotation = (org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation) this.newAstToOldAst.get(expression);
+			return this.getTypeBinding(markerAnnotation.resolvedType);
+		} else if (expression instanceof NormalAnnotation) {
+			org.eclipse.jdt.internal.compiler.ast.NormalAnnotation normalAnnotation = (org.eclipse.jdt.internal.compiler.ast.NormalAnnotation) this.newAstToOldAst.get(expression);
+			return this.getTypeBinding(normalAnnotation.resolvedType);
+		} else if (expression instanceof SingleMemberAnnotation) {
+			org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation singleMemberAnnotation = (org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation) this.newAstToOldAst.get(expression);
+			return this.getTypeBinding(singleMemberAnnotation.resolvedType);
 		}
 		return null;
 	}
@@ -729,9 +569,9 @@
 			if (node instanceof ImportReference) {
 				ImportReference importReference = (ImportReference) node;
 				if (importReference.onDemand) {
-					Binding binding = this.scope.getTypeOrPackage(CharOperation.subarray(importReference.tokens, 0, importReference.tokens.length));
+					Binding binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, importReference.tokens.length), true, importReference.isStatic());
 					if (binding != null) {
-						if (binding.bindingType() == BindingIds.PACKAGE) {
+						if ((binding.kind() & Binding.PACKAGE) != 0) {
 							IPackageBinding packageBinding = this.getPackageBinding((org.eclipse.jdt.internal.compiler.lookup.PackageBinding) binding);
 							if (packageBinding == null) {
 								return null;
@@ -747,7 +587,7 @@
 						}
 					}
 				} else {
-					Binding binding = this.scope.getTypeOrPackage(importReference.tokens);
+					Binding binding = this.scope.getImport(importReference.tokens, false, importReference.isStatic());
 					if (binding != null && binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
 						ITypeBinding typeBinding = this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding) binding);
 						return typeBinding == null ? null : typeBinding;
@@ -761,6 +601,326 @@
 		}
 		return null;
 	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.BindingResolver#resolveMember(org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration)
+	 */
+	IMethodBinding resolveMember(AnnotationTypeMemberDeclaration declaration) {
+		Object oldNode = this.newAstToOldAst.get(declaration);
+		if (oldNode instanceof AbstractMethodDeclaration) {
+			AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) oldNode;
+			if (methodDeclaration != null) {
+				IMethodBinding methodBinding = this.getMethodBinding(methodDeclaration.binding);
+				if (methodBinding == null) {
+					return null;
+				}
+				this.bindingsToAstNodes.put(methodBinding, declaration);
+				String key = methodBinding.getKey();
+				if (key != null) {
+					this.bindingTables.bindingKeysToBindings.put(key, methodBinding);				
+				}
+				return methodBinding;
+			}
+		}
+		return null;
+	}
+	
+	/*
+	 * Method declared on BindingResolver.
+	 */
+	synchronized IMethodBinding resolveMethod(MethodDeclaration method) {
+		Object oldNode = this.newAstToOldAst.get(method);
+		if (oldNode instanceof AbstractMethodDeclaration) {
+			AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) oldNode;
+			if (methodDeclaration != null) {
+				IMethodBinding methodBinding = this.getMethodBinding(methodDeclaration.binding);
+				if (methodBinding == null) {
+					return null;
+				}
+				this.bindingsToAstNodes.put(methodBinding, method);
+				String key = methodBinding.getKey();
+				if (key != null) {
+					this.bindingTables.bindingKeysToBindings.put(key, methodBinding);				
+				}
+				return methodBinding;
+			}
+		}
+		return null;
+	}
+	/*
+	 * Method declared on BindingResolver.
+	 */
+	synchronized IMethodBinding resolveMethod(MethodInvocation method) {
+		Object oldNode = this.newAstToOldAst.get(method);
+		if (oldNode instanceof MessageSend) {
+			MessageSend messageSend = (MessageSend) oldNode;
+			if (messageSend != null) {
+				return this.getMethodBinding(messageSend.binding);
+			}
+		}
+		return null;
+	}
+	/*
+	 * Method declared on BindingResolver.
+	 */
+	synchronized IMethodBinding resolveMethod(SuperMethodInvocation method) {
+		Object oldNode = this.newAstToOldAst.get(method);
+		if (oldNode instanceof MessageSend) {
+			MessageSend messageSend = (MessageSend) oldNode;
+			if (messageSend != null) {
+				return this.getMethodBinding(messageSend.binding);
+			}
+		}
+		return null;
+	}
+	
+	/*
+	 * Method declared on BindingResolver.
+	 */
+	synchronized IBinding resolveName(Name name) {
+		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(name);
+		int index = name.index;
+		if (node instanceof QualifiedNameReference) {
+			QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) node;
+			final char[][] tokens = qualifiedNameReference.tokens;
+			int qualifiedNameLength = tokens.length;
+			int indexInQualifiedName = qualifiedNameLength - index; // one-based
+			int indexOfFirstFieldBinding = qualifiedNameReference.indexOfFirstFieldBinding; // one-based
+			int otherBindingLength = qualifiedNameLength - indexOfFirstFieldBinding;
+			if (indexInQualifiedName < indexOfFirstFieldBinding) {
+				// a extra lookup is required
+				BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
+				Binding binding = null;
+				try {
+					if (internalScope == null) {
+						binding = this.scope.getTypeOrPackage(CharOperation.subarray(tokens, 0, indexInQualifiedName));
+					} else {
+						binding = internalScope.getTypeOrPackage(CharOperation.subarray(tokens, 0, indexInQualifiedName));
+					}
+				} catch (RuntimeException e) {
+					// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+					// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+					// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+				}
+				if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding) {
+					return this.getPackageBinding((org.eclipse.jdt.internal.compiler.lookup.PackageBinding)binding);
+				} else if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+					// it is a type
+					return this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)binding);
+				}
+			} else if (indexInQualifiedName == indexOfFirstFieldBinding) {
+				if (qualifiedNameReference.isTypeReference()) {
+					return this.getTypeBinding((ReferenceBinding)qualifiedNameReference.binding);
+				} else {
+					Binding binding = qualifiedNameReference.binding;
+					if (binding != null) {
+						if (binding.isValidBinding()) {
+							return this.getVariableBinding((org.eclipse.jdt.internal.compiler.lookup.VariableBinding) binding);				
+						} else {
+							if (binding instanceof ProblemFieldBinding) {
+								ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) binding;
+								switch(problemFieldBinding.problemId()) {
+									case ProblemReasons.NotVisible : 
+									case ProblemReasons.NonStaticReferenceInStaticContext :
+										ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
+										if (declaringClass != null) {
+											FieldBinding exactBinding = declaringClass.getField(tokens[tokens.length - 1], true /*resolve*/);
+											if (exactBinding != null) {
+												IVariableBinding variableBinding = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
+												if (variableBinding != null) {
+													return variableBinding;
+												}
+												variableBinding = new VariableBinding(this, exactBinding);
+												this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding);
+												return variableBinding;
+											}
+										}
+										break;
+								}
+							}
+						}
+					}
+				}
+			} else {
+				/* This is the case for a name which is part of a qualified name that
+				 * cannot be resolved. See PR 13063.
+				 */
+				if (qualifiedNameReference.otherBindings == null || (otherBindingLength - index - 1) < 0) {
+					return null;
+				} else {
+					return this.getVariableBinding(qualifiedNameReference.otherBindings[otherBindingLength - index - 1]);				
+				}
+			}
+		} else if (node instanceof QualifiedTypeReference) {
+			QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) node;
+			if (qualifiedTypeReference.resolvedType == null) {
+				return null;
+			}
+			if (index == 0) {
+				if (!qualifiedTypeReference.resolvedType.isValidBinding() && qualifiedTypeReference instanceof JavadocQualifiedTypeReference) {
+					JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) node;
+					if (typeRef.packageBinding != null) {
+						return getPackageBinding(typeRef.packageBinding);
+					}
+				}
+				return this.getTypeBinding(qualifiedTypeReference.resolvedType.leafComponentType());
+			} else {
+				int qualifiedTypeLength = qualifiedTypeReference.tokens.length;
+				int indexInQualifiedName = qualifiedTypeLength - index; // one-based
+				if (indexInQualifiedName >= 0) {
+					BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
+					Binding binding = null;
+					try {
+						if (internalScope == null) {
+							binding = this.scope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, indexInQualifiedName));
+						} else {
+							binding = internalScope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, indexInQualifiedName));
+						}
+					} catch (RuntimeException e) {
+						// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+					}
+					if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding) {
+						return this.getPackageBinding((org.eclipse.jdt.internal.compiler.lookup.PackageBinding)binding);
+					} else if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+						// it is a type
+						return this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)binding);
+					} else {
+						return null;
+					}
+				}
+			}
+		} else if (node instanceof ImportReference) {
+			ImportReference importReference = (ImportReference) node;
+			int importReferenceLength = importReference.tokens.length;
+			int indexInImportReference = importReferenceLength - index; // one-based
+			if (indexInImportReference >= 0) {
+				Binding binding = null;
+				try {
+					binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, indexInImportReference), true, importReference.isStatic());
+				} catch (RuntimeException e) {
+					// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+				}
+				if (binding != null) {
+					if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding) {
+						return this.getPackageBinding((org.eclipse.jdt.internal.compiler.lookup.PackageBinding)binding);
+					} else if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+						// it is a type
+						return this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)binding);
+					} else {
+						return null;
+					}
+				}
+			}
+		} else if (node instanceof CompilationUnitDeclaration) {
+			CompilationUnitDeclaration compilationUnitDeclaration = (CompilationUnitDeclaration) node;
+			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
+			if (types == null || types.length == 0) {
+				return null;
+			}
+			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration type = types[0];
+			if (type != null) {
+				ITypeBinding typeBinding = this.getTypeBinding(type.binding);
+				if (typeBinding != null) {
+					return typeBinding.getPackage();
+				}
+			}
+		} else if (node instanceof AbstractMethodDeclaration) {
+			AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node;
+			if (methodDeclaration != null) {
+				IMethodBinding methodBinding = this.getMethodBinding(methodDeclaration.binding);
+				if (methodBinding != null) {
+					return methodBinding;
+				}
+			}
+		} else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
+			ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+			if (typeBinding != null) {
+				return typeBinding;
+			}
+		} if (node instanceof SingleNameReference) {
+			SingleNameReference singleNameReference = (SingleNameReference) node;
+			if (singleNameReference.isTypeReference()) {
+				return this.getTypeBinding((ReferenceBinding)singleNameReference.binding);
+			} else {
+				// this is a variable or a field
+				Binding binding = singleNameReference.binding;
+				if (binding != null) {
+					if (binding.isValidBinding()) {
+						return this.getVariableBinding((org.eclipse.jdt.internal.compiler.lookup.VariableBinding) binding);				
+					} else {
+						/*
+						 * http://dev.eclipse.org/bugs/show_bug.cgi?id=24449
+						 */
+						if (binding instanceof ProblemFieldBinding) {
+							ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) binding;
+							switch(problemFieldBinding.problemId()) {
+								case ProblemReasons.NotVisible : 
+								case ProblemReasons.NonStaticReferenceInStaticContext :
+								case ProblemReasons.NonStaticReferenceInConstructorInvocation :
+									ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
+									FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
+									if (exactBinding != null) {
+										IVariableBinding variableBinding2 = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
+										if (variableBinding2 != null) {
+											return variableBinding2;
+										}
+										variableBinding2 = new VariableBinding(this, exactBinding);
+										this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding2);
+										return variableBinding2;
+									}
+									break;
+							}
+						}
+					}
+	 			}				
+			}
+		} else if (node instanceof QualifiedSuperReference) {
+			QualifiedSuperReference qualifiedSuperReference = (QualifiedSuperReference) node;
+			return this.getTypeBinding(qualifiedSuperReference.qualification.resolvedType);
+		} else if (node instanceof LocalDeclaration) {
+			return this.getVariableBinding(((LocalDeclaration)node).binding);
+		} else if (node instanceof JavadocFieldReference) {
+			JavadocFieldReference fieldRef = (JavadocFieldReference) node;
+			if (fieldRef.methodBinding != null) {
+				return getMethodBinding(fieldRef.methodBinding);
+			}
+			return getVariableBinding(fieldRef.binding);
+		} else if (node instanceof FieldReference) {
+			return getVariableBinding(((FieldReference) node).binding);
+		} else if (node instanceof SingleTypeReference) {
+			SingleTypeReference singleTypeReference = (SingleTypeReference) node;
+			org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding = singleTypeReference.resolvedType;
+			if (binding != null) {
+				if (!binding.isValidBinding() && node instanceof JavadocSingleTypeReference) {
+					JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) node;
+					if (typeRef.packageBinding != null) {
+						return getPackageBinding(typeRef.packageBinding);
+					}
+				}
+				return this.getTypeBinding(binding.leafComponentType());
+			}
+		} else if (node instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) {
+			org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) node;
+			return this.getVariableBinding(fieldDeclaration.binding);
+		} else if (node instanceof MessageSend) {
+			MessageSend messageSend = (MessageSend) node;
+			return getMethodBinding(messageSend.binding);
+		} else if (node instanceof AllocationExpression) {
+			AllocationExpression allocation = (AllocationExpression) node;
+			return getMethodBinding(allocation.binding);
+		} else if (node instanceof ImplicitDocTypeReference) {
+			ImplicitDocTypeReference implicitRef = (ImplicitDocTypeReference) node;
+			return getTypeBinding(implicitRef.resolvedType);
+		} else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeParameter) {
+			org.eclipse.jdt.internal.compiler.ast.TypeParameter typeParameter = (org.eclipse.jdt.internal.compiler.ast.TypeParameter) node;
+			return this.getTypeBinding(typeParameter.binding);
+		} else if (node instanceof org.eclipse.jdt.internal.compiler.ast.MemberValuePair) {
+			org.eclipse.jdt.internal.compiler.ast.MemberValuePair memberValuePair = (org.eclipse.jdt.internal.compiler.ast.MemberValuePair) node;
+			return getMethodBinding(memberValuePair.binding);
+		}
+		return null;
+	}
 
 	/*
 	 * @see BindingResolver#resolvePackage(PackageDeclaration)
@@ -779,7 +939,7 @@
 					this.bindingsToAstNodes.put(packageBinding, pkg);
 					String key = packageBinding.getKey();
 					if (key != null) {
-						this.bindingKeysToAstNodes.put(key, pkg);				
+						this.bindingTables.bindingKeysToBindings.put(key, packageBinding);				
 					}
 					return packageBinding;
 				}
@@ -791,208 +951,60 @@
 		}
 		return null;
 	}
-
-	/*
-	 * Method declared on BindingResolver.
-	 */
-	synchronized ASTNode findDeclaringNode(IBinding binding) {
-		if (binding == null) {
-			return null;
-		}
-		return (ASTNode) this.bindingsToAstNodes.get(binding);
-	}
 	
-	synchronized ASTNode findDeclaringNode(String bindingKey) {
-		if (bindingKey == null) {
-			return null;
+	/* (non-Javadoc)
+	 * @see BindingResolver#resolveReference(MemberRef)
+     * @since 3.0
+	 */
+	synchronized IBinding resolveReference(MemberRef ref) {
+		org.eclipse.jdt.internal.compiler.ast.Expression expression = (org.eclipse.jdt.internal.compiler.ast.Expression) this.newAstToOldAst.get(ref);
+		if (expression instanceof TypeReference) {
+			return getTypeBinding(expression.resolvedType);
 		}
-		return (ASTNode) this.bindingKeysToAstNodes.get(bindingKey);
-	}
-		
-	/*
-	 * Method declared on BindingResolver.
-	 */
-	synchronized void store(ASTNode node, org.eclipse.jdt.internal.compiler.ast.ASTNode oldASTNode) {
-		this.newAstToOldAst.put(node, oldASTNode);
-	}
-	
-	/*
-	 * Method declared on BindingResolver.
-	 */
-	synchronized void updateKey(ASTNode node, ASTNode newNode) {
-		Object astNode = this.newAstToOldAst.remove(node);
-		if (astNode != null) {
-			this.newAstToOldAst.put(newNode, astNode);
-		}
-	}
-		
-	/*
-	 * Method declared on BindingResolver.
-	 */
-	synchronized ITypeBinding getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.TypeBinding referenceBinding) {
-		if (referenceBinding == null) {
-			return null;
-		} else if (!referenceBinding.isValidBinding()) {
-			switch(referenceBinding.problemId()) {
-				case ProblemReasons.NotVisible : 
-				case ProblemReasons.NonStaticReferenceInStaticContext :
-					if (referenceBinding instanceof ProblemReferenceBinding) {
-						ProblemReferenceBinding problemReferenceBinding = (ProblemReferenceBinding) referenceBinding;
-						Binding binding2 = problemReferenceBinding.original;
-						if (binding2 != null && binding2 instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
-							TypeBinding binding = (TypeBinding) this.compilerBindingsToASTBindings.get(binding2);
-							if (binding != null) {
-								return binding;
-							}
-							binding = new TypeBinding(this, (org.eclipse.jdt.internal.compiler.lookup.TypeBinding) binding2);
-							this.compilerBindingsToASTBindings.put(binding2, binding);
-							return binding;
-						} 
-					}
+		else if (expression instanceof JavadocFieldReference) {
+			JavadocFieldReference fieldRef = (JavadocFieldReference) expression;
+			if (fieldRef.methodBinding != null) {
+				return getMethodBinding(fieldRef.methodBinding);
 			}
-			return null;
-		} else {
-			TypeBinding binding = (TypeBinding) this.compilerBindingsToASTBindings.get(referenceBinding);
-			if (binding != null) {
-				return binding;
-			}
-			binding = new TypeBinding(this, referenceBinding);
-			this.compilerBindingsToASTBindings.put(referenceBinding, binding);
-			return binding;
-		}
-	}
-	/*
-	 * Method declared on BindingResolver.
-	 */
-	synchronized IPackageBinding getPackageBinding(org.eclipse.jdt.internal.compiler.lookup.PackageBinding packageBinding) {
-		if (packageBinding == null || !packageBinding.isValidBinding()) {
-			return null;
-		}
-		IPackageBinding binding = (IPackageBinding) this.compilerBindingsToASTBindings.get(packageBinding);
-		if (binding != null) {
-			return binding;
-		}
-		binding = new PackageBinding(packageBinding);
-		this.compilerBindingsToASTBindings.put(packageBinding, binding);
-		return binding;
-	}
-	/*
-	 * Method declared on BindingResolver.
-	 */
-	synchronized IVariableBinding getVariableBinding(org.eclipse.jdt.internal.compiler.lookup.VariableBinding variableBinding) {
- 		if (variableBinding != null) {
-	 		if (variableBinding.isValidBinding()) {
-				IVariableBinding binding = (IVariableBinding) this.compilerBindingsToASTBindings.get(variableBinding);
-				if (binding != null) {
-					return binding;
-				}
-				binding = new VariableBinding(this, variableBinding);
-				this.compilerBindingsToASTBindings.put(variableBinding, binding);
-				return binding;
-	 		} else {
-				/*
-				 * http://dev.eclipse.org/bugs/show_bug.cgi?id=24449
-				 */
-				if (variableBinding instanceof ProblemFieldBinding) {
-					ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) variableBinding;
-					switch(problemFieldBinding.problemId()) {
-						case ProblemReasons.NotVisible : 
-						case ProblemReasons.NonStaticReferenceInStaticContext :
-						case ProblemReasons.NonStaticReferenceInConstructorInvocation :
-							ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
-							FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
-							if (exactBinding != null) {
-								IVariableBinding variableBinding2 = (IVariableBinding) this.compilerBindingsToASTBindings.get(exactBinding);
-								if (variableBinding2 != null) {
-									return variableBinding2;
-								}
-								variableBinding2 = new VariableBinding(this, exactBinding);
-								this.compilerBindingsToASTBindings.put(exactBinding, variableBinding2);
-								return variableBinding2;
-							}
-							break;
-					}
-				}
-	 		}
- 		}
-		return null;
-	}
-	
-	/*
-	 * Method declared on BindingResolver.
-	 */
-	synchronized IMethodBinding getMethodBinding(org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding) {
-		if (methodBinding != null) {
-			if (methodBinding.isValidBinding()) {
-				IMethodBinding binding = (IMethodBinding) this.compilerBindingsToASTBindings.get(methodBinding);
-				if (binding != null) {
-					return binding;
-				}
-				binding = new MethodBinding(this, methodBinding);
-				this.compilerBindingsToASTBindings.put(methodBinding, binding);
-				return binding;
-			} else {
-				/*
-				 * http://dev.eclipse.org/bugs/show_bug.cgi?id=23597
-				 */
-				switch(methodBinding.problemId()) {
-					case ProblemReasons.NotVisible : 
-					case ProblemReasons.NonStaticReferenceInStaticContext :
-					case ProblemReasons.NonStaticReferenceInConstructorInvocation :
-						ReferenceBinding declaringClass = methodBinding.declaringClass;
-						if (declaringClass != null) {
-							org.eclipse.jdt.internal.compiler.lookup.MethodBinding exactBinding = declaringClass.getExactMethod(methodBinding.selector, methodBinding.parameters);
-							if (exactBinding != null) {
-								IMethodBinding binding = (IMethodBinding) this.compilerBindingsToASTBindings.get(exactBinding);
-								if (binding != null) {
-									return binding;
-								}
-								binding = new MethodBinding(this, exactBinding);
-								this.compilerBindingsToASTBindings.put(exactBinding, binding);
-								return binding;
-							}
-						}
-						break;
-				}
-			}
-		}
-		return null;
-	}
-	
-	/*
-	 * @see BindingResolver#resolveConstructor(ClassInstanceCreation)
-	 */
-	synchronized IMethodBinding resolveConstructor(ClassInstanceCreation expression) {
-		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
-		if (node != null && (node.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.IsAnonymousTypeMASK) != 0) {
-			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration anonymousLocalTypeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
-			return this.getMethodBinding(anonymousLocalTypeDeclaration.allocation.binding);
-		} else if (node instanceof AllocationExpression) {
-			return this.getMethodBinding(((AllocationExpression)node).binding);
+			return getVariableBinding(fieldRef.binding);
 		}
 		return null;
 	}
 
-	/*
-	 * @see BindingResolver#resolveConstructor(ConstructorInvocation)
+	/* (non-Javadoc)
+	 * @see BindingResolver#resolveReference(MethodRef)
+     * @since 3.0
 	 */
-	synchronized IMethodBinding resolveConstructor(ConstructorInvocation expression) {
-		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
-		if (node instanceof ExplicitConstructorCall) {
-			ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall) node;
-			return this.getMethodBinding(explicitConstructorCall.binding);
+	synchronized IBinding resolveReference(MethodRef ref) {
+		org.eclipse.jdt.internal.compiler.ast.Expression expression = (org.eclipse.jdt.internal.compiler.ast.Expression) this.newAstToOldAst.get(ref);
+		if (expression instanceof JavadocMessageSend) {
+			return this.getMethodBinding(((JavadocMessageSend)expression).binding);
+		}
+		else if (expression instanceof JavadocAllocationExpression) {
+			return this.getMethodBinding(((JavadocAllocationExpression)expression).binding);
 		}
 		return null;
 	}
-
-	/*
-	 * @see BindingResolver#resolveConstructor(SuperConstructorInvocation)
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.BindingResolver#resolveType(org.eclipse.jdt.core.dom.AnnotationTypeDeclaration)
 	 */
-	synchronized IMethodBinding resolveConstructor(SuperConstructorInvocation expression) {
-		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
-		if (node instanceof ExplicitConstructorCall) {
-			ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall) node;
-			return this.getMethodBinding(explicitConstructorCall.binding);
+	ITypeBinding resolveType(AnnotationTypeDeclaration type) {
+		final Object node = this.newAstToOldAst.get(type);
+		if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
+			if (typeDeclaration != null) {
+				ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+				if (typeBinding == null) {
+					return null;
+				}
+				this.bindingsToAstNodes.put(typeBinding, type);
+				String key = typeBinding.getKey();
+				if (key != null) {
+					this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
+				}
+				return typeBinding;
+			}
 		}
 		return null;
 	}
@@ -1011,7 +1023,7 @@
 				this.bindingsToAstNodes.put(typeBinding, type);
 				String key = typeBinding.getKey();
 				if (key != null) {
-					this.bindingKeysToAstNodes.put(key, type);				
+					this.bindingTables.bindingKeysToBindings.put(key, typeBinding);				
 				}
 				return typeBinding;
 			}
@@ -1019,99 +1031,232 @@
 		return null;
 	}
 
-	synchronized org.eclipse.jdt.internal.compiler.ast.ASTNode getCorrespondingNode(ASTNode currentNode) {
-		return (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(currentNode);
-	} 
-	/**
-	 * @see org.eclipse.jdt.core.dom.BindingResolver#recordScope(ASTNode, BlockScope)
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.BindingResolver#resolveType(org.eclipse.jdt.core.dom.EnumDeclaration)
 	 */
-	synchronized void recordScope(ASTNode astNode, BlockScope blockScope) {
-		this.astNodesToBlockScope.put(astNode, blockScope);
+	ITypeBinding resolveType(EnumDeclaration type) {
+		final Object node = this.newAstToOldAst.get(type);
+		if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
+			if (typeDeclaration != null) {
+				ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+				if (typeBinding == null) {
+					return null;
+				}
+				this.bindingsToAstNodes.put(typeBinding, type);
+				String key = typeBinding.getKey();
+				if (key != null) {
+					this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
+				}
+				return typeBinding;
+			}
+		}
+		return null;
+	}
+
+	/*
+	 * Method declared on BindingResolver.
+	 */
+	synchronized ITypeBinding resolveType(Type type) {
+		// retrieve the old ast node
+		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(type);
+		org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding = null;
+		if (node != null) {
+			if (node instanceof TypeReference) {
+				TypeReference typeReference = (TypeReference) node;
+				binding = typeReference.resolvedType;
+			} else if (node instanceof SingleNameReference && ((SingleNameReference)node).isTypeReference()) {
+				binding = (org.eclipse.jdt.internal.compiler.lookup.TypeBinding) (((SingleNameReference)node).binding);
+			} else if (node instanceof QualifiedNameReference && ((QualifiedNameReference)node).isTypeReference()) {
+				binding = (org.eclipse.jdt.internal.compiler.lookup.TypeBinding) (((QualifiedNameReference)node).binding);
+			} else if (node instanceof ArrayAllocationExpression) {
+				binding = ((ArrayAllocationExpression) node).resolvedType;
+			}
+			if (binding != null) {
+				if (type.isArrayType()) {
+					ArrayType arrayType = (ArrayType) type;
+					if (binding.isArrayType()) {
+						ArrayBinding arrayBinding = (ArrayBinding) binding;
+						return getTypeBinding(this.scope.createArrayType(arrayBinding.leafComponentType, arrayType.getDimensions()));
+					} else {
+						return getTypeBinding(this.scope.createArrayType(binding, arrayType.getDimensions()));
+					}
+				} else {
+					if (binding.isArrayType()) {
+						ArrayBinding arrayBinding = (ArrayBinding) binding;
+						return getTypeBinding(arrayBinding.leafComponentType);
+					} else {
+						return getTypeBinding(binding);
+					}
+				}
+			}
+		} else if (type.isPrimitiveType()) {
+			/* Handle the void primitive type returned by getReturnType for a method declaration 
+			 * that is a constructor declaration. It prevents null from being returned
+			 */
+			if (((PrimitiveType) type).getPrimitiveTypeCode() == PrimitiveType.VOID) {
+				return this.getTypeBinding(BaseTypes.VoidBinding);
+			}
+		}
+		return null;
+	}
+	/*
+	 * Method declared on BindingResolver.
+	 */
+	synchronized ITypeBinding resolveType(TypeDeclaration type) {
+		final Object node = this.newAstToOldAst.get(type);
+		if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
+			if (typeDeclaration != null) {
+				ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+				if (typeBinding == null) {
+					return null;
+				}
+				this.bindingsToAstNodes.put(typeBinding, type);
+				String key = typeBinding.getKey();
+				if (key != null) {
+					this.bindingTables.bindingKeysToBindings.put(key, typeBinding);				
+				}
+				return typeBinding;
+			}
+		}
+		return null;
+	}
+	
+	synchronized ITypeBinding resolveTypeParameter(TypeParameter typeParameter) {
+		final Object node = this.newAstToOldAst.get(typeParameter);
+		if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeParameter) {
+			org.eclipse.jdt.internal.compiler.ast.TypeParameter typeParameter2 = (org.eclipse.jdt.internal.compiler.ast.TypeParameter) node;
+			if (typeParameter2 != null) {
+				ITypeBinding typeBinding = this.getTypeBinding(typeParameter2.binding);
+				if (typeBinding == null) {
+					return null;
+				}
+				this.bindingsToAstNodes.put(typeBinding, typeParameter);
+				String key = typeBinding.getKey();
+				if (key != null) {
+					this.bindingTables.bindingKeysToBindings.put(key, typeBinding);				
+				}
+				return typeBinding;
+			}
+		}
+		return null;
 	}
 	
 	/* (non-Javadoc)
-	 * @see BindingResolver#resolveReference(MemberRef)
-     * @since 3.0
+	 * @see org.eclipse.jdt.core.dom.BindingResolver#resolveVariable(org.eclipse.jdt.core.dom.EnumConstantDeclaration)
 	 */
-	synchronized IBinding resolveReference(MemberRef ref) {
-		/*
-		if (ref.getParent() != null) {
-			Javadoc docComment = ref.getJavadoc();
-			if (docComment != null) {
-				org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc = (org.eclipse.jdt.internal.compiler.ast.Javadoc) this.newAstToOldAst.get(docComment);
-				if (javadoc != null) {
-					int start = ref.getStartPosition();
-					// search for compiler ast nodes with same position
-					if (ref.getName() == null) {
-						for (int i=0; i<javadoc.thrownExceptions.length; i++) {
-							TypeReference typeRef = javadoc.thrownExceptions[i];
-							if (typeRef.sourceStart==start) {
-								return getTypeBinding(typeRef.resolvedType);
-							}
-						}
-					}
-					for (int i=0; i<javadoc.references.length; i++) {
-						org.eclipse.jdt.internal.compiler.ast.Expression expression = javadoc.references[i];
-						if (expression.sourceStart==start) {
-							if (expression instanceof TypeReference) {
-								return getTypeBinding(expression.resolvedType);
-							}
-							else if (expression instanceof JavadocFieldReference) {
-								return getVariableBinding(((JavadocFieldReference)expression).binding);
-							}
-						}
-					}
-				}
+	synchronized IVariableBinding resolveVariable(EnumConstantDeclaration enumConstant) {
+		final Object node = this.newAstToOldAst.get(enumConstant);
+		if (node instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) {
+			org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) node;
+			IVariableBinding variableBinding = this.getVariableBinding(fieldDeclaration.binding);
+			if (variableBinding == null) {
+				return null;
 			}
-		}
-		*/
-		org.eclipse.jdt.internal.compiler.ast.Expression expression = (org.eclipse.jdt.internal.compiler.ast.Expression) this.newAstToOldAst.get(ref);
-		if (expression instanceof TypeReference) {
-			return getTypeBinding(expression.resolvedType);
-		}
-		else if (expression instanceof JavadocFieldReference) {
-			return getVariableBinding(((JavadocFieldReference)expression).binding);
+			this.bindingsToAstNodes.put(variableBinding, enumConstant);
+			String key = variableBinding.getKey();
+			if (key != null) {
+				this.bindingTables.bindingKeysToBindings.put(key, variableBinding);				
+			}
+			return variableBinding;
 		}
 		return null;
 	}
-
-	/* (non-Javadoc)
-	 * @see BindingResolver#resolveReference(MethodRef)
-     * @since 3.0
+	/*
+	 * Method declared on BindingResolver.
 	 */
-	synchronized IBinding resolveReference(MethodRef ref) {
-		/*
-		if (ref.getParent() != null) {
-			Javadoc docComment = ref.getJavadoc();
-			if (docComment != null) {
-				org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc = (org.eclipse.jdt.internal.compiler.ast.Javadoc) this.newAstToOldAst.get(docComment);
-				if (javadoc != null) {
-					int start = ref.getStartPosition();
-					// search for compiler ast nodes with same position
-					org.eclipse.jdt.internal.compiler.lookup.MethodBinding binding = null;
-					for (int i=0; binding==null && i<javadoc.references.length; i++) {
-						org.eclipse.jdt.internal.compiler.ast.Expression expression = javadoc.references[i];
-						if (expression.sourceStart==start) {
-							if (expression instanceof JavadocMessageSend) {
-								return this.getMethodBinding(((JavadocMessageSend)expression).binding);
-							}
-							else if (expression instanceof JavadocAllocationExpression) {
-								return this.getMethodBinding(((JavadocAllocationExpression)expression).binding);
-							}
-						}
-					}
+	synchronized IVariableBinding resolveVariable(VariableDeclaration variable) {
+		final Object node = this.newAstToOldAst.get(variable);
+		if (node instanceof AbstractVariableDeclaration) {
+			AbstractVariableDeclaration abstractVariableDeclaration = (AbstractVariableDeclaration) node;
+			if (abstractVariableDeclaration instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) {
+				org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) abstractVariableDeclaration;
+				IVariableBinding variableBinding = this.getVariableBinding(fieldDeclaration.binding);
+				if (variableBinding == null) {
+					return null;
 				}
+				this.bindingsToAstNodes.put(variableBinding, variable);
+				String key = variableBinding.getKey();
+				if (key != null) {
+					this.bindingTables.bindingKeysToBindings.put(key, variableBinding);				
+				}
+				return variableBinding;
 			}
-		}
-		*/
-		org.eclipse.jdt.internal.compiler.ast.Expression expression = (org.eclipse.jdt.internal.compiler.ast.Expression) this.newAstToOldAst.get(ref);
-		if (expression instanceof JavadocMessageSend) {
-			return this.getMethodBinding(((JavadocMessageSend)expression).binding);
-		}
-		else if (expression instanceof JavadocAllocationExpression) {
-			return this.getMethodBinding(((JavadocAllocationExpression)expression).binding);
+			IVariableBinding variableBinding = this.getVariableBinding(((LocalDeclaration) abstractVariableDeclaration).binding);
+			if (variableBinding == null) {
+				return null;
+			}
+			this.bindingsToAstNodes.put(variableBinding, variable);
+			String key = variableBinding.getKey();
+			if (key != null) {
+				this.bindingTables.bindingKeysToBindings.put(key, variableBinding);				
+			}
+			return variableBinding;
 		}
 		return null;
 	}
-
+	
+	/*
+	 * Method declared on BindingResolver.
+	 */
+	synchronized ITypeBinding resolveWellKnownType(String name) {
+		if (("boolean".equals(name))//$NON-NLS-1$
+			|| ("char".equals(name))//$NON-NLS-1$
+			|| ("byte".equals(name))//$NON-NLS-1$
+			|| ("short".equals(name))//$NON-NLS-1$
+			|| ("int".equals(name))//$NON-NLS-1$
+			|| ("long".equals(name))//$NON-NLS-1$
+			|| ("float".equals(name))//$NON-NLS-1$
+			|| ("double".equals(name))//$NON-NLS-1$
+			|| ("void".equals(name))) {//$NON-NLS-1$
+			return this.getTypeBinding(Scope.getBaseType(name.toCharArray()));
+		} else if ("java.lang.Object".equals(name)) {//$NON-NLS-1$
+			return this.getTypeBinding(this.scope.getJavaLangObject());
+		} else if ("java.lang.String".equals(name)) {//$NON-NLS-1$
+			return this.getTypeBinding(this.scope.getJavaLangString());
+		} else if ("java.lang.StringBuffer".equals(name)) {//$NON-NLS-1$
+			return this.getTypeBinding(this.scope.getType(JAVA_LANG_STRINGBUFFER, 3));
+		} else if ("java.lang.Throwable".equals(name)) {//$NON-NLS-1$
+			return this.getTypeBinding(this.scope.getJavaLangThrowable());
+		} else if ("java.lang.Exception".equals(name)) {//$NON-NLS-1$
+			return this.getTypeBinding(this.scope.getType(JAVA_LANG_EXCEPTION, 3));
+		} else if ("java.lang.RuntimeException".equals(name)) {//$NON-NLS-1$
+			return this.getTypeBinding(this.scope.getJavaLangRuntimeException());
+		} else if ("java.lang.Error".equals(name)) {//$NON-NLS-1$
+			return this.getTypeBinding(this.scope.getJavaLangError());
+		} else if ("java.lang.Class".equals(name)) {//$NON-NLS-1$ 
+			return this.getTypeBinding(this.scope.getJavaLangClass());
+	    } else if ("java.lang.Cloneable".equals(name)) {//$NON-NLS-1$ 
+			return this.getTypeBinding(this.scope.getJavaLangCloneable());
+		} else if ("java.io.Serializable".equals(name)) {//$NON-NLS-1$ 
+			return this.getTypeBinding(this.scope.getJavaIoSerializable());
+		} else {
+			return null;
+		}
+	}
+	
+	/*
+	 * Method declared on BindingResolver.
+	 */
+	public CompilationUnitScope scope() {
+		return this.scope;
+	}
+		
+	/*
+	 * Method declared on BindingResolver.
+	 */
+	synchronized void store(ASTNode node, org.eclipse.jdt.internal.compiler.ast.ASTNode oldASTNode) {
+		this.newAstToOldAst.put(node, oldASTNode);
+	}
+	
+	/*
+	 * Method declared on BindingResolver.
+	 */
+	synchronized void updateKey(ASTNode node, ASTNode newNode) {
+		Object astNode = this.newAstToOldAst.remove(node);
+		if (astNode != null) {
+			this.newAstToOldAst.put(newNode, astNode);
+		}
+	}
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultCommentMapper.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultCommentMapper.java
index eef1ebe..49a9edf 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultCommentMapper.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultCommentMapper.java
@@ -24,10 +24,16 @@
  */
 class DefaultCommentMapper {
 	Comment[] comments;
-	HashMap leadingComments;
-	HashMap trailingComments;
-	
 	Scanner scanner;
+	
+	// extended nodes storage
+	int leadingPtr;
+	ASTNode[] leadingNodes;
+	int[][] leadingIndexes;
+	int trailingPtr, lastTrailingPtr;
+	ASTNode[] trailingNodes;
+	int[][] trailingIndexes;
+	static final int STORAGE_INCREMENT = 16;
 
 	/**
 	 * @param table the given table of comments
@@ -109,8 +115,11 @@
 	 * @return an array of Comment or null if there's no leading comment
 	 */
 	Comment[] getLeadingComments(ASTNode node) {
-		if (this.leadingComments != null) {
-			int[] range = (int[]) this.leadingComments.get(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];
@@ -127,8 +136,11 @@
 	 * @return an array of Comment or null if there's no trailing comment
 	 */
 	Comment[] getTrailingComments(ASTNode node) {
-		if (this.trailingComments != null) {
-			int[] range = (int[]) this.trailingComments.get(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];
@@ -152,8 +164,11 @@
 	 * @since 3.0
 	 */
 	public int getExtendedStartPosition(ASTNode node) {
-		if (this.leadingComments != null) {
-			int[] range = (int[]) this.leadingComments.get(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) {
 				return  this.comments[range[0]].getStartPosition() ;
 			}
@@ -166,18 +181,14 @@
 	 */
 	public int getExtendedEnd(ASTNode node) {
 		int end = node.getStartPosition() + node.getLength();
-		if (this.trailingComments != null) {
-			int[] range = (int[]) this.trailingComments.get(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) {
-				if (range[0] == -1 && range[1] == -1) {
-					ASTNode parent = node.getParent();
-					if (parent != null) {
-						return getExtendedEnd(parent);
-					}
-				} else {
-					Comment lastComment = this.comments[range[1]];
-					end = lastComment.getStartPosition() + lastComment.getLength();
-				}
+				Comment lastComment = this.comments[range[1]];
+				end = lastComment.getStartPosition() + lastComment.getLength();
 			}
 		}
 		return end-1;
@@ -207,7 +218,11 @@
 	 * nothing else than white spaces.
 	 */
 	void initialize(CompilationUnit unit, Scanner sc) {
-		
+
+		// Init array pointers
+		this.leadingPtr = -1;
+		this.trailingPtr = -1;
+	
 		// Init comments
 		this.comments = unit.optionalCommentTable;
 		if (this.comments == null) {
@@ -218,18 +233,40 @@
 			return;
 		}
 
-		// Init tables
-		this.leadingComments = new HashMap();
-		this.trailingComments = new HashMap();
-		
 		// Init scanner and start ranges computing
 		this.scanner = sc;
-		this.scanner.linePtr = this.scanner.lineEnds.length-1;
 		this.scanner.tokenizeWhiteSpace = true;
-		
+
 		// Start unit visit
 		DefaultASTVisitor commentVisitor = new CommentMapperVisitor();
 		unit.accept(commentVisitor);
+		
+		// Reduce leading arrays if necessary
+		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);
+		}
+		
+		// Reduce trailing arrays if necessary
+		if (this.trailingPtr >= 0) {
+			// remove last remaining unresolved nodes
+			while (this.trailingIndexes[this.trailingPtr][0] == -1) {
+				this.trailingPtr--;
+				if (this.trailingPtr < 0) {
+					this.trailingIndexes = null;
+					this.trailingNodes = null;
+					break;
+				}
+			}
+
+			// reduce array size
+			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);
+			}
+		}
 	}
 
 	/**
@@ -237,9 +274,7 @@
 	 * from previous extended position to node start position. If one or several comment are found,
 	 * returns first comment start position, otherwise returns node start position.
 	 * 
-	 * First look after first comment before node start position using global comment index
-	 * to reduce range of search. Obviously returns if no comment is found before the node...
-	 * @see #doExtraRangesForChildren(ASTNode, Scanner)
+	 * First look after first comment before node start position and return if none was found...
 	 *
 	 * When first comment was found before node, goes up in comment list until one of
 	 * following condition becomes true:
@@ -321,7 +356,7 @@
 				int lastTokenEnd = previousEnd;
 				this.scanner.resetTo(previousEnd, commentStart);
 				try {
-					while (this.scanner.currentPosition != commentStart) {
+					while (this.scanner.currentPosition < commentStart) {
 						if (this.scanner.getNextToken() != TerminalTokens.TokenNameWHITESPACE) {
 							lastTokenEnd =  this.scanner.getCurrentTokenEndPosition();
 						}
@@ -337,7 +372,16 @@
 			}
 			// Store leading comments indexes
 			if (startIdx <= endIdx) {
-				this.leadingComments.put(node, new int[] { startIdx, endIdx });
+				if (++this.leadingPtr == 0) {
+					this.leadingNodes = new ASTNode[STORAGE_INCREMENT];
+					this.leadingIndexes = new int[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);
+				}
+				this.leadingNodes[this.leadingPtr] = node;
+				this.leadingIndexes[this.leadingPtr] = new int[] { startIdx, endIdx };
 				extended = this.comments[endIdx].getStartPosition();
 			}
 		}
@@ -349,9 +393,7 @@
 	 * from node end position to specified next start. If one or several comment are found,
 	 * returns last comment end position, otherwise returns node end position.
 	 * 
-	 * First look after first comment after node end position using global comment index
-	 * to reduce range of search. Obviously returns if no comment is found after the node...
-	 * @see #doExtraRangesForChildren(ASTNode, Scanner)
+	 * First look after first comment after node end position and return if none was found...
 	 *
 	 * When first comment was found after node, goes down in comment list until one of
 	 * following condition becomes true:
@@ -372,7 +414,17 @@
 		int nodeEnd = node.getStartPosition()+node.getLength()-1;
 		if (nodeEnd == nextStart) {
 			// special case for last child of its parent
-			this.trailingComments.put(node, new int[] { -1, -1 });
+			if (++this.trailingPtr == 0) {
+				this.trailingNodes = new ASTNode[STORAGE_INCREMENT];
+				this.trailingIndexes = new int[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);
+			}
+			this.trailingNodes[this.trailingPtr] = node;
+			this.trailingIndexes[this.trailingPtr] = new int[] { -1, -1 };
 			return nodeEnd;
 		}
 		int extended = nodeEnd;
@@ -450,8 +502,42 @@
 				}
 			}
 			// Store trailing comments indexes
-			this.trailingComments.put(node, new int[] { startIdx, endIdx });
+			if (++this.trailingPtr == 0) {
+				this.trailingNodes = new ASTNode[STORAGE_INCREMENT];
+				this.trailingIndexes = new int[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);
+			}
+			this.trailingNodes[this.trailingPtr] = node;
+			int[] nodeRange = new int[] { startIdx, endIdx };
+			this.trailingIndexes[this.trailingPtr] = nodeRange;
+			// Compute new extended end
 			extended = this.comments[endIdx].getStartPosition()+this.comments[endIdx].getLength()-1;
+			// Look for children unresolved extended end
+			ASTNode previousNode = node;
+			int ptr = this.trailingPtr - 1; // children extended end were stored before
+			unresolved: while (ptr >= 0) {
+				int[] range = this.trailingIndexes[ptr];
+				if (range[0] != -1 || range[1] != -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;
+				previousNode = unresolved;
+				ptr--; // get previous node
+			}
+			// Remove remaining unresolved nodes
+			if (ptr > this.lastTrailingPtr) {
+				int offset = ptr - this.lastTrailingPtr;
+				for (int i=ptr+1; i<=this.trailingPtr; i++) {
+					this.trailingNodes[i-offset] = this.trailingNodes[i];
+					this.trailingIndexes[i-offset] = this.trailingIndexes[i];
+				}
+				this.trailingPtr -= offset;
+			}
+			this.lastTrailingPtr = this.trailingPtr;
 		}
 		return extended;
 	}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DoStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DoStatement.java
index 78ab9d7..18f5739 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DoStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DoStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -47,10 +48,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(DoStatement.class);
-		addProperty(EXPRESSION_PROPERTY);
-		addProperty(BODY_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(3);
+		createPropertyList(DoStatement.class, properyList);
+		addProperty(EXPRESSION_PROPERTY, properyList);
+		addProperty(BODY_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java
index 9b812da..fba9d08 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java
@@ -13,6 +13,7 @@
 import java.util.Iterator;
 import java.util.List;
 
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
@@ -35,6 +36,7 @@
 		super(null);
 		this.ast = ast;
 		this.scanner = scanner;
+		this.jdk15 = this.ast.apiLevel() >= AST.JLS3;
 		this.checkDocComment = check;
 		this.kind = DOM_PARSER;
 	}
@@ -57,10 +59,12 @@
 		
 		// Parse
 		if (this.checkDocComment) {
-			parseComment(start, start+length-1);
+			commentParse(start, start+length-1);
 		}
 		this.docComment.setSourceRange(start, length);
-		setComment(start, length);  // backward compatibility
+		if (this.ast.apiLevel == AST.JLS2) {
+			setComment(start, length);  // backward compatibility
+		}
 		return this.docComment;
 	}
 
@@ -190,6 +194,66 @@
 				throw new InvalidInputException();
 		}
 	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createTag()
+	 */
+	protected void createTag() {
+		TagElement tagElement = this.ast.newTagElement();
+		int start = this.tagSourceStart;
+		String tagName = new String(this.source, start, this.tagSourceEnd-start+1);
+		switch (tagName.charAt(0)) {
+			case 'a':
+				if (tagName.equals(TagElement.TAG_AUTHOR)) {
+					tagName = TagElement.TAG_AUTHOR;
+				}
+				break;
+			case 'd':
+				if (tagName.equals(TagElement.TAG_DOCROOT)) {
+					tagName = TagElement.TAG_DOCROOT;
+				}
+				break;
+			case 'r':
+				if (tagName.equals(TagElement.TAG_RETURN)) {
+					tagName = TagElement.TAG_RETURN;
+				}
+				break;
+			case 's':
+				if (tagName.equals(TagElement.TAG_SERIAL)) {
+					tagName = TagElement.TAG_SERIAL;
+				} else  if (tagName.equals(TagElement.TAG_SERIALDATA)) {
+					tagName = TagElement.TAG_SERIALDATA;
+				} else if (tagName.equals(TagElement.TAG_SERIALFIELD)) {
+					tagName = TagElement.TAG_SERIALFIELD;
+				}
+				break;
+			case 'v':
+				if (tagName.equals(TagElement.TAG_VERSION)) {
+					tagName = TagElement.TAG_VERSION;
+				}
+				break;
+		}
+		tagElement.setTagName(tagName);
+		if (this.inlineTagStarted) {
+			start = this.inlineTagStart;
+			TagElement previousTag = null;
+			if (this.astPtr == -1) {
+				previousTag = this.ast.newTagElement();
+				previousTag.setSourceRange(start, this.tagSourceEnd-start+1);
+				pushOnAstStack(previousTag, true);
+			} else {
+				previousTag = (TagElement) this.astStack[this.astPtr];
+			}
+			int previousStart = previousTag.getStartPosition();
+			previousTag.fragments().add(tagElement);
+			previousTag.setSourceRange(previousStart, this.tagSourceEnd-previousStart+1);
+		} else {
+			pushOnAstStack(tagElement, true);
+		}
+		tagElement.setSourceRange(start, this.tagSourceEnd-start+1);
+//		return true;
+	}
+
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createTypeReference()
 	 */
@@ -266,63 +330,278 @@
 	 * Parse @return tag declaration
 	 */
 	protected boolean parseReturn() {
-		return parseTag();
+		createTag();
+		return true;
 	}
 
-	/*
-	 * Parse tag declaration
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#parseTag(int)
 	 */
-	protected boolean parseTag() {
-		TagElement tag = this.ast.newTagElement();
-		int start = this.tagSourceStart;
-		tag.setTagName(new String(this.source, start, this.tagSourceEnd-start+1));
-		if (this.inlineTagStarted) {
-			start = this.inlineTagStart;
-			TagElement previousTag = null;
-			if (this.astPtr == -1) {
-				previousTag = this.ast.newTagElement();
-				previousTag.setSourceRange(start, this.tagSourceEnd-start+1);
-				pushOnAstStack(previousTag, true);
-			} else {
-				previousTag = (TagElement) this.astStack[this.astPtr];
+	protected boolean parseTag(int previousPosition) throws InvalidInputException {
+		
+		// Read tag name
+		int token = readTokenAndConsume();
+		this.tagSourceStart = this.scanner.getCurrentTokenStartPosition();
+		this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
+		char[] tag = this.scanner.getCurrentIdentifierSource(); // first token is either an identifier or a keyword
+
+		// Try to get tag name other than java identifier
+		// (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51660)
+		int tk = token;
+		int le = this.lineEnd;
+		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;
 			}
-			int previousStart = previousTag.getStartPosition();
-			previousTag.fragments().add(tag);
-			previousTag.setSourceRange(previousStart, this.tagSourceEnd-previousStart+1);
-		} else {
-			pushOnAstStack(tag, true);
+			tk = readTokenAndConsume();
+			pc = peekChar();
 		}
-		tag.setSourceRange(start, this.tagSourceEnd-start+1);
-		return true;
+		int length = this.tagSourceEnd-this.tagSourceStart+1;
+		tag = new char[length];
+		System.arraycopy(this.source, this.tagSourceStart, tag, 0, length);
+		this.index = this.tagSourceEnd+1;
+		this.scanner.currentPosition = this.tagSourceEnd+1;
+		this.tagSourceStart = previousPosition;
+		this.lineEnd = le;
+
+		// Decide which parse to perform depending on tag name
+		this.tagValue = NO_TAG_VALUE;
+		boolean valid = true;
+		switch (token) {
+			case TerminalTokens.TokenNameIdentifier :
+				switch (tag[0]) {
+					case 'd':
+						if (CharOperation.equals(tag, TAG_DEPRECATED)) {
+							this.deprecated = true;
+							this.tagValue = TAG_DEPRECATED_VALUE;
+						} else {
+							this.tagValue = TAG_OTHERS_VALUE;
+						}
+						createTag();
+					break;
+					case 'i':
+						if (CharOperation.equals(tag, TAG_INHERITDOC)) {
+							// 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
+							// was encountered in comment. But it cannot be the case for COMPILER_PARSER
+							// and so is enough as it is only this parser which signals the missing tag warnings...
+							this.inherited = this.astPtr==-1;
+							this.tagValue = TAG_INHERITDOC_VALUE;
+						} else {
+							this.tagValue = TAG_OTHERS_VALUE;
+						}
+						createTag();
+					break;
+					case 'p':
+						if (CharOperation.equals(tag, TAG_PARAM)) {
+							this.tagValue = TAG_PARAM_VALUE;
+							valid = parseParam();
+						} else {
+							this.tagValue = TAG_OTHERS_VALUE;
+							createTag();
+						}
+					break;
+					case 'e':
+						if (CharOperation.equals(tag, TAG_EXCEPTION)) {
+							this.tagValue = TAG_EXCEPTION_VALUE;
+							valid = parseThrows();
+						} else {
+							this.tagValue = TAG_OTHERS_VALUE;
+							createTag();
+						}
+					break;
+					case 's':
+						if (CharOperation.equals(tag, TAG_SEE)) {
+							this.tagValue = TAG_SEE_VALUE;
+							if (this.inlineTagStarted) {
+								// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
+								// Cannot have @see inside inline comment
+								valid = false;
+							} else {
+								valid = parseReference();
+							}
+						} else {
+							this.tagValue = TAG_OTHERS_VALUE;
+							createTag();
+						}
+					break;
+					case 'l':
+						if (CharOperation.equals(tag, TAG_LINK)) {
+							this.tagValue = TAG_LINK_VALUE;
+						} else if (CharOperation.equals(tag, TAG_LINKPLAIN)) {
+							this.tagValue = TAG_LINKPLAIN_VALUE;
+						}
+						if (this.tagValue != NO_TAG_VALUE)  {
+							if (this.inlineTagStarted) {
+								valid = parseReference();
+							} else {
+								// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
+								// Cannot have @link outside inline comment
+								valid = false;
+							}
+						} else {
+							this.tagValue = TAG_OTHERS_VALUE;
+							createTag();
+						}
+					break;
+					case 'v':
+						if (this.jdk15 && CharOperation.equals(tag, TAG_VALUE)) {
+							this.tagValue = TAG_VALUE_VALUE;
+							if (this.inlineTagStarted) {
+								valid = parseReference();
+							} else {
+								valid = false;
+							}
+						} else {
+							this.tagValue = TAG_OTHERS_VALUE;
+							createTag();
+						}
+					break;
+					default:
+						this.tagValue = TAG_OTHERS_VALUE;
+						createTag();
+				}
+				break;
+			case TerminalTokens.TokenNamereturn :
+				this.tagValue = TAG_RETURN_VALUE;
+				valid = parseReturn();
+				break;
+			case TerminalTokens.TokenNamethrows :
+				this.tagValue = TAG_THROWS_VALUE;
+				valid = parseThrows();
+				break;
+			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:
+				this.tagValue = TAG_OTHERS_VALUE;
+				createTag();
+				break;
+		}
+		this.textStart = this.index;
+		return valid;
 	}
 
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#pushParamName(java.lang.Object)
 	 */
-	protected boolean pushParamName() {
-		SimpleName name = this.ast.newSimpleName(new String(this.scanner.getCurrentIdentifierSource()));
-		name.setSourceRange(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition()-this.scanner.getCurrentTokenStartPosition()+1);
+	protected boolean pushParamName(boolean isTypeParam) {
+		int idIndex = isTypeParam ? 1 : 0;
+		SimpleName name = this.ast.newSimpleName(new String(this.identifierStack[idIndex]));
+		int nameStart = (int) (this.identifierPositionStack[idIndex] >>> 32);
+		int nameEnd = (int) (this.identifierPositionStack[idIndex] & 0x00000000FFFFFFFFL);
+		name.setSourceRange(nameStart, nameEnd-nameStart+1);
 		TagElement paramTag = this.ast.newTagElement();
 		paramTag.setTagName(TagElement.TAG_PARAM);
-		paramTag.setSourceRange(this.tagSourceStart, this.scanner.getCurrentTokenEndPosition()-this.tagSourceStart+1);
-		paramTag.fragments().add(name);
+		if (isTypeParam) { // specific storage for @param <E> (see bug 79809)
+			// '<' was stored in identifiers stack
+			TextElement text = this.ast.newTextElement();
+			text.setText(new String(this.identifierStack[0]));
+			int txtStart = (int) (this.identifierPositionStack[0] >>> 32);
+			int txtEnd = (int) (this.identifierPositionStack[0] & 0x00000000FFFFFFFFL);
+			text.setSourceRange(txtStart, txtEnd-txtStart+1);
+			paramTag.fragments().add(text);
+			// add simple name
+			paramTag.fragments().add(name);
+			// '>' was stored in identifiers stack
+			text = this.ast.newTextElement();
+			text.setText(new String(this.identifierStack[2]));
+			txtStart = (int) (this.identifierPositionStack[2] >>> 32);
+			txtEnd = (int) (this.identifierPositionStack[2] & 0x00000000FFFFFFFFL);
+			text.setSourceRange(txtStart, txtEnd-txtStart+1);
+			paramTag.fragments().add(text);
+			// set param tag source range
+			paramTag.setSourceRange(this.tagSourceStart, txtEnd-this.tagSourceStart+1);
+		} else {
+			paramTag.setSourceRange(this.tagSourceStart, nameEnd-this.tagSourceStart+1);
+			paramTag.fragments().add(name);
+		}
 		pushOnAstStack(paramTag, true);
 		return true;
 	}
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#pushSeeRef(java.lang.Object)
 	 */
-	protected boolean pushSeeRef(Object statement, boolean plain) {
+	protected boolean pushSeeRef(Object statement) {
 		TagElement seeTag = this.ast.newTagElement();
 		ASTNode node = (ASTNode) statement;
 		seeTag.fragments().add(node);
 		int end = node.getStartPosition()+node.getLength()-1;
 		if (this.inlineTagStarted) {
 			seeTag.setSourceRange(this.inlineTagStart, end-this.inlineTagStart+1);
-			if (plain) {
-				seeTag.setTagName(TagElement.TAG_LINKPLAIN);
-			} else {
-				seeTag.setTagName(TagElement.TAG_LINK);
+			switch (this.tagValue) {
+				case TAG_LINK_VALUE:
+					seeTag.setTagName(TagElement.TAG_LINK);
+				break;
+				case TAG_LINKPLAIN_VALUE:
+					seeTag.setTagName(TagElement.TAG_LINKPLAIN);
+				break;
+				case TAG_VALUE_VALUE:
+					seeTag.setTagName(TagElement.TAG_VALUE);
+				break;
 			}
 			TagElement previousTag = null;
 			int previousStart = this.inlineTagStart;
@@ -398,12 +677,15 @@
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#pushThrowName(java.lang.Object)
 	 */
-	protected boolean pushThrowName(Object typeRef, boolean real) {
+	protected boolean pushThrowName(Object typeRef) {
 		TagElement throwsTag = this.ast.newTagElement();
-		if (real) {
-			throwsTag.setTagName(TagElement.TAG_THROWS);
-		} else {
-			throwsTag.setTagName(TagElement.TAG_EXCEPTION);
+		switch (this.tagValue) {
+			case TAG_THROWS_VALUE:
+				throwsTag.setTagName(TagElement.TAG_THROWS);
+			break;
+			case TAG_EXCEPTION_VALUE:
+				throwsTag.setTagName(TagElement.TAG_EXCEPTION);
+			break;
 		}
 		throwsTag.setSourceRange(this.tagSourceStart, this.scanner.getCurrentTokenEndPosition()-this.tagSourceStart+1);
 		throwsTag.fragments().add(typeRef);
@@ -411,8 +693,8 @@
 		return true;
 	}
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#updateDocComment()
+	/*
+	 * Add stored tag elements to associated comment.
 	 */
 	protected void updateDocComment() {
 		for (int idx = 0; idx <= this.astPtr; idx++) {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EmptyStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EmptyStatement.java
index 7a3d367..c078a98 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EmptyStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EmptyStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -33,8 +34,9 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(EmptyStatement.class);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(1);
+		createPropertyList(EmptyStatement.class, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnhancedForStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnhancedForStatement.java
index 2c75f57..3ec0fa1 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnhancedForStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnhancedForStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -62,11 +63,12 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(EnhancedForStatement.class);
-		addProperty(PARAMETER_PROPERTY);
-		addProperty(EXPRESSION_PROPERTY);
-		addProperty(BODY_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(4);
+		createPropertyList(EnhancedForStatement.class, properyList);
+		addProperty(PARAMETER_PROPERTY, properyList);
+		addProperty(EXPRESSION_PROPERTY, properyList);
+		addProperty(BODY_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
@@ -316,18 +318,11 @@
 	}
 	
 	/**
-	 * Resolves and returns the binding for the loop variable of this
-	 * enhanced for statement.
-	 * <p>
-	 * Note that bindings are generally unavailable unless requested when the
-	 * AST is being built.
-	 * </p>
-	 * 
-	 * @return the binding, or <code>null</code> if the binding cannot be 
-	 *    resolved
-	 */	
+	 * @deprecated Use getParameter().resolveBinding() instead.
+	 */
+	// TODO (jeem) remove after 3.1 M4 - https://bugs.eclipse.org/bugs/show_bug.cgi?id=79098
 	public IVariableBinding resolveBinding() {
-		return this.ast.getBindingResolver().resolveVariable(this);
+		return null;
 	}
 
 	/* (omit javadoc for this method)
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnumConstantDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnumConstantDeclaration.java
index b7627f1..f24a2f1 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnumConstantDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnumConstantDeclaration.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
@@ -21,7 +22,7 @@
  * EnumConstantDeclaration:
  *     [ Javadoc ] { ExtendedModifier } Identifier
  *         [ <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b> ]
- *         [ <b>{</b> { ClassBodyDeclaration | <b>;</b> } <b>}</b> ]
+ *         [ AnonymousClassDeclaration ]
  * </pre>
  * <p>
  * When a Javadoc comment is present, the source
@@ -72,11 +73,20 @@
 	
 	/**
 	 * The "bodyDeclarations" structural property of this node type.
+	 * @deprecated This property has been replaced by ANONYMOUS_CLASS_DECLARATION_PROPERTY.
 	 */
+	// TODO (jeem) - remove this after 3.1 M4
 	public static final ChildListPropertyDescriptor BODY_DECLARATIONS_PROPERTY = 
 		new ChildListPropertyDescriptor(EnumConstantDeclaration.class, "bodyDeclarations", BodyDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
 	
 	/**
+	 * The "anonymousClassDeclaration" structural property of this node type.
+	 * @since 3.1
+	 */
+	public static final ChildPropertyDescriptor ANONYMOUS_CLASS_DECLARATION_PROPERTY = 
+		new ChildPropertyDescriptor(EnumConstantDeclaration.class, "anonymousClassDeclaration", AnonymousClassDeclaration.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+	
+	/**
 	 * A list of property descriptors (element type: 
 	 * {@link StructuralPropertyDescriptor}),
 	 * or null if uninitialized.
@@ -84,13 +94,15 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(EnumConstantDeclaration.class);
-		addProperty(JAVADOC_PROPERTY);
-		addProperty(MODIFIERS2_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(ARGUMENTS_PROPERTY);
-		addProperty(BODY_DECLARATIONS_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(6);
+		createPropertyList(EnumConstantDeclaration.class, properyList);
+		addProperty(JAVADOC_PROPERTY, properyList);
+		addProperty(MODIFIERS2_PROPERTY, properyList);
+		addProperty(NAME_PROPERTY, properyList);
+		addProperty(ARGUMENTS_PROPERTY, properyList);
+		addProperty(BODY_DECLARATIONS_PROPERTY, properyList);
+		addProperty(ANONYMOUS_CLASS_DECLARATION_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
@@ -123,15 +135,24 @@
 	/**
 	 * The body declarations (element type: <code>BodyDeclaration</code>).
 	 * Defaults to an empty list.
+	 * @deprecated
 	 */
+	// TODO (jeem) - remove this after 3.1 M4
 	private ASTNode.NodeList bodyDeclarations = 
 		new ASTNode.NodeList(BODY_DECLARATIONS_PROPERTY);
 
 	/**
+	 * The optional anonymous class declaration; <code>null</code> for none; 
+	 * defaults to none.
+	 * @since 3.1
+	 */
+	private AnonymousClassDeclaration optionalAnonymousClassDeclaration = null;
+	
+	/**
 	 * Creates a new AST node for an enumeration constants declaration owned by
 	 * the given AST. By default, the enumeration constant has an unspecified,
 	 * but legal, name; no javadoc; an empty list of modifiers and annotations;
-	 * an empty list of arguments; and an empty list of body declarations.
+	 * an empty list of arguments; and does not declare an anonymous class.
 	 * <p>
 	 * N.B. This constructor is package-private; all subclasses must be 
 	 * declared in the same package; clients are unable to declare 
@@ -172,6 +193,14 @@
 				return null;
 			}
 		}
+		if (property == ANONYMOUS_CLASS_DECLARATION_PROPERTY) {
+			if (get) {
+				return getAnonymousClassDeclaration();
+			} else {
+				setAnonymousClassDeclaration((AnonymousClassDeclaration) child);
+				return null;
+			}
+		}
 		// allow default implementation to flag the error
 		return super.internalGetSetChildProperty(property, get, child);
 	}
@@ -235,6 +264,8 @@
 		result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
 		result.bodyDeclarations().addAll(
 			ASTNode.copySubtrees(target, bodyDeclarations()));
+		result.setAnonymousClassDeclaration(
+				(AnonymousClassDeclaration) ASTNode.copySubtree(target, getAnonymousClassDeclaration()));
 		return result;
 	}
 
@@ -258,6 +289,7 @@
 			acceptChild(visitor, getName());
 			acceptChildren(visitor, this.arguments);
 			acceptChildren(visitor, this.bodyDeclarations);
+			acceptChild(visitor, getAnonymousClassDeclaration());
 		}
 		visitor.endVisit(this);
 	}
@@ -321,12 +353,49 @@
 	 * 
 	 * @return the live list of body declarations
 	 *    (element type: <code>BodyDeclaration</code>)
-	 */ 
+	 * @deprecated Use get/setAnonymousClassDeclaration instead.
+	 */
+	// TODO (jeem) - remove this after 3.1 M4
 	public List bodyDeclarations() {
 		return this.bodyDeclarations;
 	}
+
+	/**
+	 * Internal method used to reduce deprecations warnings
+	 * for obsolete bodyDeclarations().
+	 */
+	// TODO (jeem) - remove this after 3.1 M4
+	List obsoleteBodyDeclarations() {
+		return this.bodyDeclarations;
+	}
 	
 	/**
+	 * Returns the anonymous class declaration introduced by this
+	 * enum constant declaration, if it has one.
+	 * 
+	 * @return the anonymous class declaration, or <code>null</code> if none
+	 * @since 3.1
+	 */ 
+	public AnonymousClassDeclaration getAnonymousClassDeclaration() {
+		return this.optionalAnonymousClassDeclaration;
+	}
+	
+	/**
+	 * Sets whether this enum constant declaration declares
+	 * an anonymous class (that is, has class body declarations).
+	 * 
+	 * @param decl the anonymous class declaration, or <code>null</code> 
+	 *    if none
+	 * @since 3.1
+	 */ 
+	public void setAnonymousClassDeclaration(AnonymousClassDeclaration decl) {
+		ASTNode oldChild = this.optionalAnonymousClassDeclaration;
+		preReplaceChild(oldChild, decl, ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+		this.optionalAnonymousClassDeclaration = decl;
+		postReplaceChild(oldChild, decl, ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+	}
+
+	/**
 	 * Resolves and returns the field binding for this enum constant.
 	 * <p>
 	 * Note that bindings are generally unavailable unless requested when the
@@ -358,9 +427,9 @@
 			}
 			buffer.append(")");//$NON-NLS-1$
 		}
-		if (!bodyDeclarations().isEmpty()) {
+		if (getAnonymousClassDeclaration() != null) {
 			buffer.append(" {");//$NON-NLS-1$
-			for (Iterator it = bodyDeclarations().iterator(); it.hasNext(); ) {
+			for (Iterator it = getAnonymousClassDeclaration().bodyDeclarations().iterator(); it.hasNext(); ) {
 				BodyDeclaration d = (BodyDeclaration) it.next();
 				d.appendDebugString(buffer);
 				if (it.hasNext()) {
@@ -376,7 +445,7 @@
 	 * Method declared on ASTNode.
 	 */
 	int memSize() {
-		return super.memSize() + 3 * 4;
+		return super.memSize() + 3 * 6;
 	}
 	
 	/* (omit javadoc for this method)
@@ -389,7 +458,8 @@
 			+ this.modifiers.listSize()
 			+ (this.constantName == null ? 0 : getName().treeSize())
 			+ this.arguments.listSize()
-			+ this.bodyDeclarations.listSize();
+			+ this.bodyDeclarations.listSize()
+			+ (this.optionalAnonymousClassDeclaration == null ? 0 : getAnonymousClassDeclaration().treeSize());
 	}
 }
 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnumDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnumDeclaration.java
index 4afa0c1..775ba5f 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnumDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnumDeclaration.java
@@ -11,7 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
-import java.util.Iterator;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -26,6 +26,9 @@
  *         [ <b>;</b> { ClassBodyDeclaration | <b>;</b> } ]
  *         <b>}</b>
  * </pre>
+ * The {@link #enumConstants()} list holds the enum constant declarations,
+ * while the {@link #bodyDeclarations()} list holds the class body declarations
+ * that appear after the semicolon.
  * <p>
  * When a Javadoc comment is present, the source
  * range begins with the first character of the "/**" comment delimiter.
@@ -71,6 +74,13 @@
 		new ChildListPropertyDescriptor(EnumDeclaration.class, "superInterfaceTypes", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
 	
 	/**
+	 * The "enumConstants" structural property of this node type.
+	 * @since 3.1
+	 */
+	public static final ChildListPropertyDescriptor ENUM_CONSTANTS_PROPERTY = 
+		new ChildListPropertyDescriptor(EnumDeclaration.class, "enumConstants", EnumConstantDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+	
+	/**
 	 * The "bodyDeclarations" structural property of this node type.
 	 */
 	public static final ChildListPropertyDescriptor BODY_DECLARATIONS_PROPERTY = 
@@ -84,13 +94,15 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(EnumDeclaration.class);
-		addProperty(JAVADOC_PROPERTY);
-		addProperty(MODIFIERS2_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(SUPER_INTERFACE_TYPES_PROPERTY);
-		addProperty(BODY_DECLARATIONS_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(6);
+		createPropertyList(EnumDeclaration.class, properyList);
+		addProperty(JAVADOC_PROPERTY, properyList);
+		addProperty(MODIFIERS2_PROPERTY, properyList);
+		addProperty(NAME_PROPERTY, properyList);
+		addProperty(SUPER_INTERFACE_TYPES_PROPERTY, properyList);
+		addProperty(ENUM_CONSTANTS_PROPERTY, properyList);
+		addProperty(BODY_DECLARATIONS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
@@ -115,10 +127,19 @@
 		new ASTNode.NodeList(SUPER_INTERFACE_TYPES_PROPERTY);
 
 	/**
+	 * The enum constant declarations
+	 * (element type: <code>EnumConstantDeclaration</code>).
+	 * Defaults to an empty list.
+	 * @since 3.1
+	 */
+	private ASTNode.NodeList enumConstants = 
+		new ASTNode.NodeList(ENUM_CONSTANTS_PROPERTY);
+
+	/**
 	 * Creates a new AST node for an enum declaration owned by the given 
 	 * AST. By default, the enum declaration has an unspecified, but legal,
 	 * name; no modifiers; no javadoc; no superinterfaces; 
-	 * and an empty list of body declarations.
+	 * and empty lists of enum constants and body declarations.
 	 * <p>
 	 * N.B. This constructor is package-private; all subclasses must be 
 	 * declared in the same package; clients are unable to declare 
@@ -173,6 +194,9 @@
 		if (property == SUPER_INTERFACE_TYPES_PROPERTY) {
 			return superInterfaceTypes();
 		}
+		if (property == ENUM_CONSTANTS_PROPERTY) {
+			return enumConstants();
+		}
 		if (property == BODY_DECLARATIONS_PROPERTY) {
 			return bodyDeclarations();
 		}
@@ -235,6 +259,8 @@
 		result.setName((SimpleName) getName().clone(target));
 		result.superInterfaceTypes().addAll(
 			ASTNode.copySubtrees(target, superInterfaceTypes()));
+		result.enumConstants().addAll(
+				ASTNode.copySubtrees(target, enumConstants()));
 		result.bodyDeclarations().addAll(
 			ASTNode.copySubtrees(target, bodyDeclarations()));
 		return result;
@@ -259,6 +285,7 @@
 			acceptChildren(visitor, this.modifiers);
 			acceptChild(visitor, getName());
 			acceptChildren(visitor, this.superInterfaceTypes);
+			acceptChildren(visitor, this.enumConstants);
 			acceptChildren(visitor, this.bodyDeclarations);
 		}
 		visitor.endVisit(this);
@@ -276,47 +303,21 @@
 	}
 	
 	/**
-	 * Returns the ordered list of enum constant declarations of this enum
-	 * declaration.
-	 * <p>
-	 * This convenience method returns this node's enum constant declarations
-	 * with non-enum constants filtered out. Unlike <code>bodyDeclarations</code>,
-	 * this method does not return a live result.
-	 * </p>
+	 * Returns the live ordered list of enum constant declarations
+	 * of this enum declaration.
 	 * 
-	 * @return the (possibly empty) list of enum constant declarations
+	 * @return the live list of enum constant declarations
+	 *    (element type: {@link EnumConstantDeclaration})
+	 * @since 3.1
 	 */ 
-	public EnumConstantDeclaration[] getEnumConstants() {
-		List bd = bodyDeclarations();
-		int enumCount = 0;
-		for (Iterator it = bd.listIterator(); it.hasNext(); ) {
-			if (it.next() instanceof EnumConstantDeclaration) {
-				enumCount++;
-			}
-		}
-		EnumConstantDeclaration[] enumConstants = new EnumConstantDeclaration[enumCount];
-		int next = 0;
-		for (Iterator it = bd.listIterator(); it.hasNext(); ) {
-			Object decl = it.next();
-			if (decl instanceof EnumConstantDeclaration) {
-				enumConstants[next++] = (EnumConstantDeclaration) decl;
-			}
-		}
+	public List enumConstants() {
 		return enumConstants;
 	}
 
-	/**
-	 * Resolves and returns the binding for the enum declared in
-	 * this enum declaration.
-	 * <p>
-	 * Note that bindings are generally unavailable unless requested when the
-	 * AST is being built.
-	 * </p>
-	 * 
-	 * @return the binding, or <code>null</code> if the binding cannot be 
-	 *    resolved
-	 */	
-	public ITypeBinding resolveBinding() {
+	/* (omit javadoc for this method)
+	 * Method declared on AsbtractTypeDeclaration.
+	 */
+	ITypeBinding internalResolveBinding() {
 		return this.ast.getBindingResolver().resolveType(this);
 	}
 	
@@ -324,7 +325,7 @@
 	 * Method declared on ASTNode.
 	 */
 	int memSize() {
-		return super.memSize() + 1 * 4;
+		return super.memSize() + 2 * 4;
 	}
 	
 	/* (omit javadoc for this method)
@@ -336,6 +337,7 @@
 			+ this.modifiers.listSize()
 			+ (this.typeName == null ? 0 : getName().treeSize())
 			+ this.superInterfaceTypes.listSize()
+			+ this.enumConstants.listSize()
 			+ this.bodyDeclarations.listSize();
 	}
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExpressionStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExpressionStatement.java
index da42abf..4c9fdbb 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExpressionStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExpressionStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -43,9 +44,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(ExpressionStatement.class);
-		addProperty(EXPRESSION_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(2);
+		createPropertyList(ExpressionStatement.class, properyList);
+		addProperty(EXPRESSION_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldAccess.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldAccess.java
index 5b49352..0663fd5 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldAccess.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldAccess.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -77,10 +78,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(FieldAccess.class);
-		addProperty(EXPRESSION_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(3);
+		createPropertyList(FieldAccess.class, properyList);
+		addProperty(EXPRESSION_PROPERTY, properyList);
+		addProperty(NAME_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldDeclaration.java
index d15d5b0..b23523a 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldDeclaration.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
@@ -90,19 +91,21 @@
 	private static final List PROPERTY_DESCRIPTORS_3_0;
 	
 	static {
-		createPropertyList(FieldDeclaration.class);
-		addProperty(JAVADOC_PROPERTY);
-		addProperty(MODIFIERS_PROPERTY);
-		addProperty(TYPE_PROPERTY);
-		addProperty(FRAGMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList();
+		List properyList = new ArrayList(5);
+		createPropertyList(FieldDeclaration.class, properyList);
+		addProperty(JAVADOC_PROPERTY, properyList);
+		addProperty(MODIFIERS_PROPERTY, properyList);
+		addProperty(TYPE_PROPERTY, properyList);
+		addProperty(FRAGMENTS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
 		
-		createPropertyList(FieldDeclaration.class);
-		addProperty(JAVADOC_PROPERTY);
-		addProperty(MODIFIERS2_PROPERTY);
-		addProperty(TYPE_PROPERTY);
-		addProperty(FRAGMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList();
+		properyList = new ArrayList(5);
+		createPropertyList(FieldDeclaration.class, properyList);
+		addProperty(JAVADOC_PROPERTY, properyList);
+		addProperty(MODIFIERS2_PROPERTY, properyList);
+		addProperty(TYPE_PROPERTY, properyList);
+		addProperty(FRAGMENTS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ForStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ForStatement.java
index 50f7eda..207b80e 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ForStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ForStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -24,11 +25,18 @@
  * 			[ ForUpdate ] <b>)</b>
  * 			Statement
  * ForInit:
- * 		( VariableDeclarationExpression
- * 			 | { Expression {<b>,</b> Expression } }
+ * 		Expression { <b>,</b> Expression }
  * ForUpdate:
  * 		Expression { <b>,</b> Expression }
  * </pre>
+ * <p>
+ * Note: When variables are declared in the initializer
+ * of a for statement such as "<code>for (int a=1, b=2;;);</code>",
+ * they should be represented as a single
+ * <code>VariableDeclarationExpression</code>
+ * with two fragments, rather than being split up into a pair
+ * of expressions.
+ * </p>
  * 
  * @since 2.0
  */
@@ -70,12 +78,13 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(ForStatement.class);
-		addProperty(INITIALIZERS_PROPERTY);
-		addProperty(EXPRESSION_PROPERTY);
-		addProperty(UPDATERS_PROPERTY);
-		addProperty(BODY_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(5);
+		createPropertyList(ForStatement.class, properyList);
+		addProperty(INITIALIZERS_PROPERTY, properyList);
+		addProperty(EXPRESSION_PROPERTY, properyList);
+		addProperty(UPDATERS_PROPERTY, properyList);
+		addProperty(BODY_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IBinding.java
index c899516..ef99040 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IBinding.java
@@ -11,6 +11,8 @@
 
 package org.eclipse.jdt.core.dom;
 
+import org.eclipse.jdt.core.IJavaElement;
+
 /**
  * A binding represents a named entity in the Java language. The world of 
  * bindings provides an integrated picture of the structure of the program as
@@ -124,6 +126,16 @@
 	public boolean isSynthetic();
 	
 	/**
+	 * Returns the Java element that corresponds to this binding.
+	 * Returns <code>null</code> if this binding has no corresponding Java element.
+	 * 
+	 * @return the Java element that corresponds to this binding, 
+	 * 		or <code>null</code> if none
+	 * @since 3.1
+	 */
+	public IJavaElement getJavaElement();
+	
+	/**
 	 * Returns the key for this binding.
 	 * <p>
 	 * Within a connected cluster of bindings (for example, all bindings 
@@ -157,10 +169,27 @@
 	 *   block relative to its parent, the key of its method</li>
 	 * <li>anonymous types - the occurence count of the anonymous 
 	 *   type relative to its declaring type, the key of its declaring type</li>
+	 * <li>enum types - treated like classes</li>
+	 * <li>annotation types - treated like interfaces</li>
+	 * <li>type variables - the name of the type variable and 
+	 * the key of the generic type or generic method that declares that
+	 * type variable</li>
+	 * <li>wildcard types - the key of the optional wildcard type bound</li>
+	 * <li>generic type instances - the key of the generic type and the keys
+	 * of the type arguments used to instantiate it, and whether the
+	 * instance is explicit (a parameterized type reference) or
+	 * implicit (a raw type reference)</li>
+	 * <li>generic method instances - the key of the generic method and the keys
+	 * of the type arguments used to instantiate it, and whether the
+	 * instance is explicit (a parameterized method reference) or
+	 * implicit (a raw method reference)</li>
+	 * <li>members of generic type instances - the key of the generic type
+	 * instance and the key of the corresponding member in the generic
+	 * type</li>
 	 * </ul>
 	 * </p>
 	 * 
-	 * @return the key for this binding, or <code>null</code> if none
+	 * @return the key for this binding
 	 */
 	public String getKey();
 	
@@ -170,15 +199,33 @@
 	 * bindings, each binding is represented by a distinct object. However,
 	 * between different clusters of bindings, the binding objects may or may
 	 * not be different; in these cases, the client should compare bindings
-	 * via their binding keys (<code>getKey</code>) if available.
+	 * using {@link #isEqualTo(IBinding)}, which checks their keys.
 	 * 
 	 * @param obj {@inheritDoc}
 	 * @return {@inheritDoc}
-	 * @see #getKey()
 	 */
 	public boolean equals(Object obj);
 	
 	/**
+	 * Returns whether this binding has the same key as that of the given
+	 * binding. Within the context of a single cluster of bindings, each
+	 * binding is represented by a distinct object. However, between
+	 * different clusters of bindings, the binding objects may or may
+	 * not be different objects; in these cases, the binding keys
+	 * are used where available.
+	 * 
+	 * @param binding the other binding, or <code>null</code>
+	 * @return <code>true</code> if the given binding is the identical
+	 * object as this binding, or if the keys of both bindings are the
+	 * same string; <code>false</code> if the given binding is
+	 * <code>null</code>, or if the bindings do not have the same key,
+	 * or if one or both of the bindings have no key
+	 * @see #getKey()
+	 * @since 3.1
+	 */
+	public boolean isEqualTo(IBinding binding);
+	
+	/**
 	 * Returns a string representation of this binding suitable for debugging
 	 * purposes only.
 	 * 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodBinding.java
index 68541a9..a15da21 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodBinding.java
@@ -13,6 +13,20 @@
 
 /**
  * A method binding represents a method or constructor of a class or interface.
+ * Method bindings usually correspond directly to method or
+ * constructor declarations found in the source code.
+ * However, in certain cases of references to a generic method,
+ * the method binding may correspond to a copy of a generic method
+ * declaration with substitutions for the method's type parameters
+ * (for these, <code>getTypeArguments</code> returns a non-empty
+ * list, and either <code>isParameterizedMethod</code> or
+ * <code>isRawMethod</code> returns <code>true</code>).
+ * And in certain cases of references to a method declared in a
+ * generic type, the method binding may correspond to a copy of a
+ * method declaration with substitutions for the type's type
+ * parameters (for these, <code>getTypeArguments</code> returns
+ * an empty list, and both <code>isParameterizedMethod</code> and
+ * <code>isRawMethod</code> return <code>false</code>).
  * <p>
  * This interface is not intended to be implemented by clients.
  * </p>
@@ -109,6 +123,13 @@
 	/**
 	 * Returns the type parameters of this method or constructor binding.
 	 * <p>
+	 * Note that type parameters only occur on the binding of the
+	 * declaring generic method. Type bindings corresponding to a raw or
+	 * parameterized reference to a generic method do not carry type
+	 * parameters (they instead have non-empty type arguments
+	 * and non-trivial erasure).
+	 * </p>
+	 * <p>
 	 * Note: Support for new language features proposed for the upcoming 1.5
 	 * release of J2SE is tentative and subject to change.
 	 * </p>
@@ -119,4 +140,168 @@
 	 * @since 3.0
 	 */
 	public ITypeBinding[] getTypeParameters();
+	
+	/**
+	 * Returns whether this method binding represents a declaration of
+	 * a generic method.
+	 * <p>
+	 * Note that type parameters only occur on the binding of the
+	 * declaring generic method; e.g., <code>public &lt;T&gt; T identity(T t);</code>.
+	 * Method bindings corresponding to a raw or parameterized reference to a generic
+	 * method do not carry type parameters (they instead have non-empty type arguments
+	 * and non-trivial erasure).
+	 * This method is fully equivalent to <code>getTypeParameters().length &gt; 0)</code>.
+	 * </p>
+	 * <p>
+	 * Note that {@link #isGenericMethod()},
+	 * {@link #isParameterizedMethod()},
+	 * and {@link #isRawMethod()} are mutually exclusive.
+	 * </p>
+	 * <p>
+	 * Note: Support for new language features of the 1.5
+	 * release of J2SE is tentative and subject to change.
+	 * </p>
+	 *
+	 * @return <code>true</code> if this method binding represents a 
+	 * declaration of a generic method, and <code>false</code> otherwise
+	 * @see #getTypeParameters()
+	 * @since 3.1
+	 */
+	public boolean isGenericMethod();
+	
+	/**
+	 * Returns whether this method binding represents an instance of
+	 * a generic method corresponding to a parameterized method reference.
+	 * <p>
+	 * Note that {@link #isGenericMethod()},
+	 * {@link #isParameterizedMethod()},
+	 * and {@link #isRawMethod()} are mutually exclusive.
+	 * </p>
+	 * <p>
+	 * Note: Support for new language features proposed for the upcoming 1.5
+	 * release of J2SE is tentative and subject to change.
+	 * </p>
+	 *
+	 * @return <code>true</code> if this method binding represents a 
+	 * an instance of a generic method corresponding to a parameterized
+	 * method reference, and <code>false</code> otherwise
+	 * @see #getGenericMethod()
+	 * @see #getTypeArguments()
+	 * @since 3.1
+	 */
+	public boolean isParameterizedMethod();
+	
+	/**
+	 * Returns the type arguments of this generic method instance, or the
+	 * empty list for other method bindings.
+	 * <p>
+	 * Note that type arguments only occur on a method binding that represents
+	 * an instance of a generic method corresponding to a raw or parameterized
+	 * reference to a generic method. Do not confuse these with type parameters
+	 * which only occur on the method binding corresponding directly to the
+	 * declaration of a generic method.
+	 * </p> 
+	 * <p>
+	 * Note: Support for new language features proposed for the upcoming 1.5
+	 * release of J2SE is tentative and subject to change.
+	 * </p>
+	 *
+	 * @return the list of type bindings for the type arguments used to
+	 * instantiate the corrresponding generic method, or otherwise the empty list
+	 * @see #getGenericMethod()
+	 * @see #isParameterizedMethod()
+	 * @see #isRawMethod()
+	 * @since 3.1
+	 */
+	public ITypeBinding[] getTypeArguments();
+	
+	/**
+	 * Returns the erasure of this method binding.
+	 * Some bindings correspond to method declarations in the context of
+	 * a particular instance of a generic method. In those cases, this method
+	 * returns the generic method binding from which this method binding
+	 * was instantiated.
+	 * For other type bindings, this method returns the identical type binding.
+	 * Note that the resulting method binding will answer true to
+	 * {@link #isGenericMethod()} iff this method binding would return true
+	 * to either {@link #isGenericMethod()}, {@link #isParameterizedMethod()},
+	 * or {@link #isRawMethod()}.
+	 * <p>
+	 * Note: Support for new language features proposed for the upcoming 1.5
+	 * release of J2SE is tentative and subject to change.
+	 * </p>
+	 *
+	 * @return the erasure method binding
+	 * @since 3.1
+	 * @deprecated Use {@link #getGenericMethod()} instead.
+	 */
+	// TODO (jeem) - remove before 3.1M5 (bug 80800)
+	public IMethodBinding getErasure();
+	
+	/**
+	 * Returns the generic method corresponding to this method binding.
+	 * Some bindings correspond to method declarations in the context of
+	 * a particular instance of a generic method. In those cases, this method
+	 * returns the generic method binding from which this method binding
+	 * was instantiated.
+	 * For other method bindings, this method returns the identical method binding.
+	 * Note that the resulting method binding will answer true to
+	 * {@link #isGenericMethod()} iff this method binding would return true
+	 * to either {@link #isGenericMethod()}, {@link #isParameterizedMethod()},
+	 * or {@link #isRawMethod()}.
+	 * <p>
+	 * Note: Support for new language features proposed for the upcoming 1.5
+	 * release of J2SE is tentative and subject to change.
+	 * </p>
+	 *
+	 * @return the generic method binding
+	 * @since 3.1
+	 */
+	public IMethodBinding getGenericMethod();
+	
+	/**
+	 * Returns whether this method binding represents an instance of
+	 * a generic method corresponding to a raw method reference.
+	 * <p>
+	 * Note that {@link #isGenericMethod()},
+	 * {@link #isParameterizedMethod()},
+	 * and {@link #isRawMethod()} are mutually exclusive.
+	 * </p>
+	 * <p>
+	 * Note: Support for new language features proposed for the upcoming 1.5
+	 * release of J2SE is tentative and subject to change.
+	 * </p>
+	 *
+	 * @return <code>true</code> if this method binding represents a 
+	 * an instance of a generic method corresponding to a raw
+	 * method reference, and <code>false</code> otherwise
+	 * @see #getGenericMethod()
+	 * @see #getTypeArguments()
+	 * @since 3.1
+	 */
+	public boolean isRawMethod();
+	
+	/**
+	 * Returns whether this is a variable arity method.
+	 * <p>
+	 * Note: Variable arity ("varargs") methods were added in JLS3.
+	 * </p>
+	 * 
+	 * @return <code>true</code> if this is a variable arity method,
+	 *    and <code>false</code> otherwise
+	 * @since 3.1
+	 */ 
+	public boolean isVarargs();
+	
+	/**
+	 * Returns whether this method overrides the given method,
+	 * as specified in section 6.4.2 of <em>The Java Language 
+	 * Specification, Second Edition</em> (JLS2).
+	 * 
+	 * @param method the method that is possibly overriden
+	 * @return <code>true</code> if this method overrides the given method,
+	 * and <code>false</code> otherwise
+	 * @since 3.1
+	 */
+	public boolean overrides(IMethodBinding method);
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IPackageBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IPackageBinding.java
index 46404cd..c327583 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IPackageBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IPackageBinding.java
@@ -24,12 +24,10 @@
 	/**
 	 * Returns the name of the package represented by this binding. For named
 	 * packages, this is the fully qualified package name (using "." for 
-	 * separators). For unnamed packages, this is a distinctive string
-	 * that can be used to refer to this unnamed package (since there
-	 * may in fact be multiple unnamed packages).
+	 * separators). For unnamed packages, this is an empty string.
 	 * 
-	 * @return the name of the package represented by this binding, or an
-	 *    internal identifier for an unnamed package
+	 * @return the name of the package represented by this binding, or
+	 *    an empty string for an unnamed package
 	 */
 	public String getName();
 	
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
index 42ec1e8..737f046 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
@@ -30,13 +30,14 @@
  * <li>the null type - this is the special type of <code>null</code></li>
  * <li>a type variable - represents the declaration of a type variable;
  * possibly with type bounds</li>
- * <li>a parameterized type reference - represents a reference to a
- * parameterized type with type arguments (which may include wildcards)</li>
- * <li>a raw type reference - represents a (legacy) reference to a parameterized
- * type without any type arguments</li>
  * <li>a wildcard type - represents a wild card used as a type argument in
  * a parameterized type reference</li>
  * </ul>
+ * Type bindings usually correspond directly to class or
+ * interface declarations found in the source code. However,
+ * in some cases of references to a type declared in a generic type,
+ * the type binding corresponds to an copy of a type declaration
+ * with substitutions for its type parameters.
  * <p>
  * This interface is not intended to be implemented by clients.
  * </p>
@@ -49,7 +50,7 @@
  * @since 2.0
  */
 public interface ITypeBinding extends IBinding {
-
+	
 	/**
 	 * Returns the binary name of this type binding.
 	 * The binary name of a class is defined in the Java Language 
@@ -121,6 +122,30 @@
 	public int getDimensions();
 	
 	/**
+	 * Returns whether this type is assigment compatible with the given type,
+	 * as specified in section 5.2 of <em>The Java Language 
+	 * Specification, Second Edition</em> (JLS2).
+	 * 
+	 * @param type the type to check compatibility against
+	 * @return <code>true</code> if this type is assigment compatible with the
+	 * given type, and <code>false</code> otherwise
+	 * @since 3.1
+	 */
+	public boolean isAssignmentCompatible(ITypeBinding type);
+	
+	/**
+	 * Returns whether this type is cast compatible with the given type,
+	 * as specified in section 5.5 of <em>The Java Language 
+	 * Specification, Second Edition</em> (JLS2).
+	 * 
+	 * @param type the type to check compatibility against
+	 * @return <code>true</code> if this type is cast compatible with the
+	 * given type, and <code>false</code> otherwise
+	 * @since 3.1
+	 */
+	public boolean isCastCompatible(ITypeBinding type);
+
+	/**
 	 * Returns whether this type binding represents a class type.
 	 *
 	 * @return <code>true</code> if this object represents a class,
@@ -165,10 +190,11 @@
 	/**
 	 * Returns the type parameters of this class or interface type binding.
 	 * <p>
-	 * Note that type parameters only occur on the declaring class or
-	 * interface; e.g., <code>Collection&lt;T&gt;</code>. Do not confuse
-	 * them with type arguments which only occur on references; 
-	 * e.g., <code>Collection&lt;String&gt;</code>.
+	 * Note that type parameters only occur on the binding of the
+	 * declaring generic class or interface; e.g., <code>Collection&lt;T&gt;</code>.
+	 * Type bindings corresponding to a raw or parameterized reference to a generic
+	 * type do not carry type parameters (they instead have non-empty type arguments
+	 * and non-trivial erasure).
 	 * </p> 
 	 * <p>
 	 * Note: Support for new language features proposed for the upcoming 1.5
@@ -180,9 +206,38 @@
 	 * @see #isTypeVariable()
 	 * @since 3.0
 	 */
+	// TODO (jeem) - clarify whether binding for a generic type instance carries a copy of the generic type's type parameters as well as type arguments
 	public ITypeBinding[] getTypeParameters();
 	
 	/**
+	 * Returns whether this type binding represents a declaration of
+	 * a generic class or interface.
+	 * <p>
+	 * Note that type parameters only occur on the binding of the
+	 * declaring generic class or interface; e.g., <code>Collection&lt;T&gt;</code>.
+	 * Type bindings corresponding to a raw or parameterized reference to a generic
+	 * type do not carry type parameters (they instead have non-empty type arguments
+	 * and non-trivial erasure).
+	 * This method is fully equivalent to <code>getTypeParameters().length &gt; 0)</code>.
+	 * </p>
+	 * <p>
+	 * Note that {@link #isGenericType()},
+	 * {@link #isParameterizedType()},
+	 * and {@link #isRawType()} are mutually exclusive.
+	 * </p>
+	 * <p>
+	 * Note: Support for new language features of the 1.5
+	 * release of J2SE is tentative and subject to change.
+	 * </p>
+	 *
+	 * @return <code>true</code> if this type binding represents a 
+	 * declaration of a generic class or interface, and <code>false</code> otherwise
+	 * @see #getTypeParameters()
+	 * @since 3.1
+	 */
+	public boolean isGenericType();
+	
+	/**
 	 * Returns whether this type binding represents a type variable.
 	 * Type variables bindings carry the type variable's bounds.
 	 * <p>
@@ -192,6 +247,7 @@
 	 * 
 	 * @return <code>true</code> if this type binding is for a type variable,
 	 *   and <code>false</code> otherwise
+	 * @see #getName()
 	 * @see #getTypeBounds()
 	 * @since 3.0
 	 */
@@ -212,82 +268,130 @@
 	public ITypeBinding[] getTypeBounds();
 	
 	/**
-	 * Returns whether this type binding represents a parameterized 
-	 * type reference.
+	 * Returns whether this type binding represents an instance of
+	 * a generic type corresponding to a parameterized type reference.
 	 * <p>
-	 * For example, a AST type like 
+	 * For example, an AST type like 
 	 * <code>Collection&lt;String&gt;</code> typically resolves to a
-	 * parameterized type binding whose erasure is a type binding for the class 
-	 * <code>java.util.Collection</code> and whose type argument is a type
-	 * binding for the class <code>java.util.Collection</code>.
+	 * type binding whose type argument is the type binding for the
+	 * class <code>java.lang.String</code> and whose erasure is the type
+	 * binding for the generic type <code>java.util.Collection</code>.
 	 * </p>
-	 * <p>
-	 * Note: Support for new language features proposed for the upcoming 1.5
-	 * release of J2SE is tentative and subject to change.
+	 * Note that {@link #isGenericType()},
+	 * {@link #isParameterizedType()},
+	 * and {@link #isRawType()} are mutually exclusive.
 	 * </p>
 	 *
-	 * @return <code>true</code> if this object represents a parameterized
+	 * @return <code>true</code> if this type binding represents a 
+	 * an instance of a generic type corresponding to a parameterized
 	 * type reference, and <code>false</code> otherwise
 	 * @see #getTypeArguments()
-	 * @see #getErasure()
+	 * @see #getGenericType()
 	 * @since 3.0
 	 */
 	public boolean isParameterizedType();
 	
 	/**
-	 * Returns the type arguments of the parameterized type reference.
+	 * Returns the type arguments of this generic type instance, or the
+	 * empty list for other type bindings.
 	 * <p>
-	 * Note that type arguments only occur on type references; 
-	 * e.g., <code>Collection&lt;String&gt;</code>.
-	 * Do not confuse with type parameters which only occur on the
-	 * declaring class or interface; e.g., <code>Collection&lt;T&gt;</code>.
+	 * Note that type arguments only occur on a type binding that represents
+	 * an instance of a generic type corresponding to a parameterized type
+	 * reference (e.g., <code>Collection&lt;String&gt;</code>) or to a raw
+	 * type reference (e.g., <code>Collection</code>) to a generic type.
+	 * Do not confuse these with type parameters which only occur on the
+	 * type binding corresponding directly to the declaration of the 
+	 * generic class or interface (e.g., <code>Collection&lt;T&gt;</code>).
 	 * </p> 
 	 * <p>
 	 * Note: Support for new language features proposed for the upcoming 1.5
 	 * release of J2SE is tentative and subject to change.
 	 * </p>
 	 *
-	 * @return the list of type bindings for the type arguments of this
-	 * parameterized type, or otherwise the empty list
+	 * @return the list of type bindings for the type arguments used to
+	 * instantiate the corrresponding generic type, or otherwise the empty list
+	 * @see #getGenericType()
+	 * @see #isGenericType()
+	 * @see #isParameterizedType()
+	 * @see #isRawType()
 	 * @since 3.0
 	 */
 	public ITypeBinding[] getTypeArguments();
 	
 	/**
-	 * Returns the erasure of this type reference. For a parameterized
-	 * type reference or a raw type reference, returns the type binding for
-	 * the class or interface where the referenced type is declared.
-	 * Returns this type binding for types other than parameterized types.
+	 * Returns the erasure of this type binding.
+	 * In the presense of generic types, some bindings correspond to
+	 * types declarations in the context of a particular instance of
+	 * the generic type. In those cases, this method returns
+	 * the generic type binding from which this type binding
+	 * was instantiated. For other type bindings, this method returns
+	 * the identical type binding.
+	 * Note that the resulting type binding will answer true to
+	 * {@link #isGenericType()} iff this type binding would return true
+	 * to either {@link #isGenericType()}, {@link #isParameterizedType()},
+	 * or {@link #isRawType()}.
 	 * <p>
 	 * Note: Support for new language features proposed for the upcoming 1.5
 	 * release of J2SE is tentative and subject to change.
 	 * </p>
 	 *
-	 * @return the erasure type
-	 * @see #isRawType()
-	 * @see #isParameterizedType()
+	 * @return the erasure type binding
 	 * @since 3.0
+	 * @deprecated Use {@link #getGenericType()} instead.
 	 */
+	// TODO (jeem) - remove before 3.1M5 (bug 80800)
 	public ITypeBinding getErasure();
 	
 	/**
-	 * Returns whether this type binding represents a raw type reference. 
-	 * A raw type is a unparameterized (legacy) reference to a type declared
-	 * with type parameters.
+	 * Returns the generic type corresponding to this type binding.
+	 * In the presense of generic types, some bindings correspond to
+	 * types declarations in the context of a particular instance of
+	 * the generic type. In those cases, this method returns
+	 * the generic type binding from which this type binding
+	 * was instantiated. For other type bindings, this method returns
+	 * the identical type binding.
+	 * Note that the resulting type binding will answer true to
+	 * {@link #isGenericType()} iff this type binding would return true
+	 * to either {@link #isGenericType()}, {@link #isParameterizedType()},
+	 * or {@link #isRawType()}.
 	 * <p>
-	 * For example, a AST type like 
+	 * Note: Support for new language features proposed for the upcoming 1.5
+	 * release of J2SE is tentative and subject to change.
+	 * </p>
+	 *
+	 * @return the generic type binding
+	 * @since 3.1
+	 */
+	public ITypeBinding getGenericType();
+	
+	/**
+	 * Returns whether this type binding represents an instance of
+	 * a generic type corresponding to a raw type reference.
+	 * <p>
+	 * For example, an AST type like 
 	 * <code>Collection</code> typically resolves to a
-	 * raw type binding whose erasure is a type binding for the class 
+	 * type binding whose type argument is the type binding for
+	 * the class <code>java.lang.Object</code> (the
+	 * default bound for the single type parameter of 
+	 * <code>java.util.Collection</code>) and whose erasure is the
+	 * type binding for the generic type
 	 * <code>java.util.Collection</code>.
 	 * </p>
 	 * <p>
+	 * Note that {@link #isGenericType()},
+	 * {@link #isParameterizedType()},
+	 * and {@link #isRawType()} are mutually exclusive.
+	 * </p>
+	 * <p>
 	 * Note: Support for new language features proposed for the upcoming 1.5
 	 * release of J2SE is tentative and subject to change.
 	 * </p>
 	 *
-	 * @return <code>true</code> if this object represents a raw type,
-	 *    and <code>false</code> otherwise
-	 * @see #getErasure()
+	 * @return <code>true</code> if this type binding represents a 
+	 * an instance of a generic type corresponding to a raw
+	 * type reference, and <code>false</code> otherwise
+	 * @see #getGenericType()
+	 * @see #getTypeArguments()
 	 * @since 3.0
 	 */
 	public boolean isRawType();
@@ -350,25 +454,41 @@
 	/**
 	 * Returns the unqualified name of the type represented by this binding
 	 * if it has one.
-	 * <p>
-	 * For named classes, interfaces, enums, and annotation types, this is the
-	 * simple name of the type; if the type is parameterized, the name is
-	 * followed by the simple names of the type variables surrounded
-	 * by "&lt;&gt;" and separated by "," (the type bounds are not included).
-	 * For primitive types, the name is the keyword for the primitive type. For
-	 * array types, the name is the name of the component type (as computed by
-	 * this method) followed by "[]". If this represents an
-	 * anonymous class, it returns an empty string (note that it is impossible
-	 * to have an array type with an anonymous class as element type). For the
-	 * null type, it returns "null".
-	 * For type variables, this is the name of the type variable.
-	 * For parameterized type references, this is the simple name of the
-	 * erasure type followed by the names of the type arguments (as computed by
-	 * this method) surrounded by "&lt;&gt;" and separated by ",".
-	 * For raw type references, this is the simple name of the erasure type.
-	 * For wildcard types, this is "?" followed by the name of the bound 
-	 * (as computed by this method) when present.
-	 * </p>
+	 * <ul>
+	 * <li>For top-level types, member types, and local types,
+	 * the name is the simple name of the type.
+	 * Example: <code>"String"</code> or <code>"Collection"</code>.
+	 * Note that the type parameters of a generic type are not included.</li>
+	 * <li>For primitive types, the name is the keyword for the primitive type.
+	 * Example: <code>"int"</code>.</li>
+	 * <li>For the null type, the name is the string "null".</li>
+	 * <li>For anonymous classes, which do not have a name,
+	 * this method returns an empty string.</li>
+	 * <li>For array types, the name is the unqualified name of the component
+	 * type (as computed by this method) followed by "[]".
+	 * Example: <code>"String[]"</code>. Note that the component type is never an
+	 * an anonymous class.</li>
+	 * <li>For type variables, the name is just the simple name of the
+	 * type variable (type bounds are not included).
+	 * Example: <code>"X"</code>.</li>
+	 * <li>For type bindings that correspond to particular instances of a generic
+	 * type arising from a parameterized type reference,
+	 * the name is the unqualified name of the erasure type (as computed by this method)
+	 * followed by the names (again, as computed by this method) of the type arguments
+	 * surrounded by "&lt;&gt;" and separated by ",".
+	 * Example: <code>"Collection&lt;String&gt;"</code>.
+	 * </li>
+	 * <li>For type bindings that correspond to particular instances of a generic
+	 * type arising from a raw type reference, the name is the unqualified name of
+	 * the erasure type (as computed by this method).
+	 * Example: <code>"Collection"</code>.</li>
+	 * <li>For wildcard types, the name is "?" optionally followed by 
+	 * a single space followed by the keyword "extends" or "super"
+	 * followed a single space followed by the name of the bound (as computed by
+	 * this method) when present.
+	 * Example: <code>"? extends InputStream"</code>.
+	 * </li>
+	 * </ul> 
 	 * 
 	 * @return the unqualified name of the type represented by this binding,
 	 * or the empty string if it has none
@@ -382,8 +502,7 @@
 	 * @return the binding for the package in which this class, interface,
 	 * enum, or annotation type is declared, or <code>null</code> if this type
 	 * binding represents a primitive type, an array type, the null type, 
-	 * a type variable, a parameterized type reference, a raw type reference,
-	 * or a wildcard type
+	 * a type variable, or a wildcard type.
 	 */
 	public IPackageBinding getPackage();
 	
@@ -397,8 +516,7 @@
 	 * classes) is the innermost class or interface containing the expression
 	 * or statement in which this type is declared. Array types,
 	 * primitive types, the null type, top-level types, type variables,
-	 * parameterized type references, raw type references, and wildcard types
-	 * have no declaring class.
+	 * and wildcard types have no declaring class.
 	 * </p>
 	 * 
 	 * @return the binding of the type that declares this type, or
@@ -425,8 +543,8 @@
 	 * <p>
 	 * If this type binding represents an interface, an array type, a
 	 * primitive type, the null type, a type variable, an enum type,
-	 * an annotation type, a parameterized type reference, a raw type
-	 * reference, or a wildcard type, then <code>null</code> is returned.
+	 * an annotation type, or a wildcard type, then <code>null</code>
+	 * is returned.
 	 * </p>
 	 *
 	 * @return the superclass of the class represented by this type binding,
@@ -457,8 +575,7 @@
 	 * If the class or enum implements no interfaces, or the interface extends 
 	 * no interfaces, or if this type binding represents an array type, a
 	 * primitive type, the null type, a type variable, an annotation type, 
-	 * a parameterized type reference, a raw type reference, or a wildcard type,
-	 * this method returns an array of length 0.
+	 * or a wildcard type, this method returns an array of length 0.
 	 * </p>
 	 *
 	 * @return the list of type bindings for the interfaces extended by this
@@ -499,6 +616,18 @@
 	public int getDeclaredModifiers();
 	
 	/**
+	 * Returns whether this type is subtype compatible with the given type,
+	 * as specified in section 4.10 of <em>The Java Language 
+	 * Specification, Third Edition</em> (JLS3).
+	 * 
+	 * @param type the type to check compatibility against
+	 * @return <code>true</code> if this type is subtype compatible with the
+	 * given type, and <code>false</code> otherwise
+	 * @since 3.1
+	 */
+	public boolean isSubTypeCompatible(ITypeBinding type);
+	
+	/**
 	 * Returns whether this type binding represents a top-level class,
 	 * interface, enum, or annotation type.
 	 * <p>
@@ -578,8 +707,8 @@
 	 * and private classes, interfaces, enum types, and annotation types
 	 * declared by the type, but excludes inherited types. Returns an empty
 	 * list if the type declares no type members, or if this type
-	 * binding represents an array type, a primitive type, a wildcard type,
-	 * a parameterized type reference, a raw type reference, or the null type.
+	 * binding represents an array type, a primitive type, a type variable,
+	 * a wildcard type, or the null type.
 	 * The resulting bindings are in no particular order.
 	 * 
 	 * @return the list of type bindings for the member types of this type,
@@ -635,10 +764,11 @@
 	 * Returns the fully qualified name of the type represented by this 
 	 * binding if it has one.
 	 * <ul>
-	 * <li>For top-level types, the fully qualified name is the name of
-	 * the type (as computed by {@link #getName()}) preceded by the package
-	 * name (or unqualified if in a default package) and a ".".
-	 * Example: <code>"java.lang.String"</code>.</li>
+	 * <li>For top-level types, the fully qualified name is the simple name of
+	 * the type preceded by the package name (or unqualified if in a default package)
+	 * and a ".".
+	 * Example: <code>"java.lang.String"</code> or <code>"java.util.Collection"</code>.
+	 * Note that the type parameters of a generic type are not included.</li>
 	 * <li>For members of top-level types, the fully qualified name is the
 	 * simple name of the type preceded by the fully qualified name of the
 	 * enclosing type (as computed by this method) and a ".".
@@ -646,37 +776,39 @@
 	 * <li>For primitive types, the fully qualified name is the keyword for
 	 * the primitive type.
 	 * Example: <code>"int"</code>.</li>
-	 * <li>For array types whose component type has a fully qualified name, 
-	 * the fully qualified name is the fully qualified name of the component
-	 * type (as computed by this method) followed by "[]".
-	 * Example: <code>"java.lang.String[]"</code>.</li>
 	 * <li>For the null type, the fully qualified name is the string 
 	 * "null".</li>
 	 * <li>Local types (including anonymous classes) and members of local
 	 * types do not have a fully qualified name. For these types, and array
 	 * types thereof, this method returns an empty string.</li>
+	 * <li>For array types whose component type has a fully qualified name, 
+	 * the fully qualified name is the fully qualified name of the component
+	 * type (as computed by this method) followed by "[]".
+	 * Example: <code>"java.lang.String[]"</code>.</li>
 	 * <li>For type variables, the fully qualified name is just the name of the
 	 * type variable (type bounds are not included).
 	 * Example: <code>"X"</code>.</li>
-	 * <li>For raw type references, the fully qualified name is the 
-	 * fully qualified name of the type but with the type parameters
-	 * omitted.
-	 * Example: <code>"java.util.Collection"</code>.</li>
-	 * <li>For parameterized type references, the fully qualified name is the 
-	 * fully qualified name of the erasure type followed by the fully qualified
-	 * names of the type arguments surrounded by "&lt;&gt;" and separated by ",".
+	 * <li>For type bindings that correspond to particular instances of a generic
+	 * type arising from a parameterized type reference,
+	 * the fully qualified name is the fully qualified name of the erasure
+	 * type followed by the fully qualified names of the type arguments surrounded by "&lt;&gt;" and separated by ",".
 	 * Example: <code>"java.util.Collection&lt;java.lang.String&gt;"</code>.
 	 * </li>
-	 * <li>For wildcard types, the fully qualified name is "?" followed by the
-	 * fully qualified name of the bound (as computed by this method) when
-	 * present.
-	 * Example: <code>"? extends java.lang.Object"</code>.
+	 * <li>For type bindings that correspond to particular instances of a generic
+	 * type arising from a raw type reference,
+	 * the fully qualified name is the fully qualified name of the erasure type.
+	 * Example: <code>"java.util.Collection"</code>. Note that the
+	 * the type parameters are omitted.</li>
+	 * <li>For wildcard types, the fully qualified name is "?" optionally followed by 
+	 * a single space followed by the keyword "extends" or "super" 
+	 * followed a single space followed by the fully qualified name of the bound
+	 * (as computed by this method) when present.
+	 * Example: <code>"? extends java.io.InputStream"</code>.
 	 * </li>
 	 * </ul>
 	 * 
 	 * @return the fully qualified name of the type represented by this 
 	 *    binding, or the empty string if it has none
-
 	 * @see #getName()
 	 * @since 2.1
 	 */
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IVariableBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IVariableBinding.java
index b8a6c00..e88a0cd 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IVariableBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IVariableBinding.java
@@ -104,4 +104,23 @@
 	 * @since 3.0
 	 */
 	public Object getConstantValue();
+	
+	/**
+	 * Returns the method binding representing the method containing the scope
+	 * in which this local variable is declared.
+	 * <p>
+	 * The declaring method of a method formal parameter is the method itself.
+	 * For a local variable declared somewhere within the body of a method,
+	 * the declaring method is the enclosing method. When local or anonymous
+	 * classes are involved, the declaring method is the innermost such method.
+	 * There is no declaring method for a field, or for a local variable
+	 * declared in a static or instance initializer; this method returns
+	 * <code>null</code> in those cases.
+	 * </p>
+	 * 
+	 * @return the binding of the method or constructor that declares this
+	 * local variable, or <code>null</code> if none
+	 * @since 3.1
+	 */
+	public IMethodBinding getDeclaringMethod();
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IfStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IfStatement.java
index 91c863b..bc4365b 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IfStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IfStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -53,11 +54,12 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(IfStatement.class);
-		addProperty(EXPRESSION_PROPERTY);
-		addProperty(THEN_STATEMENT_PROPERTY);
-		addProperty(ELSE_STATEMENT_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(4);
+		createPropertyList(IfStatement.class, properyList);
+		addProperty(EXPRESSION_PROPERTY, properyList);
+		addProperty(THEN_STATEMENT_PROPERTY, properyList);
+		addProperty(ELSE_STATEMENT_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ImportDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ImportDeclaration.java
index bc9b34b..e36f01d 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ImportDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ImportDeclaration.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -68,16 +69,18 @@
 	private static final List PROPERTY_DESCRIPTORS_3_0;
 	
 	static {
-		createPropertyList(ImportDeclaration.class);
-		addProperty(NAME_PROPERTY);
-		addProperty(ON_DEMAND_PROPERTY);
-		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList();
+		List properyList = new ArrayList(3);
+		createPropertyList(ImportDeclaration.class, properyList);
+		addProperty(NAME_PROPERTY, properyList);
+		addProperty(ON_DEMAND_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
 		
-		createPropertyList(ImportDeclaration.class);
-		addProperty(STATIC_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(ON_DEMAND_PROPERTY);
-		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList();
+		properyList = new ArrayList(4);
+		createPropertyList(ImportDeclaration.class, properyList);
+		addProperty(STATIC_PROPERTY, properyList);
+		addProperty(NAME_PROPERTY, properyList);
+		addProperty(ON_DEMAND_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InfixExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InfixExpression.java
index 06de8b1..6a4acb7 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InfixExpression.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InfixExpression.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -207,12 +208,13 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(InfixExpression.class);
-		addProperty(LEFT_OPERAND_PROPERTY);
-		addProperty(OPERATOR_PROPERTY);
-		addProperty(RIGHT_OPERAND_PROPERTY);
-		addProperty(EXTENDED_OPERANDS_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(5);
+		createPropertyList(InfixExpression.class, properyList);
+		addProperty(LEFT_OPERAND_PROPERTY, properyList);
+		addProperty(OPERATOR_PROPERTY, properyList);
+		addProperty(RIGHT_OPERAND_PROPERTY, properyList);
+		addProperty(EXTENDED_OPERANDS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Initializer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Initializer.java
index 876ec68..72de196 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Initializer.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Initializer.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -70,17 +71,19 @@
 	private static final List PROPERTY_DESCRIPTORS_3_0;
 	
 	static {
-		createPropertyList(Initializer.class);
-		addProperty(JAVADOC_PROPERTY);
-		addProperty(MODIFIERS_PROPERTY);
-		addProperty(BODY_PROPERTY);
-		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList();
+		List properyList = new ArrayList(4);
+		createPropertyList(Initializer.class, properyList);
+		addProperty(JAVADOC_PROPERTY, properyList);
+		addProperty(MODIFIERS_PROPERTY, properyList);
+		addProperty(BODY_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
 		
-		createPropertyList(Initializer.class);
-		addProperty(JAVADOC_PROPERTY);
-		addProperty(MODIFIERS2_PROPERTY);
-		addProperty(BODY_PROPERTY);
-		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList();
+		properyList = new ArrayList(4);
+		createPropertyList(Initializer.class, properyList);
+		addProperty(JAVADOC_PROPERTY, properyList);
+		addProperty(MODIFIERS2_PROPERTY, properyList);
+		addProperty(BODY_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InstanceofExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InstanceofExpression.java
index 24dfff9..6f9ccbf 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InstanceofExpression.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InstanceofExpression.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -46,10 +47,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(InstanceofExpression.class);
-		addProperty(LEFT_OPERAND_PROPERTY);
-		addProperty(RIGHT_OPERAND_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(3);
+		createPropertyList(InstanceofExpression.class, properyList);
+		addProperty(LEFT_OPERAND_PROPERTY, properyList);
+		addProperty(RIGHT_OPERAND_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Javadoc.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Javadoc.java
index 5e420c3..dfb9646 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Javadoc.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Javadoc.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.eclipse.jdt.core.compiler.InvalidInputException;
@@ -61,14 +62,16 @@
 	private static final List PROPERTY_DESCRIPTORS_3_0;
 	
 	static {
-		createPropertyList(Javadoc.class);
-		addProperty(COMMENT_PROPERTY);
-		addProperty(TAGS_PROPERTY);
-		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList();
+		List properyList = new ArrayList(3);
+		createPropertyList(Javadoc.class, properyList);
+		addProperty(COMMENT_PROPERTY, properyList);
+		addProperty(TAGS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
 		
-		createPropertyList(Javadoc.class);
-		addProperty(TAGS_PROPERTY);
-		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList();
+		properyList = new ArrayList(2);
+		createPropertyList(Javadoc.class, properyList);
+		addProperty(TAGS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LabeledStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LabeledStatement.java
index 08d8436..de40526 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LabeledStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LabeledStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -47,10 +48,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(LabeledStatement.class);
-		addProperty(LABEL_PROPERTY);
-		addProperty(BODY_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(LabeledStatement.class, propertyList);
+		addProperty(LABEL_PROPERTY, propertyList);
+		addProperty(BODY_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LineComment.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LineComment.java
index 15ec4a6..c40b816 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LineComment.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LineComment.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -38,8 +39,9 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(LineComment.class);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(1);
+		createPropertyList(LineComment.class, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MarkerAnnotation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MarkerAnnotation.java
index 79332e8..c8b26e8 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MarkerAnnotation.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MarkerAnnotation.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -47,9 +48,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(MarkerAnnotation.class);
-		addProperty(TYPE_NAME_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(2);
+		createPropertyList(MarkerAnnotation.class, propertyList);
+		addProperty(TYPE_NAME_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 	
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberRef.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberRef.java
index 306ef4e..64ffd08 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberRef.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberRef.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -50,10 +51,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(MemberRef.class);
-		addProperty(QUALIFIER_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(MemberRef.class, propertyList);
+		addProperty(QUALIFIER_PROPERTY, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberValuePair.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberValuePair.java
index c7abc1a..b892e12 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberValuePair.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberValuePair.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -56,10 +57,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(MemberValuePair.class);
-		addProperty(NAME_PROPERTY);
-		addProperty(VALUE_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(MemberValuePair.class, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		addProperty(VALUE_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java
index 2c9f18f..5a42959 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java
@@ -11,13 +11,30 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
+import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.jdt.internal.compiler.lookup.MethodVerifier;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
+import org.eclipse.jdt.internal.core.Member;
 
 /**
  * Internal implementation of method bindings.
  */
 class MethodBinding implements IMethodBinding {
 
+	private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+		Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.SYNCHRONIZED | Modifier.NATIVE |
+		Modifier.STRICTFP;
 	private static final ITypeBinding[] NO_TYPE_BINDINGS = new ITypeBinding[0];
 	private org.eclipse.jdt.internal.compiler.lookup.MethodBinding binding;
 	private BindingResolver resolver;
@@ -25,7 +42,10 @@
 	private ITypeBinding[] exceptionTypes;
 	private String name;
 	private ITypeBinding declaringClass;
-	private ITypeBinding returnType; 
+	private ITypeBinding returnType;
+	private String key;
+	private ITypeBinding[] typeParameters;
+	private ITypeBinding[] typeArguments;
 	
 	MethodBinding(BindingResolver resolver, org.eclipse.jdt.internal.compiler.lookup.MethodBinding binding) {
 		this.resolver = resolver;
@@ -84,11 +104,12 @@
 		org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] parameters = this.binding.parameters;
 		int length = parameters.length;
 		if (length == 0) {
-			return NO_TYPE_BINDINGS;
-		}
-		this.parameterTypes = new ITypeBinding[length];
-		for (int i = 0; i < length; i++) {
-			this.parameterTypes[i] = this.resolver.getTypeBinding(parameters[i]);
+			this.parameterTypes = NO_TYPE_BINDINGS;
+		} else {
+			this.parameterTypes = new ITypeBinding[length];
+			for (int i = 0; i < length; i++) {
+				this.parameterTypes[i] = this.resolver.getTypeBinding(parameters[i]);
+			}
 		}
 		return this.parameterTypes;
 	}
@@ -102,6 +123,61 @@
 		}
 		return this.returnType;
 	}
+	
+	/*
+	 * Returns the signature of the given type.
+	 */
+	private String getSignature(Type type) {
+		StringBuffer buffer = new StringBuffer();
+		getFullyQualifiedName(type, buffer);
+		return Signature.createTypeSignature(buffer.toString(), false/*not resolved in source*/);
+	}
+	
+	/*
+	 * Appends to the given buffer the fully qualified name (as it appears in the source) of the given type
+	 */
+	private void getFullyQualifiedName(Type type, StringBuffer buffer) {
+		if (type.isArrayType()) {
+			ArrayType arrayType = (ArrayType) type;
+			getFullyQualifiedName(arrayType.getElementType(), buffer);
+			for (int i = 0, length = arrayType.getDimensions(); i < length; i++) {
+				buffer.append('[');
+				buffer.append(']');
+			}
+		} else if (type.isParameterizedType()) {
+			ParameterizedType parameterizedType = (ParameterizedType) type;
+			getFullyQualifiedName(parameterizedType.getType(), buffer);
+			buffer.append('<');
+			Iterator iterator = parameterizedType.typeArguments().iterator();
+			boolean isFirst = true;
+			while (iterator.hasNext()) {
+				if (!isFirst)
+					buffer.append(',');
+				else
+					isFirst = false;
+				Type typeArgument = (Type) iterator.next();
+				getFullyQualifiedName(typeArgument, buffer);
+			}
+			buffer.append('>');
+		} else if (type.isPrimitiveType()) {
+			buffer.append(((PrimitiveType) type).getPrimitiveTypeCode().toString());
+		} else if (type.isQualifiedType()) {
+			buffer.append(((QualifiedType) type).getName().getFullyQualifiedName());
+		} else if (type.isSimpleType()) {
+			buffer.append(((SimpleType) type).getName().getFullyQualifiedName());
+		} else if (type.isWildcardType()) {
+			buffer.append('?');
+			WildcardType wildcardType = (WildcardType) type;
+			Type bound = wildcardType.getBound();
+			if (bound == null) return;
+			if (wildcardType.isUpperBound()) {
+				buffer.append(" extends "); //$NON-NLS-1$
+			} else {
+				buffer.append(" super "); //$NON-NLS-1$
+			}
+			getFullyQualifiedName(bound, buffer);
+		}
+	}
 
 	/*
 	 * @see IMethodBinding#getExceptionTypes()
@@ -113,15 +189,59 @@
 		org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] exceptions = this.binding.thrownExceptions;
 		int length = exceptions.length;
 		if (length == 0) {
-			return NO_TYPE_BINDINGS;
-		}
-		this.exceptionTypes = new ITypeBinding[length];
-		for (int i = 0; i < length; i++) {
-			this.exceptionTypes[i] = this.resolver.getTypeBinding(exceptions[i]);
+			this.exceptionTypes = NO_TYPE_BINDINGS;
+		} else {
+			this.exceptionTypes = new ITypeBinding[length];
+			for (int i = 0; i < length; i++) {
+				this.exceptionTypes[i] = this.resolver.getTypeBinding(exceptions[i]);
+			}
 		}
 		return this.exceptionTypes;
 	}
 
+	public IJavaElement getJavaElement() {
+		IType declaringType = (IType) getDeclaringClass().getJavaElement();
+		if (declaringType == null) return null;
+		if (!(this.resolver instanceof DefaultBindingResolver)) return null;
+		MethodDeclaration methodDeclaration = (MethodDeclaration) ((DefaultBindingResolver) this.resolver).bindingsToAstNodes.get(this);
+		if (methodDeclaration != null) {
+			ArrayList parameterSignatures = new ArrayList();
+			Iterator iterator = methodDeclaration.parameters().iterator();
+			while (iterator.hasNext()) {
+				SingleVariableDeclaration parameter = (SingleVariableDeclaration) iterator.next();
+				Type type = parameter.getType();
+				parameterSignatures.add(getSignature(type));
+			}
+			int parameterCount = parameterSignatures.size();
+			String[] parameters = new String[parameterCount];
+			parameterSignatures.toArray(parameters);
+			return declaringType.getMethod(getName(), parameters);
+		} else {
+			// case of method not in the created AST
+			String selector = getName();
+			char[] methodSignature = this.binding.genericSignature();
+			if (methodSignature == null)
+				methodSignature = this.binding.signature();
+			methodSignature = CharOperation.replaceOnCopy(methodSignature, '/', '.');
+			char[][] parameterSignatures = Signature.getParameterTypes(methodSignature);
+			String[] parameters = CharOperation.toStrings(parameterSignatures);
+			IMethod result = declaringType.getMethod(selector, parameters);
+			if (declaringType.isBinary())
+				return result;
+			IMethod[] methods = null;
+			try {
+				methods = declaringType.getMethods();
+			} catch (JavaModelException e) {
+				// declaring type doesn't exist
+				return null;
+			}
+			IMethod[] candidates = Member.findMethods(result, methods);
+			if (candidates == null || candidates.length == 0)
+				return null;
+			return candidates[0];
+		}
+	}
+	
 	/*
 	 * @see IBinding#getKind()
 	 */
@@ -133,7 +253,7 @@
 	 * @see IBinding#getModifiers()
 	 */
 	public int getModifiers() {
-		return this.binding.getAccessFlags();
+		return this.binding.getAccessFlags() & VALID_MODIFIERS;
 	}
 
 	/*
@@ -150,44 +270,155 @@
 		return this.binding.isSynthetic();
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.IMethodBinding#isVarargs()
+	 * @since 3.1
+	 */
+	public boolean isVarargs() {
+		return this.binding.isVarargs();
+	}
+
 	/*
 	 * @see IBinding#getKey()
 	 */
 	public String getKey() {
-		StringBuffer buffer = new StringBuffer();
-		buffer.append(this.getDeclaringClass().getKey());
-		buffer.append('/');
-		ITypeBinding _returnType = getReturnType();
-		if (_returnType != null) {
-			buffer.append(_returnType.getKey());
+		if (this.key == null) {
+			this.key = new String(this.binding.computeUniqueKey());
 		}
-		if (!isConstructor()) {
-			buffer.append(this.getName());
+		return this.key;
+	}
+	
+	/*
+	 * @see IBinding#isEqualTo(Binding)
+	 * @since 3.1
+	 */
+	public boolean isEqualTo(IBinding other) {
+		if (other == this) {
+			// identical binding - equal (key or no key)
+			return true;
 		}
-		ITypeBinding[] parameters = getParameterTypes();
-		buffer.append('(');
-		for (int i = 0, max = parameters.length; i < max; i++) {
-			ITypeBinding parameter = parameters[i];
-			if (parameter != null) {
-				buffer.append(parameter.getKey());
-			}
+		if (other == null) {
+			// other binding missing
+			return false;
 		}
-		buffer.append(')');
-		ITypeBinding[] thrownExceptions = getExceptionTypes();
-		for (int i = 0, max = thrownExceptions.length; i < max; i++) {
-			if (thrownExceptions[i] != null) {
-				buffer.append(thrownExceptions[i].getKey());
-			}
+		if (!(other instanceof MethodBinding)) {
+			return false;
 		}
-		return buffer.toString();
+		org.eclipse.jdt.internal.compiler.lookup.MethodBinding otherBinding = ((MethodBinding) other).binding;
+		return BindingComparator.isEqual(this.binding, otherBinding);
 	}
 	
 	/* (non-Javadoc)
-	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeParameters()
+	 * @see org.eclipse.jdt.core.dom.IMethodBinding#getTypeParameters()
 	 */
 	public ITypeBinding[] getTypeParameters() {
-		// TODO (olivier) missing implementation of J2SE 1.5 language feature
-		return NO_TYPE_BINDINGS;
+		if (this.typeParameters != null) {
+			return this.typeParameters;
+		}
+		TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
+		if (typeVariableBindings != null) {
+			int typeVariableBindingsLength = typeVariableBindings.length;
+			if (typeVariableBindingsLength != 0) {
+				this.typeParameters = new ITypeBinding[typeVariableBindingsLength];
+				for (int i = 0; i < typeVariableBindingsLength; i++) {
+					typeParameters[i] = this.resolver.getTypeBinding(typeVariableBindings[i]);
+				}
+			} else {
+				this.typeParameters = NO_TYPE_BINDINGS;
+			}
+		} else {
+			this.typeParameters = NO_TYPE_BINDINGS;
+		}
+		return this.typeParameters;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ITypeBinding#isGenericMethod()
+	 * @since 3.1
+	 */
+	public boolean isGenericMethod() {
+		// equivalent to return getTypeParameters().length > 0;
+		if (this.typeParameters != null) {
+			return this.typeParameters.length > 0;
+		}
+		TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
+		return (typeVariableBindings != null && typeVariableBindings.length > 0);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.IMethodBinding#getTypeArguments()
+	 */
+	public ITypeBinding[] getTypeArguments() {
+		if (this.typeArguments != null) {
+			return this.typeArguments;
+		}
+
+		if (this.binding instanceof ParameterizedGenericMethodBinding) {
+			ParameterizedGenericMethodBinding genericMethodBinding = (ParameterizedGenericMethodBinding) this.binding;
+			org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] typeArgumentsBindings = genericMethodBinding.typeArguments;
+			if (typeArgumentsBindings != null) {
+				int typeArgumentsLength = typeArgumentsBindings.length;
+				if (typeArgumentsLength != 0) {
+					this.typeArguments = new ITypeBinding[typeArgumentsLength];
+					for (int i = 0; i < typeArgumentsLength; i++) {
+						this.typeArguments[i] = this.resolver.getTypeBinding(typeArgumentsBindings[i]);
+					}
+				} else {
+					this.typeArguments = NO_TYPE_BINDINGS;
+				}
+			} else {
+				this.typeArguments = NO_TYPE_BINDINGS;
+			}
+		} else {
+			this.typeArguments = NO_TYPE_BINDINGS;
+		}
+		return this.typeArguments;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.IMethodBinding#isParameterizedMethod()
+	 */
+	public boolean isParameterizedMethod() {
+		return (this.binding instanceof ParameterizedGenericMethodBinding)
+			&& !((ParameterizedGenericMethodBinding) this.binding).isRaw;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.IMethodBinding#isRawMethod()
+	 */
+	public boolean isRawMethod() {
+		return (this.binding instanceof ParameterizedGenericMethodBinding)
+			&& ((ParameterizedGenericMethodBinding) this.binding).isRaw;
+	}
+
+	/**
+	 * @deprecated Use {@link #getGenericMethod()} instead.
+	 */
+	// TODO (jeem) - remove before 3.1M5 (bug 80800)
+	public IMethodBinding getErasure() {
+		return getGenericMethod();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.IMethodBinding#getGenericMethod()
+	 */
+	public IMethodBinding getGenericMethod() {
+		return this.resolver.getMethodBinding(this.binding.original());
+	}
+	
+	/* (non-Javadoc)
+	 * @see IMethodBinding#overrides(IMethodBinding)
+	 */
+	public boolean overrides(IMethodBinding method) {
+		org.eclipse.jdt.internal.compiler.lookup.MethodBinding otherCompilerBinding = ((MethodBinding) method).binding;
+		if (this.binding == otherCompilerBinding) 
+			return false;
+		if (!this.binding.declaringClass.isCompatibleWith(otherCompilerBinding.declaringClass))
+			return false;
+		LookupEnvironment lookupEnvironment = this.resolver.lookupEnvironment();
+		if (lookupEnvironment == null) return false;
+		MethodVerifier methodVerifier = lookupEnvironment.methodVerifier();
+		return methodVerifier.doesMethodOverride(this.binding, otherCompilerBinding);
 	}
 
 	/* 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java
index 69feab4..0184d15 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
@@ -41,7 +42,9 @@
  * 		     { <b>,</b> FormalParameter } ] <b>)</b> {<b>[</b> <b>]</b> }
  *        [ <b>throws</b> TypeName { <b>,</b> TypeName } ] ( Block | <b>;</b> )
  * ConstructorDeclaration:
- *    [ Javadoc ] { ExtendedModifier } Identifier <b>(</b>
+ *    [ Javadoc ] { ExtendedModifier }
+ *		  [ <b>&lt;</b> TypeParameter { <b>,</b> TypeParameter } <b>&gt;</b> ]
+ *        Identifier <b>(</b>
  * 		  [ FormalParameter
  * 			 { <b>,</b> FormalParameter } ] <b>)</b>
  *        [<b>throws</b> TypeName { <b>,</b> TypeName } ] Block
@@ -165,30 +168,32 @@
 	private static final List PROPERTY_DESCRIPTORS_3_0;
 	
 	static {
-		createPropertyList(MethodDeclaration.class);
-		addProperty(JAVADOC_PROPERTY);
-		addProperty(MODIFIERS_PROPERTY);
-		addProperty(CONSTRUCTOR_PROPERTY);
-		addProperty(RETURN_TYPE_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(PARAMETERS_PROPERTY);
-		addProperty(EXTRA_DIMENSIONS_PROPERTY);
-		addProperty(THROWN_EXCEPTIONS_PROPERTY);
-		addProperty(BODY_PROPERTY);
-		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList();
+		List propertyList = new ArrayList(10);
+		createPropertyList(MethodDeclaration.class, propertyList);
+		addProperty(JAVADOC_PROPERTY, propertyList);
+		addProperty(MODIFIERS_PROPERTY, propertyList);
+		addProperty(CONSTRUCTOR_PROPERTY, propertyList);
+		addProperty(RETURN_TYPE_PROPERTY, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		addProperty(PARAMETERS_PROPERTY, propertyList);
+		addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+		addProperty(THROWN_EXCEPTIONS_PROPERTY, propertyList);
+		addProperty(BODY_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
 		
-		createPropertyList(MethodDeclaration.class);
-		addProperty(JAVADOC_PROPERTY);
-		addProperty(MODIFIERS2_PROPERTY);
-		addProperty(CONSTRUCTOR_PROPERTY);
-		addProperty(TYPE_PARAMETERS_PROPERTY);
-		addProperty(RETURN_TYPE2_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(PARAMETERS_PROPERTY);
-		addProperty(EXTRA_DIMENSIONS_PROPERTY);
-		addProperty(THROWN_EXCEPTIONS_PROPERTY);
-		addProperty(BODY_PROPERTY);
-		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList();
+		propertyList = new ArrayList(11);
+		createPropertyList(MethodDeclaration.class, propertyList);
+		addProperty(JAVADOC_PROPERTY, propertyList);
+		addProperty(MODIFIERS2_PROPERTY, propertyList);
+		addProperty(CONSTRUCTOR_PROPERTY, propertyList);
+		addProperty(TYPE_PARAMETERS_PROPERTY, propertyList);
+		addProperty(RETURN_TYPE2_PROPERTY, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		addProperty(PARAMETERS_PROPERTY, propertyList);
+		addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+		addProperty(THROWN_EXCEPTIONS_PROPERTY, propertyList);
+		addProperty(BODY_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
 	}
 
 	/**
@@ -527,12 +532,6 @@
 	 * Returns the live ordered list of type parameters of this method
 	 * declaration (added in JLS3 API). This list is non-empty for parameterized methods.
 	 * <p>
-	 * Note that these children are not relevant for constructor declarations
-	 * (although it does still figure in subtree equality comparisons
-	 * and visits), and is devoid of the binding information ordinarily
-	 * available.
-	 * </p>
-	 * <p>
 	 * Note: This API element is only needed for dealing with Java code that uses
 	 * new language features of J2SE 1.5. It is included in anticipation of J2SE
 	 * 1.5 support, which is planned for the next release of Eclipse after 3.0, and
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodInvocation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodInvocation.java
index c2b9026..87937be 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodInvocation.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodInvocation.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -78,18 +79,20 @@
 	private static final List PROPERTY_DESCRIPTORS_3_0;
 	
 	static {
-		createPropertyList(MethodInvocation.class);
-		addProperty(EXPRESSION_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(ARGUMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList();
+		List properyList = new ArrayList(4);
+		createPropertyList(MethodInvocation.class, properyList);
+		addProperty(EXPRESSION_PROPERTY, properyList);
+		addProperty(NAME_PROPERTY, properyList);
+		addProperty(ARGUMENTS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
 		
-		createPropertyList(MethodInvocation.class);
-		addProperty(EXPRESSION_PROPERTY);
-		addProperty(TYPE_ARGUMENTS_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(ARGUMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList();
+		properyList = new ArrayList(5);
+		createPropertyList(MethodInvocation.class, properyList);
+		addProperty(EXPRESSION_PROPERTY, properyList);
+		addProperty(TYPE_ARGUMENTS_PROPERTY, properyList);
+		addProperty(NAME_PROPERTY, properyList);
+		addProperty(ARGUMENTS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodRef.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodRef.java
index ab1307d..158a300 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodRef.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodRef.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -57,11 +58,12 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(MethodRef.class);
-		addProperty(QUALIFIER_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(PARAMETERS_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(4);
+		createPropertyList(MethodRef.class, properyList);
+		addProperty(QUALIFIER_PROPERTY, properyList);
+		addProperty(NAME_PROPERTY, properyList);
+		addProperty(PARAMETERS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodRefParameter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodRefParameter.java
index 207bced..7d0e656 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodRefParameter.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodRefParameter.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -48,10 +49,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(MethodRefParameter.class);
-		addProperty(TYPE_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(3);
+		createPropertyList(MethodRefParameter.class, properyList);
+		addProperty(TYPE_PROPERTY, properyList);
+		addProperty(NAME_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java
index f28f11a..0f62bf1 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -434,9 +435,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(Modifier.class);
-		addProperty(KEYWORD_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List properyList = new ArrayList(2);
+		createPropertyList(Modifier.class, properyList);
+		addProperty(KEYWORD_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NaiveASTFlattener.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NaiveASTFlattener.java
index c4a8a86..f176c79 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NaiveASTFlattener.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NaiveASTFlattener.java
@@ -42,6 +42,8 @@
 	 */
 	private StringBuffer buffer;
 	
+	private int indent = 0;
+	
 	/**
 	 * Creates a new AST printer.
 	 */
@@ -65,6 +67,11 @@
 		this.buffer.setLength(0);
 	}
 	
+	void printIndent() {
+		for (int i = 0; i < this.indent; i++) 
+			this.buffer.append("  "); //$NON-NLS-1$
+	}
+	
 	/**
 	 * Appends the text representation of the given modifier flags, followed by a single space.
 	 * Used for 3.0 modifiers and annotations.
@@ -130,6 +137,7 @@
 		if (node.getJavadoc() != null) {
 			node.getJavadoc().accept(this);
 		}
+		printIndent();
 		printModifiers(node.modifiers());
 		this.buffer.append("@interface ");//$NON-NLS-1$
 		node.getName().accept(this);
@@ -138,7 +146,7 @@
 			BodyDeclaration d = (BodyDeclaration) it.next();
 			d.accept(this);
 		}
-		this.buffer.append("}");//$NON-NLS-1$
+		this.buffer.append("}\n");//$NON-NLS-1$
 		return false;
 	}
 	
@@ -150,6 +158,7 @@
 		if (node.getJavadoc() != null) {
 			node.getJavadoc().accept(this);
 		}
+		printIndent();
 		printModifiers(node.modifiers());
 		node.getType().accept(this);
 		this.buffer.append(" ");//$NON-NLS-1$
@@ -159,7 +168,7 @@
 			this.buffer.append(" default ");//$NON-NLS-1$
 			node.getDefault().accept(this);
 		}
-		this.buffer.append(";");//$NON-NLS-1$
+		this.buffer.append(";\n");//$NON-NLS-1$
 		return false;
 	}
 	
@@ -167,12 +176,15 @@
 	 * @see ASTVisitor#visit(AnonymousClassDeclaration)
 	 */
 	public boolean visit(AnonymousClassDeclaration node) {
-		this.buffer.append("{");//$NON-NLS-1$
+		this.buffer.append("{\n");//$NON-NLS-1$
+		this.indent++;
 		for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
 			BodyDeclaration b = (BodyDeclaration) it.next();
 			b.accept(this);
 		}
-		this.buffer.append("}");//$NON-NLS-1$
+		this.indent--;
+		printIndent();
+		this.buffer.append("}\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -242,13 +254,14 @@
 	 * @see ASTVisitor#visit(AssertStatement)
 	 */
 	public boolean visit(AssertStatement node) {
+		printIndent();
 		this.buffer.append("assert ");//$NON-NLS-1$
 		node.getExpression().accept(this);
 		if (node.getMessage() != null) {
 			this.buffer.append(" : ");//$NON-NLS-1$
 			node.getMessage().accept(this);
 		}
-		this.buffer.append(";");//$NON-NLS-1$
+		this.buffer.append(";\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -266,12 +279,15 @@
 	 * @see ASTVisitor#visit(Block)
 	 */
 	public boolean visit(Block node) {
-		this.buffer.append("{");//$NON-NLS-1$
+		this.buffer.append("{\n");//$NON-NLS-1$
+		this.indent++;
 		for (Iterator it = node.statements().iterator(); it.hasNext(); ) {
 			Statement s = (Statement) it.next();
 			s.accept(this);
 		}
-		this.buffer.append("}");//$NON-NLS-1$
+		this.indent--;
+		printIndent();
+		this.buffer.append("}\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -280,6 +296,7 @@
 	 * @since 3.0
 	 */
 	public boolean visit(BlockComment node) {
+		printIndent();
 		this.buffer.append("/* */");//$NON-NLS-1$
 		return false;
 	}
@@ -300,12 +317,13 @@
 	 * @see ASTVisitor#visit(BreakStatement)
 	 */
 	public boolean visit(BreakStatement node) {
+		printIndent();
 		this.buffer.append("break");//$NON-NLS-1$
 		if (node.getLabel() != null) {
 			this.buffer.append(" ");//$NON-NLS-1$
 			node.getLabel().accept(this);
 		}
-		this.buffer.append(";");//$NON-NLS-1$
+		this.buffer.append(";\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -403,9 +421,9 @@
 	 */
 	public boolean visit(ConditionalExpression node) {
 		node.getExpression().accept(this);
-		this.buffer.append("?");//$NON-NLS-1$
+		this.buffer.append(" ? ");//$NON-NLS-1$
 		node.getThenExpression().accept(this);
-		this.buffer.append(":");//$NON-NLS-1$
+		this.buffer.append(" : ");//$NON-NLS-1$
 		node.getElseExpression().accept(this);
 		return false;
 	}
@@ -414,6 +432,7 @@
 	 * @see ASTVisitor#visit(ConstructorInvocation)
 	 */
 	public boolean visit(ConstructorInvocation node) {
+		printIndent();
 		if (node.getAST().apiLevel() >= AST.JLS3) {
 			if (!node.typeArguments().isEmpty()) {
 				this.buffer.append("<");//$NON-NLS-1$
@@ -435,7 +454,7 @@
 				this.buffer.append(",");//$NON-NLS-1$
 			}
 		}
-		this.buffer.append(");");//$NON-NLS-1$
+		this.buffer.append(");\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -443,12 +462,13 @@
 	 * @see ASTVisitor#visit(ContinueStatement)
 	 */
 	public boolean visit(ContinueStatement node) {
+		printIndent();
 		this.buffer.append("continue");//$NON-NLS-1$
 		if (node.getLabel() != null) {
 			this.buffer.append(" ");//$NON-NLS-1$
 			node.getLabel().accept(this);
 		}
-		this.buffer.append(";");//$NON-NLS-1$
+		this.buffer.append(";\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -456,11 +476,12 @@
 	 * @see ASTVisitor#visit(DoStatement)
 	 */
 	public boolean visit(DoStatement node) {
+		printIndent();
 		this.buffer.append("do ");//$NON-NLS-1$
 		node.getBody().accept(this);
 		this.buffer.append(" while (");//$NON-NLS-1$
 		node.getExpression().accept(this);
-		this.buffer.append(");");//$NON-NLS-1$
+		this.buffer.append(");\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -468,7 +489,8 @@
 	 * @see ASTVisitor#visit(EmptyStatement)
 	 */
 	public boolean visit(EmptyStatement node) {
-		this.buffer.append(";");//$NON-NLS-1$
+		printIndent();
+		this.buffer.append(";\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -477,6 +499,7 @@
 	 * @since 3.0
 	 */
 	public boolean visit(EnhancedForStatement node) {
+		printIndent();
 		this.buffer.append("for (");//$NON-NLS-1$
 		node.getParameter().accept(this);
 		this.buffer.append(" : ");//$NON-NLS-1$
@@ -494,6 +517,7 @@
 		if (node.getJavadoc() != null) {
 			node.getJavadoc().accept(this);
 		}
+		printIndent();
 		printModifiers(node.modifiers());
 		node.getName().accept(this);
 		if (!node.arguments().isEmpty()) {
@@ -507,13 +531,8 @@
 			}
 			this.buffer.append(")");//$NON-NLS-1$
 		}
-		if (!node.bodyDeclarations().isEmpty()) {
-			this.buffer.append("{");//$NON-NLS-1$
-			for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
-				BodyDeclaration d = (BodyDeclaration) it.next();
-				d.accept(this);
-			}
-			this.buffer.append("}");//$NON-NLS-1$
+		if (node.getAnonymousClassDeclaration() != null) {
+			node.getAnonymousClassDeclaration().accept(this);
 		}
 		return false;
 	}
@@ -526,6 +545,7 @@
 		if (node.getJavadoc() != null) {
 			node.getJavadoc().accept(this);
 		}
+		printIndent();
 		printModifiers(node.modifiers());
 		this.buffer.append("enum ");//$NON-NLS-1$
 		node.getName().accept(this);
@@ -542,23 +562,24 @@
 			this.buffer.append(" ");//$NON-NLS-1$
 		}
 		this.buffer.append("{");//$NON-NLS-1$
-		BodyDeclaration prev = null;
-		for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
-			BodyDeclaration d = (BodyDeclaration) it.next();
-			if (prev instanceof EnumConstantDeclaration) {
-				// enum constant declarations do not include punctuation
-				if (d instanceof EnumConstantDeclaration) {
-					// enum constant declarations are separated by commas
-					this.buffer.append(", ");//$NON-NLS-1$
-				} else {
-					// semicolon separates last enum constant declaration from 
-					// first class body declarations
-					this.buffer.append("; ");//$NON-NLS-1$
-				}
-			}
+		for (Iterator it = node.enumConstants().iterator(); it.hasNext(); ) {
+			EnumConstantDeclaration d = (EnumConstantDeclaration) it.next();
 			d.accept(this);
+			// enum constant declarations do not include punctuation
+			if (it.hasNext()) {
+				// enum constant declarations are separated by commas
+				this.buffer.append(", ");//$NON-NLS-1$
+			}
 		}
-		this.buffer.append("}");//$NON-NLS-1$
+		if (!node.bodyDeclarations().isEmpty()) {
+			this.buffer.append("; ");//$NON-NLS-1$
+			for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
+				BodyDeclaration d = (BodyDeclaration) it.next();
+				d.accept(this);
+				// other body declarations include trailing punctuation
+			}
+		}
+		this.buffer.append("}\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -566,8 +587,9 @@
 	 * @see ASTVisitor#visit(ExpressionStatement)
 	 */
 	public boolean visit(ExpressionStatement node) {
+		printIndent();
 		node.getExpression().accept(this);
-		this.buffer.append(";");//$NON-NLS-1$
+		this.buffer.append(";\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -588,6 +610,7 @@
 		if (node.getJavadoc() != null) {
 			node.getJavadoc().accept(this);
 		}
+		printIndent();
 		if (node.getAST().apiLevel() == AST.JLS2) {
 			printModifiers(node.getModifiers());
 		}
@@ -603,7 +626,7 @@
 				this.buffer.append(", ");//$NON-NLS-1$
 			}
 		}
-		this.buffer.append(";");//$NON-NLS-1$
+		this.buffer.append(";\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -611,6 +634,7 @@
 	 * @see ASTVisitor#visit(ForStatement)
 	 */
 	public boolean visit(ForStatement node) {
+		printIndent();
 		this.buffer.append("for (");//$NON-NLS-1$
 		for (Iterator it = node.initializers().iterator(); it.hasNext(); ) {
 			Expression e = (Expression) it.next();
@@ -634,6 +658,7 @@
 	 * @see ASTVisitor#visit(IfStatement)
 	 */
 	public boolean visit(IfStatement node) {
+		printIndent();
 		this.buffer.append("if (");//$NON-NLS-1$
 		node.getExpression().accept(this);
 		this.buffer.append(") ");//$NON-NLS-1$
@@ -649,6 +674,7 @@
 	 * @see ASTVisitor#visit(ImportDeclaration)
 	 */
 	public boolean visit(ImportDeclaration node) {
+		printIndent();
 		this.buffer.append("import ");//$NON-NLS-1$
 		if (node.getAST().apiLevel() >= AST.JLS3) {
 			if (node.isStatic()) {
@@ -659,7 +685,7 @@
 		if (node.isOnDemand()) {
 			this.buffer.append(".*");//$NON-NLS-1$
 		}
-		this.buffer.append(";");//$NON-NLS-1$
+		this.buffer.append(";\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -711,12 +737,13 @@
 	 * @see ASTVisitor#visit(Javadoc)
 	 */
 	public boolean visit(Javadoc node) {
+		printIndent();
 		this.buffer.append("/** ");//$NON-NLS-1$
 		for (Iterator it = node.tags().iterator(); it.hasNext(); ) {
 			ASTNode e = (ASTNode) it.next();
 			e.accept(this);
 		}
-		this.buffer.append("\n */");//$NON-NLS-1$
+		this.buffer.append("\n */\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -724,6 +751,7 @@
 	 * @see ASTVisitor#visit(LabeledStatement)
 	 */
 	public boolean visit(LabeledStatement node) {
+		printIndent();
 		node.getLabel().accept(this);
 		this.buffer.append(": ");//$NON-NLS-1$
 		node.getBody().accept(this);
@@ -815,6 +843,7 @@
 		if (node.getJavadoc() != null) {
 			node.getJavadoc().accept(this);
 		}
+		printIndent();
 		if (node.getAST().apiLevel() == AST.JLS2) {
 			printModifiers(node.getModifiers());
 		}
@@ -870,7 +899,7 @@
 			this.buffer.append(" ");//$NON-NLS-1$
 		}
 		if (node.getBody() == null) {
-			this.buffer.append(";");//$NON-NLS-1$
+			this.buffer.append(";\n");//$NON-NLS-1$
 		} else {
 			node.getBody().accept(this);
 		}
@@ -969,9 +998,10 @@
 				this.buffer.append(" ");//$NON-NLS-1$
 			}
 		}
+		printIndent();
 		this.buffer.append("package ");//$NON-NLS-1$
 		node.getName().accept(this);
-		this.buffer.append(";");//$NON-NLS-1$
+		this.buffer.append(";\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -1054,12 +1084,13 @@
 	 * @see ASTVisitor#visit(ReturnStatement)
 	 */
 	public boolean visit(ReturnStatement node) {
+		printIndent();
 		this.buffer.append("return");//$NON-NLS-1$
 		if (node.getExpression() != null) {
 			this.buffer.append(" ");//$NON-NLS-1$
 			node.getExpression().accept(this);
 		}
-		this.buffer.append(";");//$NON-NLS-1$
+		this.buffer.append(";\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -1095,6 +1126,7 @@
 	 * @see ASTVisitor#visit(SingleVariableDeclaration)
 	 */
 	public boolean visit(SingleVariableDeclaration node) {
+		printIndent();
 		if (node.getAST().apiLevel() == AST.JLS2) {
 			printModifiers(node.getModifiers());
 		}
@@ -1131,6 +1163,7 @@
 	 * @see ASTVisitor#visit(SuperConstructorInvocation)
 	 */
 	public boolean visit(SuperConstructorInvocation node) {
+		printIndent();
 		if (node.getExpression() != null) {
 			node.getExpression().accept(this);
 			this.buffer.append(".");//$NON-NLS-1$
@@ -1156,7 +1189,7 @@
 				this.buffer.append(",");//$NON-NLS-1$
 			}
 		}
-		this.buffer.append(");");//$NON-NLS-1$
+		this.buffer.append(");\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -1213,12 +1246,13 @@
 	 */
 	public boolean visit(SwitchCase node) {
 		if (node.isDefault()) {
-			this.buffer.append("default :");//$NON-NLS-1$
+			this.buffer.append("default :\n");//$NON-NLS-1$
 		} else {
 			this.buffer.append("case ");//$NON-NLS-1$
 			node.getExpression().accept(this);
-			this.buffer.append(":");//$NON-NLS-1$
+			this.buffer.append(":\n");//$NON-NLS-1$
 		}
+		this.indent++; //decremented in visit(SwitchStatement)
 		return false;
 	}
 
@@ -1229,12 +1263,16 @@
 		this.buffer.append("switch (");//$NON-NLS-1$
 		node.getExpression().accept(this);
 		this.buffer.append(") ");//$NON-NLS-1$
-		this.buffer.append("{");//$NON-NLS-1$
+		this.buffer.append("{\n");//$NON-NLS-1$
+		this.indent++;
 		for (Iterator it = node.statements().iterator(); it.hasNext(); ) {
 			Statement s = (Statement) it.next();
 			s.accept(this);
+			this.indent--; // incremented in visit(SwitchCase)
 		}
-		this.buffer.append("}");//$NON-NLS-1$
+		this.indent--;
+		printIndent();
+		this.buffer.append("}\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -1314,9 +1352,10 @@
 	 * @see ASTVisitor#visit(ThrowStatement)
 	 */
 	public boolean visit(ThrowStatement node) {
+		printIndent();
 		this.buffer.append("throw ");//$NON-NLS-1$
 		node.getExpression().accept(this);
-		this.buffer.append(";");//$NON-NLS-1$
+		this.buffer.append(";\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -1324,6 +1363,7 @@
 	 * @see ASTVisitor#visit(TryStatement)
 	 */
 	public boolean visit(TryStatement node) {
+		printIndent();
 		this.buffer.append("try ");//$NON-NLS-1$
 		node.getBody().accept(this);
 		this.buffer.append(" ");//$NON-NLS-1$
@@ -1332,7 +1372,7 @@
 			cc.accept(this);
 		}
 		if (node.getFinally() != null) {
-			this.buffer.append("finally ");//$NON-NLS-1$
+			this.buffer.append(" finally ");//$NON-NLS-1$
 			node.getFinally().accept(this);
 		}
 		return false;
@@ -1403,7 +1443,8 @@
 				this.buffer.append(" ");//$NON-NLS-1$
 			}
 		}
-		this.buffer.append("{");//$NON-NLS-1$
+		this.buffer.append("{\n");//$NON-NLS-1$
+		this.indent++;
 		BodyDeclaration prev = null;
 		for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
 			BodyDeclaration d = (BodyDeclaration) it.next();
@@ -1420,7 +1461,9 @@
 			}
 			d.accept(this);
 		}
-		this.buffer.append("}");//$NON-NLS-1$
+		this.indent--;
+		printIndent();
+		this.buffer.append("}\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -1506,6 +1549,7 @@
 	 * @see ASTVisitor#visit(VariableDeclarationStatement)
 	 */
 	public boolean visit(VariableDeclarationStatement node) {
+		printIndent();
 		if (node.getAST().apiLevel() == AST.JLS2) {
 			printModifiers(node.getModifiers());
 		}
@@ -1521,7 +1565,7 @@
 				this.buffer.append(", ");//$NON-NLS-1$
 			}
 		}
-		this.buffer.append(";");//$NON-NLS-1$
+		this.buffer.append(";\n");//$NON-NLS-1$
 		return false;
 	}
 
@@ -1547,6 +1591,7 @@
 	 * @see ASTVisitor#visit(WhileStatement)
 	 */
 	public boolean visit(WhileStatement node) {
+		printIndent();
 		this.buffer.append("while (");//$NON-NLS-1$
 		node.getExpression().accept(this);
 		this.buffer.append(") ");//$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NormalAnnotation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NormalAnnotation.java
index 98b40e1..c724c4a 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NormalAnnotation.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NormalAnnotation.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -52,10 +53,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(NormalAnnotation.class);
-		addProperty(TYPE_NAME_PROPERTY);
-		addProperty(VALUES_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(NormalAnnotation.class, propertyList);
+		addProperty(TYPE_NAME_PROPERTY, propertyList);
+		addProperty(VALUES_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 	
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NullLiteral.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NullLiteral.java
index ae6ac0e..e2e7e0b 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NullLiteral.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NullLiteral.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -28,8 +29,9 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(NullLiteral.class);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(1);
+		createPropertyList(NullLiteral.class, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NumberLiteral.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NumberLiteral.java
index c55f158..b2059ca 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NumberLiteral.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NumberLiteral.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.eclipse.jdt.core.compiler.InvalidInputException;
@@ -39,9 +40,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(NumberLiteral.class);
-		addProperty(TOKEN_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(2);
+		createPropertyList(NumberLiteral.class, propertyList);
+		addProperty(TOKEN_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java
index 8243c94..2e0c67f 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java
@@ -11,7 +11,11 @@
 
 package org.eclipse.jdt.core.dom;
 
+import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.core.NameLookup;
+import org.eclipse.jdt.internal.core.SearchableEnvironment;
 
 /**
  * Internal implementation of package bindings.
@@ -19,7 +23,7 @@
 class PackageBinding implements IPackageBinding {
 
 	private static final String[] NO_NAME_COMPONENTS = new String[0];
-	private static final String UNNAMED = "UNNAMED";//$NON-NLS-1$
+	private static final String UNNAMED = ""; //$NON-NLS-1$
 	private static final char PACKAGE_NAME_SEPARATOR = '.';
 	
 	private org.eclipse.jdt.internal.compiler.lookup.PackageBinding binding;
@@ -86,10 +90,43 @@
 	}
 
 	/*
+	 * @see IBinding#getJavaElement()
+	 */
+	public IJavaElement getJavaElement() {
+		INameEnvironment nameEnvironment = this.binding.environment.nameEnvironment; // a package binding always has a LooupEnvironment set
+		if (!(nameEnvironment instanceof SearchableEnvironment)) return null;
+		NameLookup nameLookup = ((SearchableEnvironment) nameEnvironment).nameLookup;
+		if (nameLookup == null) return null;
+		IJavaElement[] pkgs = nameLookup.findPackageFragments(getName(), false/*exact match*/);
+		if (pkgs == null) return null;
+		return pkgs[0];
+	}
+	
+	/*
 	 * @see IBinding#getKey()
 	 */
 	public String getKey() {
-		return getName();
+		return new String(this.binding.computeUniqueKey());
+	}
+	
+	/*
+	 * @see IBinding#isEqualTo(Binding)
+	 * @since 3.1
+	 */
+	public boolean isEqualTo(IBinding other) {
+		if (other == this) {
+			// identical binding - equal (key or no key)
+			return true;
+		}
+		if (other == null) {
+			// other binding missing
+			return false;
+		}
+		if (!(other instanceof PackageBinding)) {
+			return false;
+		}
+		org.eclipse.jdt.internal.compiler.lookup.PackageBinding packageBinding2 = ((PackageBinding) other).binding;
+		return CharOperation.equals(this.binding.compoundName, packageBinding2.compoundName);
 	}
 	
 	private void computeNameAndComponents() {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageDeclaration.java
index 48e95e4..a816170 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageDeclaration.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -69,15 +70,17 @@
 	private static final List PROPERTY_DESCRIPTORS_3_0;
 	
 	static {
-		createPropertyList(PackageDeclaration.class);
-		addProperty(NAME_PROPERTY);
-		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList();
+		List propertyList = new ArrayList(2);
+		createPropertyList(PackageDeclaration.class, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
 		
-		createPropertyList(PackageDeclaration.class);
-		addProperty(JAVADOC_PROPERTY);
-		addProperty(ANNOTATIONS_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList();
+		propertyList = new ArrayList(4);
+		createPropertyList(PackageDeclaration.class, propertyList);
+		addProperty(JAVADOC_PROPERTY, propertyList);
+		addProperty(ANNOTATIONS_PROPERTY, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParameterizedType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParameterizedType.java
index 9f582f5..c5f8db7 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParameterizedType.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParameterizedType.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -56,10 +57,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(ParameterizedType.class);
-		addProperty(TYPE_PROPERTY);
-		addProperty(TYPE_ARGUMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(ParameterizedType.class, propertyList);
+		addProperty(TYPE_PROPERTY, propertyList);
+		addProperty(TYPE_ARGUMENTS_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParenthesizedExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParenthesizedExpression.java
index f8a9435..da94e9d 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParenthesizedExpression.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParenthesizedExpression.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -40,9 +41,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(ParenthesizedExpression.class);
-		addProperty(EXPRESSION_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(2);
+		createPropertyList(ParenthesizedExpression.class, propertyList);
+		addProperty(EXPRESSION_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PostfixExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PostfixExpression.java
index 18e312a..71b0fad 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PostfixExpression.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PostfixExpression.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -124,10 +125,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(PostfixExpression.class);
-		addProperty(OPERAND_PROPERTY);
-		addProperty(OPERATOR_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(PostfixExpression.class, propertyList);
+		addProperty(OPERAND_PROPERTY, propertyList);
+		addProperty(OPERATOR_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrefixExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrefixExpression.java
index f483663..6e6f9df 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrefixExpression.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrefixExpression.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -140,10 +141,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(PrefixExpression.class);
-		addProperty(OPERATOR_PROPERTY);
-		addProperty(OPERAND_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(PrefixExpression.class, propertyList);
+		addProperty(OPERATOR_PROPERTY, propertyList);
+		addProperty(OPERAND_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrimitiveType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrimitiveType.java
index 896d719..0756efe 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrimitiveType.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrimitiveType.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -167,9 +168,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(PrimitiveType.class);
-		addProperty(PRIMITIVE_TYPE_CODE_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(2);
+		createPropertyList(PrimitiveType.class, propertyList);
+		addProperty(PRIMITIVE_TYPE_CODE_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedName.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedName.java
index c00899e..0cca1f5 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedName.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedName.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 
@@ -54,10 +55,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(QualifiedName.class);
-		addProperty(QUALIFIER_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(QualifiedName.class, propertyList);
+		addProperty(QUALIFIER_PROPERTY, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedType.java
index b500edf..70a7280 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedType.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedType.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -66,10 +67,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(QualifiedType.class);
-		addProperty(QUALIFIER_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(QualifiedType.class, propertyList);
+		addProperty(QUALIFIER_PROPERTY, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ReturnStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ReturnStatement.java
index 1815814..cd22e5a 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ReturnStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ReturnStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -40,9 +41,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(ReturnStatement.class);
-		addProperty(EXPRESSION_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(2);
+		createPropertyList(ReturnStatement.class, propertyList);
+		addProperty(EXPRESSION_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleName.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleName.java
index f80bce1..aa1e16f 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleName.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleName.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.eclipse.jdt.core.compiler.InvalidInputException;
@@ -46,9 +47,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(SimpleName.class);
-		addProperty(IDENTIFIER_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(2);
+		createPropertyList(SimpleName.class, propertyList);
+		addProperty(IDENTIFIER_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 	
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java
index 445f503..6c39c23 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -39,9 +40,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(SimpleType.class);
-		addProperty(NAME_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(2);
+		createPropertyList(SimpleType.class, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleMemberAnnotation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleMemberAnnotation.java
index 2e9d9ae..f1ff4f2 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleMemberAnnotation.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleMemberAnnotation.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -56,10 +57,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(SingleMemberAnnotation.class);
-		addProperty(TYPE_NAME_PROPERTY);
-		addProperty(VALUE_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(SingleMemberAnnotation.class, propertyList);
+		addProperty(TYPE_NAME_PROPERTY, propertyList);
+		addProperty(VALUE_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 	
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java
index 7f2c782..8e44c29 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
@@ -103,22 +104,24 @@
 	private static final List PROPERTY_DESCRIPTORS_3_0;
 	
 	static {
-		createPropertyList(SingleVariableDeclaration.class);
-		addProperty(MODIFIERS_PROPERTY);
-		addProperty(TYPE_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(EXTRA_DIMENSIONS_PROPERTY);
-		addProperty(INITIALIZER_PROPERTY);
-		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList();
+		List propertyList = new ArrayList(6);
+		createPropertyList(SingleVariableDeclaration.class, propertyList);
+		addProperty(MODIFIERS_PROPERTY, propertyList);
+		addProperty(TYPE_PROPERTY, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+		addProperty(INITIALIZER_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
 		
-		createPropertyList(SingleVariableDeclaration.class);
-		addProperty(MODIFIERS2_PROPERTY);
-		addProperty(TYPE_PROPERTY);
-		addProperty(VARARGS_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(EXTRA_DIMENSIONS_PROPERTY);
-		addProperty(INITIALIZER_PROPERTY);
-		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList();
+		propertyList = new ArrayList(7);
+		createPropertyList(SingleVariableDeclaration.class, propertyList);
+		addProperty(MODIFIERS2_PROPERTY, propertyList);
+		addProperty(TYPE_PROPERTY, propertyList);
+		addProperty(VARARGS_PROPERTY, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+		addProperty(INITIALIZER_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
 	}
 
 	/**
@@ -207,6 +210,30 @@
 	}
 
 	/* (omit javadoc for this method)
+	 * Method declared on VariableDeclaration.
+	 * @since 3.1
+	 */
+	final SimplePropertyDescriptor internalExtraDimensionsProperty() {
+		return EXTRA_DIMENSIONS_PROPERTY;
+	}
+
+	/* (omit javadoc for this method)
+	 * Method declared on VariableDeclaration.
+	 * @since 3.1
+	 */
+	final ChildPropertyDescriptor internalInitializerProperty() {
+		return INITIALIZER_PROPERTY;
+	}
+
+	/* (omit javadoc for this method)
+	 * Method declared on VariableDeclaration.
+	 * @since 3.1
+	 */
+	final ChildPropertyDescriptor internalNameProperty() {
+		return NAME_PROPERTY;
+	}
+
+	/* (omit javadoc for this method)
 	 * Method declared on ASTNode.
 	 */
 	final List internalStructuralPropertiesForType(int apiLevel) {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StringLiteral.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StringLiteral.java
index a5dcca1..c0e5307 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StringLiteral.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StringLiteral.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.eclipse.jdt.core.compiler.InvalidInputException;
@@ -39,9 +40,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(StringLiteral.class);
-		addProperty(ESCAPED_VALUE_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(2);
+		createPropertyList(StringLiteral.class, propertyList);
+		addProperty(ESCAPED_VALUE_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperConstructorInvocation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperConstructorInvocation.java
index 8cb79cd..70884ad 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperConstructorInvocation.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperConstructorInvocation.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -70,16 +71,18 @@
 	private static final List PROPERTY_DESCRIPTORS_3_0;
 	
 	static {
-		createPropertyList(SuperConstructorInvocation.class);
-		addProperty(EXPRESSION_PROPERTY);
-		addProperty(ARGUMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(SuperConstructorInvocation.class, propertyList);
+		addProperty(EXPRESSION_PROPERTY, propertyList);
+		addProperty(ARGUMENTS_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
 		
-		createPropertyList(SuperConstructorInvocation.class);
-		addProperty(EXPRESSION_PROPERTY);
-		addProperty(TYPE_ARGUMENTS_PROPERTY);
-		addProperty(ARGUMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList();
+		propertyList = new ArrayList(4);
+		createPropertyList(SuperConstructorInvocation.class, propertyList);
+		addProperty(EXPRESSION_PROPERTY, propertyList);
+		addProperty(TYPE_ARGUMENTS_PROPERTY, propertyList);
+		addProperty(ARGUMENTS_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperFieldAccess.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperFieldAccess.java
index 666c12e..d79a8d2 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperFieldAccess.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperFieldAccess.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -53,10 +54,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(SuperFieldAccess.class);
-		addProperty(QUALIFIER_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(SuperFieldAccess.class, propertyList);
+		addProperty(QUALIFIER_PROPERTY, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperMethodInvocation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperMethodInvocation.java
index b8ad70e..e6bd344 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperMethodInvocation.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperMethodInvocation.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -78,18 +79,20 @@
 	private static final List PROPERTY_DESCRIPTORS_3_0;
 	
 	static {
-		createPropertyList(SuperMethodInvocation.class);
-		addProperty(QUALIFIER_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(ARGUMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList();
+		List propertyList = new ArrayList(4);
+		createPropertyList(SuperMethodInvocation.class, propertyList);
+		addProperty(QUALIFIER_PROPERTY, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		addProperty(ARGUMENTS_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
 		
-		createPropertyList(SuperMethodInvocation.class);
-		addProperty(QUALIFIER_PROPERTY);
-		addProperty(TYPE_ARGUMENTS_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(ARGUMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList();
+		propertyList = new ArrayList(5);
+		createPropertyList(SuperMethodInvocation.class, propertyList);
+		addProperty(QUALIFIER_PROPERTY, propertyList);
+		addProperty(TYPE_ARGUMENTS_PROPERTY, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		addProperty(ARGUMENTS_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SwitchCase.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SwitchCase.java
index d976f20..f893c77 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SwitchCase.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SwitchCase.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -43,9 +44,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(SwitchCase.class);
-		addProperty(EXPRESSION_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(2);
+		createPropertyList(SwitchCase.class, propertyList);
+		addProperty(EXPRESSION_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SwitchStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SwitchStatement.java
index f9f6fa5..9c93441 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SwitchStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SwitchStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -54,10 +55,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(SwitchStatement.class);
-		addProperty(EXPRESSION_PROPERTY);
-		addProperty(STATEMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(SwitchStatement.class, propertyList);
+		addProperty(EXPRESSION_PROPERTY, propertyList);
+		addProperty(STATEMENTS_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SynchronizedStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SynchronizedStatement.java
index 0f75787..1c0860f 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SynchronizedStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SynchronizedStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -47,10 +48,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(SynchronizedStatement.class);
-		addProperty(EXPRESSION_PROPERTY);
-		addProperty(BODY_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(SynchronizedStatement.class, propertyList);
+		addProperty(EXPRESSION_PROPERTY, propertyList);
+		addProperty(BODY_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagElement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagElement.java
index b5c6d54..728057c 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagElement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagElement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -57,10 +58,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(TagElement.class);
-		addProperty(TAG_NAME_PROPERTY);
-		addProperty(FRAGMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(TagElement.class, propertyList);
+		addProperty(TAG_NAME_PROPERTY, propertyList);
+		addProperty(FRAGMENTS_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 	
 	/**
@@ -83,6 +85,15 @@
 	public static final String TAG_AUTHOR = "@author"; //$NON-NLS-1$
 
 	/**
+	 * Standard inline doc tag name (value {@value}).
+	 * <p>
+	 * Note that this tag first appeared in J2SE 5.
+	 * </p>
+	 * @since 3.1
+	 */
+	public static final String TAG_CODE = "@code"; //$NON-NLS-1$
+
+	/**
 	 * Standard doc tag name (value {@value}).
 	 */
 	public static final String TAG_DEPRECATED = "@deprecated"; //$NON-NLS-1$
@@ -113,6 +124,15 @@
 	public static final String TAG_LINKPLAIN = "@linkplain"; //$NON-NLS-1$
 
 	/**
+	 * Standard inline doc tag name (value {@value}).
+	 * <p>
+	 * Note that this tag first appeared in J2SE 5.
+	 * </p>
+	 * @since 3.1
+	 */
+	public static final String TAG_LITERAL = "@literal"; //$NON-NLS-1$
+
+	/**
 	 * Standard doc tag name (value {@value}).
 	 */
 	public static final String TAG_PARAM = "@param"; //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TextElement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TextElement.java
index 4573d89..7775842 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TextElement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TextElement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -42,9 +43,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(TextElement.class);
-		addProperty(TEXT_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(2);
+		createPropertyList(TextElement.class, propertyList);
+		addProperty(TEXT_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 	
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ThisExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ThisExpression.java
index 505cc87..e6d7085 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ThisExpression.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ThisExpression.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -45,9 +46,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(ThisExpression.class);
-		addProperty(QUALIFIER_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(2);
+		createPropertyList(ThisExpression.class, propertyList);
+		addProperty(QUALIFIER_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ThrowStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ThrowStatement.java
index b9c101c..8c9135d 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ThrowStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ThrowStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -40,9 +41,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(ThrowStatement.class);
-		addProperty(EXPRESSION_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(2);
+		createPropertyList(ThrowStatement.class, propertyList);
+		addProperty(EXPRESSION_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TryStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TryStatement.java
index 1a8807a..aab8534 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TryStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TryStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -56,11 +57,12 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(TryStatement.class);
-		addProperty(BODY_PROPERTY);
-		addProperty(CATCH_CLAUSES_PROPERTY);
-		addProperty(FINALLY_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(4);
+		createPropertyList(TryStatement.class, propertyList);
+		addProperty(BODY_PROPERTY, propertyList);
+		addProperty(CATCH_CLAUSES_PROPERTY, propertyList);
+		addProperty(FINALLY_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
index 0bd60a9..b33ff84 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
@@ -11,152 +11,211 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.io.File;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IClassFile;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IMethod;
+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.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
-import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+import org.eclipse.jdt.internal.compiler.env.IDependent;
 import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.BaseTypes;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
+import org.eclipse.jdt.internal.compiler.util.Util;
+import org.eclipse.jdt.internal.core.ClassFile;
 
 /**
  * Internal implementation of type bindings.
  */
 class TypeBinding implements ITypeBinding {
+	private static final IMethodBinding[] NO_METHOD_BINDINGS = new IMethodBinding[0];
 
 	private static final String NO_NAME = ""; //$NON-NLS-1$	
 	private static final ITypeBinding[] NO_TYPE_BINDINGS = new ITypeBinding[0];
 	private static final IVariableBinding[] NO_VARIABLE_BINDINGS = new IVariableBinding[0];
-	private static final IMethodBinding[] NO_METHOD_BINDINGS = new IMethodBinding[0];
+
+	private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+		Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.STRICTFP;
 	
 	private org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding;
-	private BindingResolver resolver;
 	private String key;
+	private BindingResolver resolver;
 	
 	public TypeBinding(BindingResolver resolver, org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding) {
 		this.binding = binding;
 		this.resolver = resolver;
 	}
+
+	/*
+	 * @see ITypeBinding#getBinaryName()
+	 * @since 3.0
+	 */
+	public String getBinaryName() {
+		char[] constantPoolName = this.binding.constantPoolName();
+		if (constantPoolName == null) return null;
+		char[] dotSeparated = CharOperation.replaceOnCopy(constantPoolName, '/', '.');
+		return new String(dotSeparated);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getBound()
+	 */
+	public ITypeBinding getBound() {
+		if (this.binding.isWildcard()) {
+			WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
+			if (wildcardBinding.bound != null) {
+				return this.resolver.getTypeBinding(wildcardBinding.bound);
+			}
+		}
+		return null;
+	}
 	
 	/*
-	 * @see ITypeBinding#isPrimitive()
+	 * Returns the class file for the given file name, or null if not found.
+	 * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
 	 */
-	public boolean isPrimitive() {
-		return !isNullType() && binding.isBaseType();
-	}
-
-	/*
-	 * @see ITypeBinding#isArray()
-	 */
-	public boolean isArray() {
-		return binding.isArrayType();
-	}
-
-	/*
-	 * @see ITypeBinding#getElementType()
-	 */
-	public ITypeBinding getElementType() {
-		if (!this.isArray()) {
+	private IClassFile getClassFile(char[] fileName) {
+		int lastSlash = CharOperation.lastIndexOf('/', fileName);
+		if (lastSlash == -1) 
+			lastSlash = CharOperation.lastIndexOf(File.separatorChar, fileName);
+		if (lastSlash == -1)
 			return null;
+		IPackageFragment pkg = getPackageFragment(fileName, lastSlash);
+		if (pkg == null) return null;
+		char[] simpleName = CharOperation.subarray(fileName, lastSlash+1, fileName.length);
+		return pkg.getClassFile(new String(simpleName));
+	}
+	
+	/*
+	 * Returns the compilation unit for the given file name, or null if not found.
+	 * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
+	 */
+	private ICompilationUnit getCompilationUnit(char[] fileName) {
+		char[] slashSeparatedFileName = CharOperation.replaceOnCopy(fileName, File.separatorChar, '/');
+		int lastSlash = CharOperation.lastIndexOf('/', slashSeparatedFileName);
+		if (lastSlash == -1) return null;
+		IPackageFragment pkg = getPackageFragment(slashSeparatedFileName, lastSlash);
+		if (pkg == null) return null;
+		char[] simpleName = CharOperation.subarray(slashSeparatedFileName, lastSlash+1, slashSeparatedFileName.length);
+		ICompilationUnit cu = pkg.getCompilationUnit(new String(simpleName));
+		if (this.resolver instanceof DefaultBindingResolver) {
+			ICompilationUnit workingCopy = cu.findWorkingCopy(((DefaultBindingResolver) this.resolver).workingCopyOwner);
+			if (workingCopy != null) 
+				return workingCopy;
 		}
-		ArrayBinding arrayBinding = (ArrayBinding) binding;
-		return resolver.getTypeBinding(arrayBinding.leafComponentType);
+		return cu;
 	}
 
 	/*
-	 * @see ITypeBinding#getDimensions()
+	 * @see ITypeBinding#getDeclaredFields()
 	 */
-	public int getDimensions() {
-		if (!this.isArray()) {
-			return 0;
-		}
-		ArrayBinding arrayBinding = (ArrayBinding) binding;
-		return arrayBinding.dimensions;
-	}
-
-	/*
-	 * @see ITypeBinding#isClass()
-	 */
-	public boolean isClass() {
-		return this.binding.isClass();
-	}
-
-	/*
-	 * @see ITypeBinding#isInterface()
-	 */
-	public boolean isInterface() {
-		return this.binding.isInterface();
-	}
-
-	/*
-	 * @see ITypeBinding#isTypeVariable()
-	 */
-	public boolean isTypeVariable() {
-		// TODO (olivier) missing implementation of J2SE 1.5 language feature
-		return false;
-	}
-
-	/*
-	 * @see IBinding#getName()
-	 */
-	public String getName() {
-		if (this.binding.isClass() || this.binding.isInterface()) {
-			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
-			if (referenceBinding.isAnonymousType()) {
-				return NO_NAME;
-			} else if (referenceBinding.isMemberType()) {
-				char[] name = referenceBinding.compoundName[referenceBinding.compoundName.length - 1];
-				return new String(CharOperation.subarray(name, CharOperation.lastIndexOf('$', name) + 1, name.length));
-			} else if (referenceBinding.isLocalType()) {
-				char[] name = referenceBinding.compoundName[referenceBinding.compoundName.length - 1];
-				return new String(CharOperation.subarray(name, CharOperation.lastIndexOf('$', name) + 1, name.length));
-			} else {
-				return new String(referenceBinding.compoundName[referenceBinding.compoundName.length - 1]);
-			}
-		} else if (this.binding.isArrayType()) {
-			ArrayBinding arrayBinding = (ArrayBinding) this.binding;
-			int dimensions = arrayBinding.dimensions;
-			char[] brackets = new char[dimensions * 2];
-			for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
-				brackets[i] = ']';
-				brackets[i - 1] = '[';
-			}
-			StringBuffer buffer = new StringBuffer();
-			org.eclipse.jdt.internal.compiler.lookup.TypeBinding leafComponentTypeBinding = arrayBinding.leafComponentType;
-			if (leafComponentTypeBinding.isClass() || leafComponentTypeBinding.isInterface()) {
-				ReferenceBinding referenceBinding2 = (ReferenceBinding) leafComponentTypeBinding;
-				if (referenceBinding2.isMemberType()) {
-					char[] name = referenceBinding2.compoundName[referenceBinding2.compoundName.length - 1];
-					buffer.append(CharOperation.subarray(name, CharOperation.lastIndexOf('$', name) + 1, name.length));
-				} else if (referenceBinding2.isLocalType()) {
-					char[] name = referenceBinding2.compoundName[referenceBinding2.compoundName.length - 1];
-					buffer.append(CharOperation.subarray(name, CharOperation.lastIndexOf('$', name) + 1, name.length));
-				} else {
-					buffer.append(referenceBinding2.compoundName[referenceBinding2.compoundName.length - 1]);
+	public IVariableBinding[] getDeclaredFields() {
+		try {
+			if (isClass() || isInterface() || isEnum()) {
+				ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+				FieldBinding[] fields = referenceBinding.fields();
+				int length = fields.length;
+				IVariableBinding[] newFields = new IVariableBinding[length];
+				for (int i = 0; i < length; i++) {
+					newFields[i] = this.resolver.getVariableBinding(fields[i]);
 				}
-			} else {
-				buffer.append(leafComponentTypeBinding.readableName());
+				return newFields;
 			}
-			buffer.append(brackets);
-			return buffer.toString();
-		} else {
-			return new String(this.binding.readableName());
+		} catch (RuntimeException e) {
+			/* in case a method cannot be resolvable due to missing jars on the classpath
+			 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+			 */
 		}
+		return NO_VARIABLE_BINDINGS;
 	}
 
 	/*
-	 * @see ITypeBinding#getPackage()
+	 * @see ITypeBinding#getDeclaredMethods()
 	 */
-	public IPackageBinding getPackage() {
-		if (this.binding.isBaseType() || this.binding.isArrayType()) {
-			return null;
-		} else {
-			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
-			return this.resolver.getPackageBinding(referenceBinding.getPackage());
+	public IMethodBinding[] getDeclaredMethods() {
+		try {
+			if (isClass() || isInterface() || isEnum()) {
+				ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+				org.eclipse.jdt.internal.compiler.lookup.MethodBinding[] methods = referenceBinding.methods();
+				int length = methods.length;
+				int removeSyntheticsCounter = 0;
+				IMethodBinding[] newMethods = new IMethodBinding[length];
+				for (int i = 0; i < length; i++) {
+					org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding = methods[i];
+					if (!shouldBeRemoved(methodBinding)) { 
+						newMethods[removeSyntheticsCounter++] = this.resolver.getMethodBinding(methodBinding);
+					}
+				}
+				if (removeSyntheticsCounter != length) {
+					System.arraycopy(newMethods, 0, (newMethods = new IMethodBinding[removeSyntheticsCounter]), 0, removeSyntheticsCounter);
+				}
+				return newMethods;
+			}
+		} catch (RuntimeException e) {
+			/* in case a method cannot be resolvable due to missing jars on the classpath
+			 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+			 */
 		}
+		return NO_METHOD_BINDINGS;
+	}
+
+	/*
+	 * @see ITypeBinding#getDeclaredModifiers()
+	 */
+	public int getDeclaredModifiers() {
+		return getModifiers();
+	}
+
+	/*
+	 * @see ITypeBinding#getDeclaredTypes()
+	 */
+	public ITypeBinding[] getDeclaredTypes() {
+		try {
+			if (isClass() || isInterface() || isEnum()) {
+				ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+				ReferenceBinding[] members = referenceBinding.memberTypes();
+				int length = members.length;
+				ITypeBinding[] newMembers = new ITypeBinding[length];
+				for (int i = 0; i < length; i++) {
+					newMembers[i] = this.resolver.getTypeBinding(members[i]);
+				}
+				return newMembers;
+			}
+		} catch (RuntimeException e) {
+			/* in case a method cannot be resolvable due to missing jars on the classpath
+			 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+			 */
+		}
+		return NO_TYPE_BINDINGS;
 	}
 
 	/*
@@ -182,28 +241,40 @@
 	}
 
 	/*
-	 * @see ITypeBinding#getSuperclass()
+	 * @see ITypeBinding#getDimensions()
 	 */
-	public ITypeBinding getSuperclass() {
-		if (this.binding == null || this.binding.isArrayType() || this.binding.isBaseType() || this.binding.isInterface()) {
+	public int getDimensions() {
+		if (!this.isArray()) {
+			return 0;
+		}
+		ArrayBinding arrayBinding = (ArrayBinding) binding;
+		return arrayBinding.dimensions;
+	}
+
+	/*
+	 * @see ITypeBinding#getElementType()
+	 */
+	public ITypeBinding getElementType() {
+		if (!this.isArray()) {
 			return null;
 		}
-		ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
-		ReferenceBinding superclass = null;
-		try {
-			superclass = referenceBinding.superclass();
-		} catch (RuntimeException e) {
-			/* in case a method cannot be resolvable due to missing jars on the classpath
-			 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
-			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
-			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
-			 */
-			return this.resolver.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
-		}
-		if (superclass == null) {
-			return null;
-		}
-		return this.resolver.getTypeBinding(superclass);		
+		ArrayBinding arrayBinding = (ArrayBinding) binding;
+		return resolver.getTypeBinding(arrayBinding.leafComponentType);
+	}
+
+	/**
+	 * @deprecated Use {@link #getGenericType()} instead.
+	 */
+	// TODO (jeem) - remove before 3.1M5 (bug 80800)
+	public ITypeBinding getErasure() {
+		return getGenericType();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getGenericType()
+	 */
+	public ITypeBinding getGenericType() {
+		return this.resolver.getTypeBinding(this.binding.erasure());
 	}
 
 	/*
@@ -238,197 +309,77 @@
 			return newInterfaces;
 		}
 	}
-
+	
 	/*
-	 * @see IBinding#getModifiers()
+	 * @see IBinding#getJavaElement()
 	 */
-	public int getModifiers() {
-		if (this.binding.isClass()) {
-			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
-			if (referenceBinding.isAnonymousType()) {
-				return referenceBinding.getAccessFlags() & ~Modifier.FINAL;
+	public IJavaElement getJavaElement() {
+		if (this.binding == null || this.binding.isArrayType() || this.binding.isBaseType()) return null;
+		ReferenceBinding referenceBinding;
+		if (this.binding.isParameterizedType() || this.binding.isRawType())
+			referenceBinding = (ReferenceBinding) this.binding.erasure();
+		else
+			referenceBinding = (ReferenceBinding) this.binding;
+		char[] fileName = referenceBinding.getFileName();
+		if (Util.isClassFileName(fileName)) {
+			ClassFile classFile = (ClassFile) getClassFile(fileName);
+			if (classFile == null) return null;
+			return classFile.getType();
+		}
+		if (referenceBinding.isLocalType() || referenceBinding.isAnonymousType()) {
+			// local or anonymous type
+			ICompilationUnit cu = getCompilationUnit(fileName);
+			if (cu == null) return null;
+			if (!(this.resolver instanceof DefaultBindingResolver)) return null;
+			DefaultBindingResolver bindingResolver = (DefaultBindingResolver) this.resolver;
+			ASTNode node = (ASTNode) bindingResolver.bindingsToAstNodes.get(this);
+			// must use getElementAt(...) as there is no back pointer to the defining method (scope is null after resolution has ended)
+			try {
+				return cu.getElementAt(node.getStartPosition());
+			} catch (JavaModelException e) {
+				// does not exist
+				return null;
 			}
-			return referenceBinding.getAccessFlags();
-		} else if (this.binding.isInterface()) {
-			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
-			// clear the AccAbstract and the AccInterface bits
-			return referenceBinding.getAccessFlags() & ~(Modifier.ABSTRACT | 0x200);
+		} else if (referenceBinding.isTypeVariable()) {
+			// type parameter
+			final String typeVariableName = new String(referenceBinding.sourceName());
+			Binding declaringElement = ((TypeVariableBinding) referenceBinding).declaringElement;
+			IBinding declaringTypeBinding = null;
+			if (declaringElement instanceof MethodBinding) {
+				declaringTypeBinding = this.resolver.getMethodBinding((MethodBinding) declaringElement);
+				IMethod declaringMethod = (IMethod) declaringTypeBinding.getJavaElement();
+				return declaringMethod.getTypeParameter(typeVariableName);
+			} else {
+				declaringTypeBinding = this.resolver.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding) declaringElement);
+				IType declaringType = (IType) declaringTypeBinding.getJavaElement();
+				return declaringType.getTypeParameter(typeVariableName);
+			}
 		} else {
-			return 0;
-		}
-	}
-
-	/*
-	 * @see ITypeBinding#getDeclaredModifiers()
-	 */
-	public int getDeclaredModifiers() {
-		return getModifiers();
-	}
-
-	/*
-	 * @see ITypeBinding#isTopLevel()
-	 */
-	public boolean isTopLevel() {
-		if (this.binding.isClass() || this.binding.isInterface()) {
-			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
-			return !referenceBinding.isNestedType();
-		}
-		return false;
-	}
-
-	/*
-	 * @see ITypeBinding#isNested()
-	 */
-	public boolean isNested() {
-		if (this.binding.isClass() || this.binding.isInterface()) {
-			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
-			return referenceBinding.isNestedType();
-		}
-		return false;
-	}
-
-	/*
-	 * @see ITypeBinding#isMember()
-	 */
-	public boolean isMember() {
-		if (this.binding.isClass() || this.binding.isInterface()) {
-			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
-			return referenceBinding.isMemberType();
-		}
-		return false;
-	}
-
-	/*
-	 * @see ITypeBinding#isLocal()
-	 */
-	public boolean isLocal() {
-		if (this.binding.isClass() || this.binding.isInterface()) {
-			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
-			return referenceBinding.isLocalType() && !referenceBinding.isMemberType();
-		}
-		return false;
-	}
-
-	/*
-	 * @see ITypeBinding#isAnonymous()
-	 */
-	public boolean isAnonymous() {
-		if (this.binding.isClass() || this.binding.isInterface()) {
-			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
-			return referenceBinding.isAnonymousType();
-		}
-		return false;
-	}
-
-	/*
-	 * @see ITypeBinding#getDeclaredTypes()
-	 */
-	public ITypeBinding[] getDeclaredTypes() {
-		try {
-			if (this.binding.isClass() || this.binding.isInterface()) {
-				ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
-				ReferenceBinding[] members = referenceBinding.memberTypes();
-				int length = members.length;
-				ITypeBinding[] newMembers = new ITypeBinding[length];
-				for (int i = 0; i < length; i++) {
-					newMembers[i] = this.resolver.getTypeBinding(members[i]);
-				}
-				return newMembers;
+			if (fileName == null) return null; // case of a WilCardBinding that doesn't have a corresponding Java element
+			// member or top level type
+			ITypeBinding declaringTypeBinding = getDeclaringClass();
+			if (declaringTypeBinding == null) {
+				// top level type
+				ICompilationUnit cu = getCompilationUnit(fileName);
+				if (cu == null) return null;
+				return cu.getType(new String(referenceBinding.sourceName()));
+			} else {
+				// member type
+				IType declaringType = (IType) declaringTypeBinding.getJavaElement();
+				if (declaringType == null) return null;
+				return declaringType.getType(new String(referenceBinding.sourceName()));
 			}
-		} catch (RuntimeException e) {
-			/* in case a method cannot be resolvable due to missing jars on the classpath
-			 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
-			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
-			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
-			 */
 		}
-		return NO_TYPE_BINDINGS;
-	}
-	
-	/*
-	 * @see ITypeBinding#getBinaryName()
-	 * @since 3.0
-	 */
-	public String getBinaryName() {
-		char[] constantPoolName = this.binding.constantPoolName();
-		if (constantPoolName == null) return null;
-		int length = constantPoolName.length;
-		char[] dotSeparated = new char[length];
-		System.arraycopy(constantPoolName, 0, dotSeparated, 0, length);
-		CharOperation.replace(dotSeparated, '/', '.');
-		return new String(dotSeparated);
 	}
 
 	/*
-	 * @see ITypeBinding#getDeclaredFields()
+	 * @see IBinding#getKey()
 	 */
-	public IVariableBinding[] getDeclaredFields() {
-		try {
-			if (this.binding.isClass() || this.binding.isInterface()) {
-				ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
-				FieldBinding[] fields = referenceBinding.fields();
-				int length = fields.length;
-				IVariableBinding[] newFields = new IVariableBinding[length];
-				for (int i = 0; i < length; i++) {
-					newFields[i] = this.resolver.getVariableBinding(fields[i]);
-				}
-				return newFields;
-			}
-		} catch (RuntimeException e) {
-			/* in case a method cannot be resolvable due to missing jars on the classpath
-			 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
-			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
-			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
-			 */
+	public String getKey() {
+		if (this.key == null) {
+			this.key = new String(this.binding.computeUniqueKey());
 		}
-		return NO_VARIABLE_BINDINGS;
-	}
-
-	/*
-	 * @see ITypeBinding#getDeclaredMethods()
-	 */
-	public IMethodBinding[] getDeclaredMethods() {
-		try {
-			if (this.binding.isClass() || this.binding.isInterface()) {
-				ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
-				org.eclipse.jdt.internal.compiler.lookup.MethodBinding[] methods = referenceBinding.methods();
-				int length = methods.length;
-				int removeSyntheticsCounter = 0;
-				IMethodBinding[] newMethods = new IMethodBinding[length];
-				for (int i = 0; i < length; i++) {
-					org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding = methods[i];
-					if (!shouldBeRemoved(methodBinding)) { 
-						newMethods[removeSyntheticsCounter++] = this.resolver.getMethodBinding(methodBinding);
-					}
-				}
-				if (removeSyntheticsCounter != length) {
-					System.arraycopy(newMethods, 0, (newMethods = new IMethodBinding[removeSyntheticsCounter]), 0, removeSyntheticsCounter);
-				}
-				return newMethods;
-			}
-		} catch (RuntimeException e) {
-			/* in case a method cannot be resolvable due to missing jars on the classpath
-			 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
-			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
-			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
-			 */
-		}
-		return NO_METHOD_BINDINGS;
-	}
-
-	private boolean shouldBeRemoved(org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding) {
-		return methodBinding.isDefaultAbstract() || methodBinding.isSynthetic() || (methodBinding.isConstructor() && isInterface());
-	}
-	
-	/*
-	 * @see ITypeBinding#isFromSource()
-	 */
-	public boolean isFromSource() {
-		if (this.binding.isClass() || this.binding.isInterface()) {
-			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
-			return !referenceBinding.isBinaryBinding();
-		}
-		return false;
+		return this.key;
 	}
 
 	/*
@@ -439,116 +390,136 @@
 	}
 
 	/*
-	 * @see IBinding#isDeprecated()
+	 * @see IBinding#getModifiers()
 	 */
-	public boolean isDeprecated() {
-		if (this.binding.isClass() || this.binding.isInterface()) {
+	public int getModifiers() {
+		if (isClass()) {
 			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
-			return referenceBinding.isDeprecated();
-		}
-		return false;
-	}
-
-	/**
-	 * @see IBinding#isSynthetic()
-	 */
-	public boolean isSynthetic() {
-		return false;
-	}
-
-	/*
-	 * @see IBinding#getKey()
-	 */
-	public String getKey() {
-		if (this.key == null) {
-			if (isLocal()) {
-				StringBuffer buffer = new StringBuffer();
-				
-				// declaring method or type
-				SourceTypeBinding sourceBinding = (SourceTypeBinding) this.binding; // per construction, a local type can only be defined in source
-				ClassScope scope = sourceBinding.scope;
-				ReferenceContext referenceContext;
-				if (isAnonymous()) {
-					ClassScope classScope = scope.enclosingClassScope();
-					referenceContext = classScope.referenceContext;
-				} else {
-					MethodScope methodScope = scope.enclosingMethodScope();
-					referenceContext = methodScope.referenceContext;
-				}
-				if (referenceContext instanceof AbstractMethodDeclaration) {
-					org.eclipse.jdt.internal.compiler.lookup.MethodBinding internalBinding = ((AbstractMethodDeclaration) referenceContext).binding;
-					IMethodBinding methodBinding = this.resolver.getMethodBinding(internalBinding);
-					if (methodBinding != null) {
-						buffer.append(methodBinding.getKey());
-					}
-				} else if (referenceContext instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
-					org.eclipse.jdt.internal.compiler.lookup.TypeBinding internalBinding = ((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) referenceContext).binding;
-					ITypeBinding typeBinding = this.resolver.getTypeBinding(internalBinding);
-					if (typeBinding != null) {
-						buffer.append(typeBinding.getKey());
-					}
-				}
-	
-				if (isAnonymous()) {
-					buffer.append('$');
-					CompilationUnitScope compilationUnitScope = scope.compilationUnitScope();
-					CompilationUnitDeclaration compilationUnitDeclaration = compilationUnitScope.referenceContext;
-					LocalTypeBinding[] localTypeBindings = compilationUnitDeclaration.localTypes;
-					for (int i = 0, max = compilationUnitDeclaration.localTypeCount; i < max; i++) {
-						if (localTypeBindings[i] == sourceBinding) {
-							buffer.append(i+1);
-							break;
-						}
-					}
-				} else {
-					// type name
-					buffer.append('/');
-					buffer.append(getName());
-				}
-				
-				this.key = buffer.toString();
-			} else {
-				if (this.binding.isClass() || this.binding.isInterface()) {
-					StringBuffer buffer = new StringBuffer();
-					char[] constantPoolName = this.binding.constantPoolName();
-					if (constantPoolName != null) {
-						buffer.append(constantPoolName);
-					} else {
-						char[] qualifiedSourceName = this.binding.qualifiedSourceName();
-						if (qualifiedSourceName != null) {
-							CharOperation.replace(qualifiedSourceName, '.', '$');
-							buffer
-								.append(getPackage().getName())
-								.append('/')
-								.append(qualifiedSourceName);
-						} else {
-							buffer
-								.append(getPackage().getName())
-								.append('/')
-								.append(getName());
-						}
-					}
-					this.key = buffer.toString();
-				} else if (this.binding.isArrayType()) {
-					if (this.getElementType() != null) {
-						this.key = this.getElementType().getKey() + this.getDimensions();
-					} else {
-						this.key = Integer.toString(this.getDimensions());
-					}
-				} else {
-					// this is a primitive type
-					this.key = this.getName();
-				}
+			final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
+			if (referenceBinding.isAnonymousType()) {
+				return accessFlags & ~Modifier.FINAL;
 			}
+			return accessFlags;
+		} else if (isInterface()) {
+			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+			final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
+			// clear the AccAbstract and the AccInterface bits
+			return accessFlags & ~(Modifier.ABSTRACT | 0x200);
+		} else if (isEnum()) {
+			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+			final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
+			// clear the AccEnum bits
+			return accessFlags & ~0x4000;
+		} else {
+			return 0;
 		}
-		return this.key;
 	}
 
-	/**
-	 * @see ITypeBinding#isNullType()
+	public String getName() {
+		if (isWildcardType()) {
+			WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
+			StringBuffer buffer = new StringBuffer();
+			buffer.append(TypeConstants.WILDCARD_NAME);
+			if (wildcardBinding.bound != null) {
+				switch(wildcardBinding.kind) {
+			        case Wildcard.SUPER :
+			        	buffer.append(TypeConstants.WILDCARD_SUPER);
+			            break;
+			        case Wildcard.EXTENDS :
+			        	buffer.append(TypeConstants.WILDCARD_EXTENDS);
+				}
+				buffer.append(getBound().getName());
+			}
+			return String.valueOf(buffer);
+		}
+		if (isParameterizedType()) {
+			ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) this.binding;
+			StringBuffer buffer = new StringBuffer();
+			buffer.append(parameterizedTypeBinding.sourceName());
+			ITypeBinding[] typeArguments = getTypeArguments();
+			final int typeArgumentsLength = typeArguments.length;
+			if (typeArgumentsLength != 0) {
+				buffer.append('<');
+				for (int i = 0, max = typeArguments.length; i < max; i++) {
+					if (i > 0) {
+						buffer.append(',');
+					}
+					buffer.append(typeArguments[i].getName());
+				}
+				buffer.append('>');	
+			}
+			return String.valueOf(buffer);
+		}
+		if (isRawType()) {
+			return getGenericType().getName();
+		}
+		if (isPrimitive() || isNullType()) {
+			BaseTypeBinding baseTypeBinding = (BaseTypeBinding) this.binding;
+			return new String(baseTypeBinding.simpleName);
+		}
+		if (isArray()) {
+			int dimensions = getDimensions();
+			char[] brackets = new char[dimensions * 2];
+			for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
+				brackets[i] = ']';
+				brackets[i - 1] = '[';
+			}
+			StringBuffer buffer = new StringBuffer(getElementType().getName());
+			buffer.append(brackets);
+			return String.valueOf(buffer);
+		}
+		if (isAnonymous()) {
+			return NO_NAME;
+		}
+		if (isTypeVariable()) {
+			TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+			return new String(typeVariableBinding.sourceName);
+		}
+		return new String(this.binding.sourceName());
+	}
+	
+	/*
+	 * @see ITypeBinding#getPackage()
 	 */
-	public boolean isNullType() {
-		return this.binding == BaseTypes.NullBinding;
+	public IPackageBinding getPackage() {
+		if (this.binding.isBaseType() || this.binding.isArrayType()) {
+			return null;
+		} else {
+			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+			return this.resolver.getPackageBinding(referenceBinding.getPackage());
+		}
+	}
+	
+	/*
+	 * Returns the package that includes the given file name, or null if not found.
+	 * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
+	 */
+	private IPackageFragment getPackageFragment(char[] fileName, int lastSlash) {
+		int jarSeparator = CharOperation.indexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, fileName);
+		if (jarSeparator != -1) {
+			String jarMemento = new String(CharOperation.subarray(fileName, 0, jarSeparator));
+			IPackageFragmentRoot root = (IPackageFragmentRoot) JavaCore.create(jarMemento);
+			char[] pkgName = CharOperation.subarray(fileName, jarSeparator+1, lastSlash);
+			CharOperation.replace(pkgName, '/', '.');
+			return root.getPackageFragment(new String(pkgName));
+		} else {
+			Path path = new Path(new String(CharOperation.subarray(fileName, 0, lastSlash)));
+			IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+			IContainer folder = path.segmentCount() == 1 ? workspaceRoot.getProject(path.lastSegment()) : (IContainer) workspaceRoot.getFolder(path);
+			IJavaElement element = JavaCore.create(folder);
+			if (element == null) return null;
+			switch (element.getElementType()) {
+				case IJavaElement.PACKAGE_FRAGMENT:
+					return (IPackageFragment) element;
+				case IJavaElement.PACKAGE_FRAGMENT_ROOT:
+					return ((IPackageFragmentRoot) element).getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
+				case IJavaElement.JAVA_PROJECT:
+					IPackageFragmentRoot root = ((IJavaProject) element).getPackageFragmentRoot(folder);
+					if (root == null) return null;
+					return root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
+			}
+			return null;
+		}
 	}
 
 	/**
@@ -558,67 +529,129 @@
 		if (isAnonymous() || isLocal()) {
 			return NO_NAME;
 		}
-		
 		if (isPrimitive() || isNullType()) {
-			return getName();
+			BaseTypeBinding baseTypeBinding = (BaseTypeBinding) this.binding;
+			return new String(baseTypeBinding.simpleName);
 		}
-		
+		if (isWildcardType()) {
+			WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
+			StringBuffer buffer = new StringBuffer();
+			buffer.append(TypeConstants.WILDCARD_NAME);
+			final ITypeBinding bound = getBound();
+			if (bound != null) {
+				switch(wildcardBinding.kind) {
+			        case Wildcard.SUPER :
+			        	buffer.append(TypeConstants.WILDCARD_SUPER);
+			            break;
+			        case Wildcard.EXTENDS :
+			        	buffer.append(TypeConstants.WILDCARD_EXTENDS);
+				}
+				buffer.append(bound.getQualifiedName());
+			}
+			return String.valueOf(buffer);
+		}
+		if (isRawType()) {
+			return getGenericType().getQualifiedName();
+		}
 		if (isArray()) {
 			ITypeBinding elementType = getElementType();
-			String elementTypeQualifiedName = elementType.getQualifiedName();
-			if (elementTypeQualifiedName.length() != 0) {
-				int dimensions = getDimensions();
-				char[] brackets = new char[dimensions * 2];
-				for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
-					brackets[i] = ']';
-					brackets[i - 1] = '[';
-				}
-				StringBuffer stringBuffer = new StringBuffer(elementTypeQualifiedName);
-				stringBuffer.append(brackets);
-				return stringBuffer.toString();
-			} else {
+			if (elementType.isLocal() || elementType.isAnonymous()) {
 				return NO_NAME;
 			}
+			final int dimensions = getDimensions();
+			char[] brackets = new char[dimensions * 2];
+			for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
+				brackets[i] = ']';
+				brackets[i - 1] = '[';
+			}
+			StringBuffer buffer = new StringBuffer(elementType.getQualifiedName());
+			buffer.append(brackets);
+			return String.valueOf(buffer);
 		}
+		if (isTypeVariable()) {
+			TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+			return new String(typeVariableBinding.sourceName);
+		}
+		if (isMember()) {
+			StringBuffer buffer = new StringBuffer();
+			buffer
+				.append(getDeclaringClass().getQualifiedName())
+				.append('.')
+				.append(getName());
+			return String.valueOf(buffer);
+		}
+		if (isParameterizedType()) {
+			StringBuffer buffer = new StringBuffer();
+			buffer.append(getGenericType().getQualifiedName());
+			ITypeBinding[] typeArguments = getTypeArguments();
+			final int typeArgumentsLength = typeArguments.length;
+			if (typeArgumentsLength != 0) {
+				buffer.append('<');
+				for (int i = 0, max = typeArguments.length; i < max; i++) {
+					if (i > 0) {
+						buffer.append(',');
+					}
+					buffer.append(typeArguments[i].getQualifiedName());
+				}
+				buffer.append('>');
+			}
+			return String.valueOf(buffer);
+		}
+		if (isRawType()) {
+			return getGenericType().getQualifiedName();
+		}
+		PackageBinding packageBinding = this.binding.getPackage();
 		
-		if (isTopLevel() || isMember()) {
-			PackageBinding packageBinding = this.binding.getPackage();
-			
-			if (packageBinding == null || packageBinding.compoundName == CharOperation.NO_CHAR_CHAR) {
-				return new String(this.binding.qualifiedSourceName());
-			} else {
-				StringBuffer stringBuffer = new StringBuffer();
-				stringBuffer
-					.append(this.binding.qualifiedPackageName())
-					.append('.')
-					.append(this.binding.qualifiedSourceName());
-				return stringBuffer.toString();
+		StringBuffer buffer = new StringBuffer();
+		if (packageBinding != null && packageBinding.compoundName != CharOperation.NO_CHAR_CHAR) {
+			buffer.append(CharOperation.concatWith(packageBinding.compoundName, '.')).append('.');
+		}
+		buffer.append(getName());
+
+		return String.valueOf(buffer);
+	}
+
+	/*
+	 * @see ITypeBinding#getSuperclass()
+	 */
+	public ITypeBinding getSuperclass() {
+		if (this.binding == null || this.binding.isArrayType() || this.binding.isBaseType() || this.binding.isInterface()) {
+			return null;
+		}
+		ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+		ReferenceBinding superclass = null;
+		try {
+			superclass = referenceBinding.superclass();
+		} catch (RuntimeException e) {
+			/* in case a method cannot be resolvable due to missing jars on the classpath
+			 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+			 */
+			return this.resolver.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
+		}
+		if (superclass == null) {
+			return null;
+		}
+		return this.resolver.getTypeBinding(superclass);		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeArguments()
+	 */
+	public ITypeBinding[] getTypeArguments() {
+		if (this.binding.isParameterizedType()) {
+			ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) this.binding;
+			final org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] arguments = parameterizedTypeBinding.arguments;
+			if (arguments != null) {
+				int argumentsLength = arguments.length;
+				ITypeBinding[] typeArguments = new ITypeBinding[argumentsLength];
+				for (int i = 0; i < argumentsLength; i++) {
+					typeArguments[i] = this.resolver.getTypeBinding(arguments[i]);
+				}
+				return typeArguments;
 			}
 		}
-		return NO_NAME;
-	}
-	
-	/* (non-Javadoc)
-	 * @see ITypeBinding#isEnum()
-	 */
-	public boolean isEnum() {
-		// TODO (olivier) missing implementation of J2SE 1.5 language feature
-		return false;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.jdt.core.dom.ITypeBinding#isAnnotation()
-	 */
-	public boolean isAnnotation() {
-		// TODO (olivier) missing implementation of J2SE 1.5 language feature
-		return false;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeParameters()
-	 */
-	public ITypeBinding[] getTypeParameters() {
-		// TODO (olivier) missing implementation of J2SE 1.5 language feature
 		return NO_TYPE_BINDINGS;
 	}
 
@@ -626,64 +659,291 @@
 	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeBounds()
 	 */
 	public ITypeBinding[] getTypeBounds() {
-		// TODO (olivier) missing implementation of J2SE 1.5 language feature
+		if (this.binding instanceof TypeVariableBinding) {
+			TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+			int boundsNumber = 0;
+			ReferenceBinding superclass = typeVariableBinding.superclass();
+			if (superclass != null) {
+				boundsNumber++;
+			}
+			ReferenceBinding[] superinterfaces = typeVariableBinding.superInterfaces();
+			int superinterfacesLength = 0;
+			if (superinterfaces != null) {
+				superinterfacesLength = superinterfaces.length;
+				boundsNumber += superinterfacesLength;
+			}
+			if (boundsNumber != 0) {
+				ITypeBinding[] typeBounds = new ITypeBinding[boundsNumber];
+				int boundsIndex = 0;
+				if (superclass != null) {
+					typeBounds[boundsIndex++] = this.resolver.getTypeBinding(superclass);
+				}
+				if (superinterfaces != null) {
+					for (int i = 0; i < superinterfacesLength; i++, boundsIndex++) {
+						typeBounds[boundsIndex] = this.resolver.getTypeBinding(superinterfaces[i]);
+					}
+				}
+				return typeBounds;
+			}
+		}
 		return NO_TYPE_BINDINGS;
 	}
 
 	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeParameters()
+	 */
+	public ITypeBinding[] getTypeParameters() {
+		TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
+		if (typeVariableBindings != null) {
+			int typeVariableBindingsLength = typeVariableBindings.length;
+			if (typeVariableBindingsLength != 0) {
+				ITypeBinding[] typeParameters = new ITypeBinding[typeVariableBindingsLength];
+				for (int i = 0; i < typeVariableBindingsLength; i++) {
+					typeParameters[i] = this.resolver.getTypeBinding(typeVariableBindings[i]);
+				}
+				return typeParameters;
+			}
+		}
+		return NO_TYPE_BINDINGS;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ITypeBinding#isGenericType()
+	 * @since 3.1
+	 */
+	public boolean isGenericType() {
+		// equivalent to return getTypeParameters().length > 0;
+		TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
+		return (typeVariableBindings != null && typeVariableBindings.length > 0);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ITypeBinding#isAnnotation()
+	 */
+	public boolean isAnnotation() {
+		return this.binding.isAnnotationType();
+	}
+
+	/*
+	 * @see ITypeBinding#isAnonymous()
+	 */
+	public boolean isAnonymous() {
+		if (isClass() || binding.isInterface() || isEnum()) {
+			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+			return referenceBinding.isAnonymousType();
+		}
+		return false;
+	}
+
+	/*
+	 * @see ITypeBinding#isArray()
+	 */
+	public boolean isArray() {
+		return binding.isArrayType();
+	}
+	
+	/* (non-Javadoc)
+	 * @see ITypeBinding#isAssignmentCompatible(ITypeBinding)
+	 */
+	public boolean isAssignmentCompatible(ITypeBinding type) {
+		if (this == type) return true;
+		TypeBinding other = (TypeBinding) type;
+		Scope scope = this.resolver.scope();
+		if (scope == null) return false;
+		return this.binding.isCompatibleWith(other.binding) || scope.isBoxingCompatibleWith(this.binding, other.binding);
+	}
+	
+	/* (non-Javadoc)
+	 * @see ITypeBinding#isCastCompatible(ITypeBinding)
+	 */
+	public boolean isCastCompatible(ITypeBinding type) {
+		Expression expression = new Expression() {
+			public StringBuffer printExpression(int indent,StringBuffer output) {
+				return null;
+			}
+		};
+		Scope scope = this.resolver.scope();
+		if (scope == null) return false;
+		return expression.checkCastTypesCompatibility(scope, this.binding, ((TypeBinding) type).binding, null);
+	}
+
+	/*
+	 * @see ITypeBinding#isClass()
+	 */
+	public boolean isClass() {
+		return this.binding.isClass() && !this.binding.isTypeVariable();
+	}
+
+	/*
+	 * @see IBinding#isDeprecated()
+	 */
+	public boolean isDeprecated() {
+		if (isClass() || isInterface() || isEnum()) {
+			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+			return referenceBinding.isDeprecated();
+		}
+		return false;
+	}
+	
+	/* (non-Javadoc)
+	 * @see ITypeBinding#isEnum()
+	 */
+	public boolean isEnum() {
+		return this.binding.isEnum();
+	}
+
+	/*
+	 * @see IBinding#isEqualTo(Binding)
+	 * @since 3.1
+	 */
+	public boolean isEqualTo(IBinding other) {
+		if (other == this) {
+			// identical binding - equal (key or no key)
+			return true;
+		}
+		if (other == null) {
+			// other binding missing
+			return false;
+		}
+		if (!(other instanceof TypeBinding)) {
+			return false;
+		}
+		org.eclipse.jdt.internal.compiler.lookup.TypeBinding otherBinding = ((TypeBinding) other).binding;
+		// check return type
+		return BindingComparator.isEqual(this.binding, otherBinding);
+	}
+	
+	/*
+	 * @see ITypeBinding#isFromSource()
+	 */
+	public boolean isFromSource() {
+		if (isClass() || isInterface() || isEnum()) {
+			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+			return !referenceBinding.isBinaryBinding();
+		}
+		return false;
+	}
+
+	/*
+	 * @see ITypeBinding#isInterface()
+	 */
+	public boolean isInterface() {
+		return this.binding.isInterface();
+	}
+
+	/*
+	 * @see ITypeBinding#isLocal()
+	 */
+	public boolean isLocal() {
+		if (isClass() || isInterface() || isEnum()) {
+			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+			return referenceBinding.isLocalType() && !referenceBinding.isMemberType();
+		}
+		return false;
+	}
+
+	/*
+	 * @see ITypeBinding#isMember()
+	 */
+	public boolean isMember() {
+		if (isClass() || isInterface() || isEnum()) {
+			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+			return referenceBinding.isMemberType();
+		}
+		return false;
+	}
+
+	/*
+	 * @see ITypeBinding#isNested()
+	 */
+	public boolean isNested() {
+		if (isClass() || isInterface() || isEnum()) {
+			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+			return referenceBinding.isNestedType();
+		}
+		return false;
+	}
+	
+	/**
+	 * @see ITypeBinding#isNullType()
+	 */
+	public boolean isNullType() {
+		return this.binding == BaseTypes.NullBinding;
+	}
+
+	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.core.dom.ITypeBinding#isParameterizedType()
 	 */
 	public boolean isParameterizedType() {
-		// TODO (olivier) missing implementation of J2SE 1.5 language feature
-		return false;
+		return this.binding.isParameterizedType() && ((ParameterizedTypeBinding) this.binding).arguments != null;
 	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeArguments()
+	
+	/*
+	 * @see ITypeBinding#isPrimitive()
 	 */
-	public ITypeBinding[] getTypeArguments() {
-		// TODO (olivier) missing implementation of J2SE 1.5 language feature
-		return NO_TYPE_BINDINGS;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getErasure()
-	 */
-	public ITypeBinding getErasure() {
-		// TODO (olivier) missing implementation of J2SE 1.5 language feature
-		return this;
+	public boolean isPrimitive() {
+		return !isNullType() && binding.isBaseType();
 	}
 
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.core.dom.ITypeBinding#isRawType()
 	 */
 	public boolean isRawType() {
-		// TODO (olivier) missing implementation of J2SE 1.5 language feature
-		return false;
+		return this.binding.isRawType();
 	}
 
 	/* (non-Javadoc)
-	 * @see org.eclipse.jdt.core.dom.ITypeBinding#isWildcardType()
+	 * @see ITypeBinding#isSubTypeCompatible(ITypeBinding)
 	 */
-	public boolean isWildcardType() {
-		// TODO (olivier) missing implementation of J2SE 1.5 language feature
+	public boolean isSubTypeCompatible(ITypeBinding type) {
+		if (this == type) return true;
+		if (this.binding.isBaseType()) return false;
+		TypeBinding other = (TypeBinding) type;
+		if (other.binding.isBaseType()) return false;
+		return this.binding.isCompatibleWith(other.binding);
+	}
+	
+	/**
+	 * @see IBinding#isSynthetic()
+	 */
+	public boolean isSynthetic() {
 		return false;
 	}
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getBound()
+	/*
+	 * @see ITypeBinding#isTopLevel()
 	 */
-	public ITypeBinding getBound() {
-		// TODO (olivier) missing implementation of J2SE 1.5 language feature
-		return null;
+	public boolean isTopLevel() {
+		if (isClass() || isInterface() || isEnum()) {
+			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+			return !referenceBinding.isNestedType();
+		}
+		return false;
+	}
+
+	/*
+	 * @see ITypeBinding#isTypeVariable()
+	 */
+	public boolean isTypeVariable() {
+		return this.binding.isTypeVariable();
 	}
 
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.core.dom.ITypeBinding#isUpperbound()
 	 */
 	public boolean isUpperbound() {
-		// TODO (olivier) missing implementation of J2SE 1.5 language feature
-		return false;
+		return this.binding.isWildcard() && ((WildcardBinding) this.binding).kind == Wildcard.EXTENDS;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ITypeBinding#isWildcardType()
+	 */
+	public boolean isWildcardType() {
+		return this.binding.isWildcard();
+	}
+
+	private boolean shouldBeRemoved(org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding) {
+		return methodBinding.isDefaultAbstract() || methodBinding.isSynthetic() || (methodBinding.isConstructor() && isInterface());
 	}
 	
 	/* 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclaration.java
index 12b3fcd..86b1da9 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclaration.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
@@ -163,26 +164,28 @@
 	private static final List PROPERTY_DESCRIPTORS_3_0;
 	
 	static {
-		createPropertyList(TypeDeclaration.class);
-		addProperty(JAVADOC_PROPERTY);
-		addProperty(MODIFIERS_PROPERTY);
-		addProperty(INTERFACE_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(SUPERCLASS_PROPERTY);
-		addProperty(SUPER_INTERFACES_PROPERTY);
-		addProperty(BODY_DECLARATIONS_PROPERTY);
-		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList();
+		List propertyList = new ArrayList(8);
+		createPropertyList(TypeDeclaration.class, propertyList);
+		addProperty(JAVADOC_PROPERTY, propertyList);
+		addProperty(MODIFIERS_PROPERTY, propertyList);
+		addProperty(INTERFACE_PROPERTY, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		addProperty(SUPERCLASS_PROPERTY, propertyList);
+		addProperty(SUPER_INTERFACES_PROPERTY, propertyList);
+		addProperty(BODY_DECLARATIONS_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
 		
-		createPropertyList(TypeDeclaration.class);
-		addProperty(JAVADOC_PROPERTY);
-		addProperty(MODIFIERS2_PROPERTY);
-		addProperty(INTERFACE_PROPERTY);
-		addProperty(NAME_PROPERTY);
-		addProperty(TYPE_PARAMETERS_PROPERTY);
-		addProperty(SUPERCLASS_TYPE_PROPERTY);
-		addProperty(SUPER_INTERFACE_TYPES_PROPERTY);
-		addProperty(BODY_DECLARATIONS_PROPERTY);
-		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList();
+		propertyList = new ArrayList(9);
+		createPropertyList(TypeDeclaration.class, propertyList);
+		addProperty(JAVADOC_PROPERTY, propertyList);
+		addProperty(MODIFIERS2_PROPERTY, propertyList);
+		addProperty(INTERFACE_PROPERTY, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		addProperty(TYPE_PARAMETERS_PROPERTY, propertyList);
+		addProperty(SUPERCLASS_TYPE_PROPERTY, propertyList);
+		addProperty(SUPER_INTERFACE_TYPES_PROPERTY, propertyList);
+		addProperty(BODY_DECLARATIONS_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
 	}
 
 	/**
@@ -764,18 +767,10 @@
 		return memberTypes;
 	}
 
-	/**
-	 * Resolves and returns the binding for the class or interface declared in
-	 * this type declaration.
-	 * <p>
-	 * Note that bindings are generally unavailable unless requested when the
-	 * AST is being built.
-	 * </p>
-	 * 
-	 * @return the binding, or <code>null</code> if the binding cannot be 
-	 *    resolved
-	 */	
-	public ITypeBinding resolveBinding() {
+	/* (omit javadoc for this method)
+	 * Method declared on AsbtractTypeDeclaration.
+	 */
+	ITypeBinding internalResolveBinding() {
 		return this.ast.getBindingResolver().resolveType(this);
 	}
 	
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclarationStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclarationStatement.java
index 300e6d2..bd95600 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclarationStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclarationStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -24,14 +25,15 @@
  * TypeDeclarationStatement:
  *    TypeDeclaration
  * </pre>
- * For JLS3, the kinds of type declarations
- * grew to include enum and annotation type declarations:
+ * For JLS3, the kinds of type declarations grew to include enum declarations:
  * <pre>
  * TypeDeclarationStatement:
  *    TypeDeclaration
  *    EnumDeclaration
- *    AnnotationTypeDeclaration
  * </pre>
+ * Although allowed at the AST, not all arrangements of AST nodes are meaningful;
+ * in particular, only class and enum declarations are meaningful in the context of 
+ * a block.
  * 
  * @since 2.0
  */
@@ -69,13 +71,15 @@
 	private static final List PROPERTY_DESCRIPTORS_3_0;
 	
 	static {
-		createPropertyList(TypeDeclarationStatement.class);
-		addProperty(TYPE_DECLARATION_PROPERTY);
-		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList();
+		List propertyList = new ArrayList(2);
+		createPropertyList(TypeDeclarationStatement.class, propertyList);
+		addProperty(TYPE_DECLARATION_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
 		
-		createPropertyList(TypeDeclarationStatement.class);
-		addProperty(DECLARATION_PROPERTY);
-		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList();
+		propertyList = new ArrayList(2);
+		createPropertyList(TypeDeclarationStatement.class, propertyList);
+		addProperty(DECLARATION_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
 	}
 
 	/**
@@ -190,7 +194,7 @@
 	
 	/**
 	 * Returns the abstract type declaration of this local type declaration
-	 * statement (JLS2 API only).
+	 * statement (added in JLS3 API).
 	 * 
 	 * @return the type declaration node
 	 * @since 3.0
@@ -211,7 +215,7 @@
 		
 	/**
 	 * Sets the abstract type declaration of this local type declaration
-	 * statement (JLS2 API only).
+	 * statement (added in JLS3 API).
 	 * 
 	 * @param decl the type declaration node
 	 * @exception IllegalArgumentException if:
@@ -236,7 +240,7 @@
 	
 	/**
 	 * Returns the type declaration of this local type declaration
-	 * statement (added in JLS3 API).
+	 * statement (JLS2 API only).
 	 * 
 	 * @return the type declaration node
 	 * @exception UnsupportedOperationException if this operation is used in
@@ -250,7 +254,7 @@
 		
 	/**
 	 * Sets the type declaration of this local type declaration
-	 * statement (added in JLS3 API).
+	 * statement (JLS2 API only).
 	 * 
 	 * @param decl the type declaration node
 	 * @exception IllegalArgumentException if:
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeLiteral.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeLiteral.java
index 9fc281b..b149f8e 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeLiteral.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeLiteral.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -40,9 +41,10 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(TypeLiteral.class);
-		addProperty(TYPE_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(2);
+		createPropertyList(TypeLiteral.class, propertyList);
+		addProperty(TYPE_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeParameter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeParameter.java
index e38ce3d..6247d14 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeParameter.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeParameter.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -52,10 +53,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(TypeParameter.class);
-		addProperty(NAME_PROPERTY);
-		addProperty(TYPE_BOUNDS_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(TypeParameter.class, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		addProperty(TYPE_BOUNDS_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
@@ -195,6 +197,21 @@
 	}
 	
 	/**
+	 * Resolves and returns the binding for this type parameter.
+	 * <p>
+	 * Note that bindings are generally unavailable unless requested when the
+	 * AST is being built.
+	 * </p>
+	 * 
+	 * @return the binding, or <code>null</code> if the binding cannot be 
+	 *    resolved
+	 * @since 3.1
+	 */	
+	public final IBinding resolveBinding() {
+		return this.ast.getBindingResolver().resolveTypeParameter(this);
+	}
+	
+	/**
 	 * Sets the name of the type variable of this type parameter to the given
 	 * name.
 	 * 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java
index 4d4ca84..b533b0f 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java
@@ -11,188 +11,43 @@
 
 package org.eclipse.jdt.core.dom;
 
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.util.IModifierConstants;
-import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
-import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
-import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.core.JavaElement;
+import org.eclipse.jdt.internal.core.LocalVariable;
 
 /**
  * Internal implementation of variable bindings.
  */
 class VariableBinding implements IVariableBinding {
 
+	private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+		Modifier.STATIC | Modifier.FINAL | Modifier.TRANSIENT | Modifier.VOLATILE;
+	
 	private org.eclipse.jdt.internal.compiler.lookup.VariableBinding binding;
-	private BindingResolver resolver;
-	private String name;
 	private ITypeBinding declaringClass;
-	private ITypeBinding type;
 	private String key;
+	private String name;
+	private BindingResolver resolver;
+	private ITypeBinding type;
 
 	VariableBinding(BindingResolver resolver, org.eclipse.jdt.internal.compiler.lookup.VariableBinding binding) {
 		this.resolver = resolver;
 		this.binding = binding;
 	}
 
-	/*
-	 * @see IVariableBinding#isField()
-	 */
-	public boolean isField() {
-		return this.binding instanceof FieldBinding;
-	}
-
-	/*
-	 * @see IBinding#getName()
-	 */
-	public String getName() {
-		if (this.name == null) {
-			this.name = new String(this.binding.name);
-		}
-		return this.name;
-	}
-
-	/*
-	 * @see IVariableBinding#getDeclaringClass()
-	 */
-	public ITypeBinding getDeclaringClass() {
-		if (isField()) {
-			if (this.declaringClass == null) {
-				FieldBinding fieldBinding = (FieldBinding) this.binding;
-				this.declaringClass = this.resolver.getTypeBinding(fieldBinding.declaringClass);
-			}
-			return this.declaringClass;
-		} else {
-			return null;
-		}
-	}
-	
-	/*
-	 * @see IVariableBinding#getType()
-	 */
-	public ITypeBinding getType() {
-		if (type == null) {
-			type = this.resolver.getTypeBinding(this.binding.type);
-		}
-		return type;
-	}
-
-	/*
-	 * @see IBinding#getKind()
-	 */
-	public int getKind() {
-		return IBinding.VARIABLE;
-	}
-
-	/*
-	 * @see IBinding#getModifiers()
-	 */
-	public int getModifiers() {
-		if (isField()) {
-			return ((FieldBinding) this.binding).getAccessFlags();
-		}
-		if (binding.isFinal()) {
-			return IModifierConstants.ACC_FINAL;
-		}
-		return 0;
-	}
-
-	/*
-	 * @see IBinding#isDeprecated()
-	 */
-	public boolean isDeprecated() {
-		if (isField()) {
-			return ((FieldBinding) this.binding).isDeprecated();
-		}
-		return false;
-	}
-
-	/**
-	 * @see IBinding#isSynthetic()
-	 */
-	public boolean isSynthetic() {
-		if (isField()) {
-			return ((FieldBinding) this.binding).isSynthetic();
-		}
-		return false;
-	}
-
-	/*
-	 * @see IBinding#getKey()
-	 */
-	public String getKey() {
-		if (this.key == null) {
-			if (isField()) {
-				StringBuffer buffer = new StringBuffer();
-				if (this.getDeclaringClass() != null) {
-					buffer.append(this.getDeclaringClass().getKey());
-					buffer.append('/');
-				}
-				buffer.append(this.getName());
-				this.key = buffer.toString();
-			} else {
-				StringBuffer buffer = new StringBuffer();
-				
-				// declaring method or type
-				LocalVariableBinding localVarBinding = (LocalVariableBinding) this.binding;
-				BlockScope scope = localVarBinding.declaringScope;
-				MethodScope methodScope = scope instanceof MethodScope ? (MethodScope) scope : scope.enclosingMethodScope();
-				ReferenceContext referenceContext = methodScope.referenceContext;
-				if (referenceContext instanceof AbstractMethodDeclaration) {
-					org.eclipse.jdt.internal.compiler.lookup.MethodBinding internalBinding = ((AbstractMethodDeclaration) referenceContext).binding;
-					IMethodBinding methodBinding = this.resolver.getMethodBinding(internalBinding);
-					if (methodBinding != null) {
-						buffer.append(methodBinding.getKey());
-					}
-				} else if (referenceContext instanceof TypeDeclaration) {
-					org.eclipse.jdt.internal.compiler.lookup.TypeBinding internalBinding = ((TypeDeclaration) referenceContext).binding;
-					ITypeBinding typeBinding = this.resolver.getTypeBinding(internalBinding);
-					if (typeBinding != null) {
-						buffer.append(typeBinding.getKey());
-					}
-				}
-	
-				// scope index
-				getKey(scope, buffer);
-	
-				// variable name
-				buffer.append('/');
-				buffer.append(getName());
-				
-				this.key = buffer.toString();
-			}
-		}
-		return this.key;
-	}
-	
-	private void getKey(BlockScope scope, StringBuffer buffer) {
-		int scopeIndex = scope.scopeIndex();
-		if (scopeIndex != -1) {
-			getKey((BlockScope)scope.parent, buffer);
-			buffer.append('/');
-			buffer.append(scopeIndex);
-		}
-	}
-	
-	/*
-	 * @see IVariableBinding#getVariableId()
-	 */
-	public int getVariableId() {
-		return this.binding.id;
-	}
-
 	/* (non-Javadoc)
 	 * @see IVariableBinding#getConstantValue()
 	 * @since 3.0
 	 */
 	public Object getConstantValue() {
-		if (!this.binding.isConstantValue() || this.binding.constant == null) {
-			return null;
-		}
-		Constant c = this.binding.constant;
+		if (!this.binding.isConstantValue()) return null;
+		Constant c = this.binding.constant();
+		if (c == null) return null;
 		switch (c.typeID()) {
 			case TypeIds.T_boolean:
 				return Boolean.valueOf(c.booleanValue());
@@ -210,12 +65,210 @@
 				return new Long(c.longValue());
 			case TypeIds.T_short:
 				return new Short(c.shortValue());
-			case TypeIds.T_String:
+			case TypeIds.T_JavaLangString:
 				return c.stringValue();
 		}
 		return null;
 	}
 
+	/*
+	 * @see IVariableBinding#getDeclaringClass()
+	 */
+	public ITypeBinding getDeclaringClass() {
+		if (isField()) {
+			if (this.declaringClass == null) {
+				FieldBinding fieldBinding = (FieldBinding) this.binding;
+				this.declaringClass = this.resolver.getTypeBinding(fieldBinding.declaringClass);
+			}
+			return this.declaringClass;
+		} else {
+			return null;
+		}
+	}
+
+	/*
+	 * @see IVariableBinding#getDeclaringMethod()
+	 */
+	public IMethodBinding getDeclaringMethod() {
+		if (!isField()) {
+			ASTNode node = this.resolver.findDeclaringNode(this);
+			while (true) {
+				if (node == null) break;
+				switch(node.getNodeType()) {
+					case ASTNode.INITIALIZER :
+						return null;
+					case ASTNode.METHOD_DECLARATION :
+						MethodDeclaration methodDeclaration = (MethodDeclaration) node;
+						return methodDeclaration.resolveBinding();
+					default:
+						node = node.getParent();
+				}
+			}
+		}
+		return null;
+	}
+
+	/*
+	 * @see IBinding#getJavaElement()
+	 */
+	public IJavaElement getJavaElement() {
+		if (isField()) {
+			// field
+			IType declaringType = (IType) getDeclaringClass().getJavaElement();
+			if (declaringType == null) return null;
+			return declaringType.getField(getName());
+		}
+		// local variable
+		IMethodBinding declaringMethod = getDeclaringMethod();
+		if (declaringMethod == null) return null;
+		JavaElement method = (JavaElement) declaringMethod.getJavaElement();
+		if (!(this.resolver instanceof DefaultBindingResolver)) return null;
+		VariableDeclaration localVar = (VariableDeclaration) ((DefaultBindingResolver) this.resolver).bindingsToAstNodes.get(this);
+		if (localVar == null) return null;
+		int nameStart;
+		int nameLength;
+		int sourceStart;
+		int sourceLength;
+		if (localVar instanceof SingleVariableDeclaration) {
+			sourceStart = localVar.getStartPosition();
+			sourceLength = localVar.getLength();
+			SimpleName simpleName = ((SingleVariableDeclaration) localVar).getName();
+			nameStart = simpleName.getStartPosition();
+			nameLength = simpleName.getLength();
+		} else {
+			nameStart =  localVar.getStartPosition();
+			nameLength = localVar.getLength();
+			VariableDeclarationStatement statement = (VariableDeclarationStatement) localVar.getParent();
+			sourceStart = statement.getStartPosition();
+			sourceLength = statement.getLength();
+		}
+		char[] typeSig = this.binding.type.genericTypeSignature();
+		return new LocalVariable(method, localVar.getName().getIdentifier(), sourceStart, sourceStart+sourceLength-1, nameStart, nameStart+nameLength-1, new String(typeSig));
+	}
+	
+	/*
+	 * @see IBinding#getKey()
+	 */
+	public String getKey() {
+		if (this.key == null) {
+			this.key = new String(this.binding.computeUniqueKey());
+		}
+		return this.key;
+	}
+
+	/*
+	 * @see IBinding#getKind()
+	 */
+	public int getKind() {
+		return IBinding.VARIABLE;
+	}
+
+	/*
+	 * @see IBinding#getModifiers()
+	 */
+	public int getModifiers() {
+		if (isField()) {
+			return ((FieldBinding) this.binding).getAccessFlags() & VALID_MODIFIERS;
+		}
+		if (binding.isFinal()) {
+			return IModifierConstants.ACC_FINAL;
+		}
+		return 0;
+	}
+
+	/*
+	 * @see IBinding#getName()
+	 */
+	public String getName() {
+		if (this.name == null) {
+			this.name = new String(this.binding.name);
+		}
+		return this.name;
+	}
+	
+	/*
+	 * @see IVariableBinding#getType()
+	 */
+	public ITypeBinding getType() {
+		if (type == null) {
+			type = this.resolver.getTypeBinding(this.binding.type);
+		}
+		return type;
+	}
+	
+	/*
+	 * @see IVariableBinding#getVariableId()
+	 */
+	public int getVariableId() {
+		return this.binding.id;
+	}
+
+	/*
+	 * @see IBinding#isDeprecated()
+	 */
+	public boolean isDeprecated() {
+		if (isField()) {
+			return ((FieldBinding) this.binding).isDeprecated();
+		}
+		return false;
+	}
+	
+	/*
+	 * @see IBinding#isEqualTo(Binding)
+	 * @since 3.1
+	 */
+	public boolean isEqualTo(IBinding other) {
+		if (other == this) {
+			// identical binding - equal (key or no key)
+			return true;
+		}
+		if (other == null) {
+			// other binding missing
+			return false;
+		}
+		if (!(other instanceof VariableBinding)) {
+			return false;
+		}
+		org.eclipse.jdt.internal.compiler.lookup.VariableBinding otherBinding = ((VariableBinding) other).binding;
+		if (this.binding instanceof FieldBinding) {
+			if (otherBinding instanceof FieldBinding) {
+				return BindingComparator.isEqual((FieldBinding) this.binding, (FieldBinding) otherBinding);
+			} else {
+				return false;
+			}
+		} else {
+			if (BindingComparator.isEqual(this.binding, otherBinding)) {
+				IMethodBinding declaringMethod = this.getDeclaringMethod();
+				IMethodBinding otherDeclaringMethod = ((VariableBinding) other).getDeclaringMethod();
+				if (declaringMethod == null) {
+					if (otherDeclaringMethod != null) {
+						return false;
+					}
+					return true;
+				}
+				return declaringMethod.isEqualTo(otherDeclaringMethod);
+			}
+			return false;
+		}
+	}
+
+	/*
+	 * @see IVariableBinding#isField()
+	 */
+	public boolean isField() {
+		return this.binding instanceof FieldBinding;
+	}
+
+	/*
+	 * @see IBinding#isSynthetic()
+	 */
+	public boolean isSynthetic() {
+		if (isField()) {
+			return ((FieldBinding) this.binding).isSynthetic();
+		}
+		return false;
+	}
+
 	/* 
 	 * For debugging purpose only.
 	 * @see java.lang.Object#toString()
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclaration.java
index 7ac5325..06281ea 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclaration.java
@@ -29,6 +29,66 @@
 public abstract class VariableDeclaration extends ASTNode {
 	
 	/**
+	 * Returns structural property descriptor for the "extraDimensions" property
+	 * of this node.
+	 * 
+	 * @return the property descriptor
+	 * @since 3.1
+	 */
+	abstract SimplePropertyDescriptor internalExtraDimensionsProperty();
+
+	/**
+	 * Returns structural property descriptor for the "extraDimensions" property
+	 * of this node.
+	 * 
+	 * @return the property descriptor
+	 * @since 3.1
+	 */
+	public final SimplePropertyDescriptor getExtraDimensionsProperty() {
+		return internalExtraDimensionsProperty();
+	}
+
+	/**
+	 * Returns structural property descriptor for the "initializer" property
+	 * of this node.
+	 * 
+	 * @return the property descriptor
+	 * @since 3.1
+	 */
+	abstract ChildPropertyDescriptor internalInitializerProperty();
+
+	/**
+	 * Returns structural property descriptor for the "initializer" property
+	 * of this node.
+	 * 
+	 * @return the property descriptor
+	 * @since 3.1
+	 */
+	public final ChildPropertyDescriptor getInitializerProperty() {
+		return internalInitializerProperty();
+	}
+
+	/**
+	 * Returns structural property descriptor for the "name" property
+	 * of this node.
+	 * 
+	 * @return the property descriptor
+	 * @since 3.1
+	 */
+	abstract ChildPropertyDescriptor internalNameProperty();
+
+	/**
+	 * Returns structural property descriptor for the "name" property
+	 * of this node.
+	 * 
+	 * @return the property descriptor
+	 * @since 3.1
+	 */
+	public final ChildPropertyDescriptor getNameProperty() {
+		return internalNameProperty();
+	}
+
+	/**
 	 * Creates a new AST node for a variable declaration owned by the given AST.
 	 * <p>
 	 * N.B. This constructor is package-private.
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationExpression.java
index a3f8c57..e6b1a40 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationExpression.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationExpression.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
@@ -20,8 +21,9 @@
  * This kind of node collects together several variable declaration fragments
  * (<code>VariableDeclarationFragment</code>) into a single expression
  * (<code>Expression</code>), all sharing the same modifiers and base type.
- * This type of node is used (only) as the initializer of a
- * <code>ForStatement</code>.
+ * This type of node can be used as the initializer of a
+ * <code>ForStatement</code>, or wrapped in an <code>ExpressionStatement</code>
+ * to form the equivalent of a <code>VariableDeclarationStatement</code>.
  * </p>
  * For JLS2:
  * <pre>
@@ -87,17 +89,19 @@
 	private static final List PROPERTY_DESCRIPTORS_3_0;
 	
 	static {
-		createPropertyList(VariableDeclarationExpression.class);
-		addProperty(MODIFIERS_PROPERTY);
-		addProperty(TYPE_PROPERTY);
-		addProperty(FRAGMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList();
+		List propertyList = new ArrayList(4);
+		createPropertyList(VariableDeclarationExpression.class, propertyList);
+		addProperty(MODIFIERS_PROPERTY, propertyList);
+		addProperty(TYPE_PROPERTY, propertyList);
+		addProperty(FRAGMENTS_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
 		
-		createPropertyList(VariableDeclarationExpression.class);
-		addProperty(MODIFIERS2_PROPERTY);
-		addProperty(TYPE_PROPERTY);
-		addProperty(FRAGMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList();
+		propertyList = new ArrayList(4);
+		createPropertyList(VariableDeclarationExpression.class, propertyList);
+		addProperty(MODIFIERS2_PROPERTY, propertyList);
+		addProperty(TYPE_PROPERTY, propertyList);
+		addProperty(FRAGMENTS_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationFragment.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationFragment.java
index 3a2332a..80d11af 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationFragment.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationFragment.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -59,11 +60,12 @@
 	private static final List PROPERTY_DESCRIPTORS;
 		
 	static {
-		createPropertyList(VariableDeclarationFragment.class);
-		addProperty(NAME_PROPERTY);
-		addProperty(EXTRA_DIMENSIONS_PROPERTY);
-		addProperty(INITIALIZER_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(4);
+		createPropertyList(VariableDeclarationFragment.class, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+		addProperty(INITIALIZER_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
@@ -113,6 +115,30 @@
 	}
 
 	/* (omit javadoc for this method)
+	 * Method declared on VariableDeclaration.
+	 * @since 3.1
+	 */
+	final SimplePropertyDescriptor internalExtraDimensionsProperty() {
+		return EXTRA_DIMENSIONS_PROPERTY;
+	}
+
+	/* (omit javadoc for this method)
+	 * Method declared on VariableDeclaration.
+	 * @since 3.1
+	 */
+	final ChildPropertyDescriptor internalInitializerProperty() {
+		return INITIALIZER_PROPERTY;
+	}
+
+	/* (omit javadoc for this method)
+	 * Method declared on VariableDeclaration.
+	 * @since 3.1
+	 */
+	final ChildPropertyDescriptor internalNameProperty() {
+		return NAME_PROPERTY;
+	}
+
+	/* (omit javadoc for this method)
 	 * Method declared on ASTNode.
 	 */
 	final List internalStructuralPropertiesForType(int apiLevel) {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationStatement.java
index 687d7c5..1c4c2dd 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
@@ -34,6 +35,12 @@
  *    { ExtendedModifier } Type VariableDeclarationFragment 
  *        { <b>,</b> VariableDeclarationFragment } <b>;</b>
  * </pre>
+ * <p>
+ * Note: This type of node is a convenience of sorts. 
+ * An equivalent way to represent the same statement is to use
+ * a <code>VariableDeclarationExpression</code>
+ * wrapped in an <code>ExpressionStatement</code>.
+ * </p>
  * 
  * @since 2.0
  */
@@ -85,17 +92,19 @@
 	private static final List PROPERTY_DESCRIPTORS_3_0;
 	
 	static {
-		createPropertyList(VariableDeclarationStatement.class);
-		addProperty(MODIFIERS_PROPERTY);
-		addProperty(TYPE_PROPERTY);
-		addProperty(FRAGMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList();
+		List propertyList = new ArrayList(4);
+		createPropertyList(VariableDeclarationStatement.class, propertyList);
+		addProperty(MODIFIERS_PROPERTY, propertyList);
+		addProperty(TYPE_PROPERTY, propertyList);
+		addProperty(FRAGMENTS_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
 		
-		createPropertyList(VariableDeclarationStatement.class);
-		addProperty(MODIFIERS2_PROPERTY);
-		addProperty(TYPE_PROPERTY);
-		addProperty(FRAGMENTS_PROPERTY);
-		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList();
+		propertyList = new ArrayList(4);
+		createPropertyList(VariableDeclarationStatement.class, propertyList);
+		addProperty(MODIFIERS2_PROPERTY, propertyList);
+		addProperty(TYPE_PROPERTY, propertyList);
+		addProperty(FRAGMENTS_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WhileStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WhileStatement.java
index 731bf08..e6f7694 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WhileStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WhileStatement.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -47,10 +48,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(WhileStatement.class);
-		addProperty(EXPRESSION_PROPERTY);
-		addProperty(BODY_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(WhileStatement.class, propertyList);
+		addProperty(EXPRESSION_PROPERTY, propertyList);
+		addProperty(BODY_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WildcardType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WildcardType.java
index 9b48773..8a33583 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WildcardType.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WildcardType.java
@@ -11,6 +11,7 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -57,10 +58,11 @@
 	private static final List PROPERTY_DESCRIPTORS;
 	
 	static {
-		createPropertyList(WildcardType.class);
-		addProperty(BOUND_PROPERTY);
-		addProperty(UPPER_BOUND_PROPERTY);
-		PROPERTY_DESCRIPTORS = reapPropertyList();
+		List propertyList = new ArrayList(3);
+		createPropertyList(WildcardType.class, propertyList);
+		addProperty(BOUND_PROPERTY, propertyList);
+		addProperty(UPPER_BOUND_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java
index f689e0b..1c56637 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java
@@ -13,12 +13,21 @@
 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.JavaCore;
+
 import org.eclipse.jdt.core.dom.AST;
 import org.eclipse.jdt.core.dom.ASTNode;
+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.NodeInfoStore;
 import org.eclipse.jdt.internal.core.dom.rewrite.NodeRewriteEvent;
@@ -26,12 +35,6 @@
 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.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.
  * The AST rewriter collects descriptions of modifications to nodes and
@@ -328,7 +331,6 @@
 		if (node == null || property == null) {
 			throw new IllegalArgumentException();
 		}
-		validateIsInsideAST(node);
 		validateIsListProperty(property);
 		
 		return new ListRewrite(this, node, property);
@@ -420,6 +422,35 @@
 		return placeholder;
 	}
 	
+	/**
+	 * Creates and returns a node that represents a sequence of nodes. 
+	 * Each of the given nodes must be either be brand new (not part of the original AST), or
+	 * a placeholder node (for example, one created by {@link #createCopyTarget(ASTNode)}
+	 * or {@link #createStringPlaceholder(String, int)}), or another group node.
+	 * The type of the returned node is unspecified. The returned node can be used
+	 * to replace an existing node (or as an element of another group node).
+	 * When the document is rewritten, the source code for each of the given nodes is
+	 * inserted, in order, into the output document at the position corresponding to the
+	 * group (indentation is adjusted).
+	 * 
+	 * @param targetNodes the nodes to go in the group
+	 * @return the new group node
+	 * @throws IllegalArgumentException if the targetNodes is <code>null</code> or empty
+	 * @since 3.1
+	 */
+	public final ASTNode createGroupNode(ASTNode[] targetNodes) {
+		if (targetNodes == null || targetNodes.length == 0) {
+			throw new IllegalArgumentException();
+		}
+		Block res= getNodeStore().createCollapsePlaceholder();
+		ListRewrite listRewrite= getListRewrite(res, Block.STATEMENTS_PROPERTY);
+		for (int i= 0; i < targetNodes.length; i++) {
+			listRewrite.insertLast(targetNodes[i], null);
+		}
+		return res;
+	}
+	
+	
 	private ASTNode createTargetNode(ASTNode node, boolean isMove) {
 		if (node == null) {
 			throw new IllegalArgumentException();
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ListRewrite.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ListRewrite.java
index 566920c..7f848f2 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ListRewrite.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ListRewrite.java
@@ -78,6 +78,16 @@
 			getRewriteStore().setEventEditGroup(event, editGroup);
 		}
 	}
+	
+	/**
+	 * Returns the ASTRewrite instance from which this ListRewriter has been created from.
+	 * @return the parent AST Rewriter instance.
+	 * @since 3.1
+	 */
+	public ASTRewrite getASTRewrite() {
+		return this.rewriter;
+	}
+	
 
 	/**
 	 * Replaces the given node from its parent's list property in the rewriter.
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
index a6936aa..cb1e8ea 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
@@ -247,7 +247,7 @@
 	
 	final int doVisit(ASTNode node) {
 		node.accept(this);
-		return node.getStartPosition() + node.getLength();
+		return getExtendedEnd(node);
 	}
 	
 	private final int doVisit(ASTNode parent, StructuralPropertyDescriptor property, int offset) {
@@ -564,7 +564,7 @@
 			int length= getExtendedLength(node);
 			doTextRemoveAndVisit(offset, length, node, editGroup);
 			doTextInsert(offset, (ASTNode) event.getNewValue(), getIndent(offset), true, editGroup);
-			return offset + length;			
+			return offset + length;	
 		}
 		return doVisit(parent, property, 0);
 	}
@@ -679,7 +679,11 @@
 				}
 			}
 		}
-		return doVisit(parent, property, offset);
+		int pos= doVisit(parent, property, offset);
+		if (endPos != -1) {
+			return endPos;
+		}
+		return pos;
 	}
 	
 	private int rewriteOptionalQualifier(ASTNode parent, StructuralPropertyDescriptor property, int startPos) {
@@ -820,15 +824,9 @@
 		}
 		
 		RewriteEvent[] events= event.getChildren();
-		boolean hasExisting= false;
-		for (int i= 0; i < events.length; i++) {
-			int changeKind= events[i].getChangeKind();
-			hasExisting |= (changeKind != RewriteEvent.INSERTED);
-		}
-		
 		ParagraphListRewriter listRewriter= new ParagraphListRewriter(insertIndent, separator);
 		StringBuffer leadString= new StringBuffer();
-		if (!hasExisting) {
+		if (isAllOfKind(events, RewriteEvent.INSERTED)) {
 			for (int i= 0; i < lead; i++) {
 				leadString.append(getLineDelimiter());
 			}
@@ -837,6 +835,50 @@
 		return listRewriter.rewriteList(parent, property, insertPos, leadString.toString());
 	}
 	
+	private int rewriteOptionalTypeParameters(ASTNode parent, StructuralPropertyDescriptor property, int offset, String keyword) {
+		int pos= offset;
+		RewriteEvent event= getEvent(parent, property);
+		if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) {
+			RewriteEvent[] children= event.getChildren();
+			try {
+				boolean isAllRemoved= isAllOfKind(children, RewriteEvent.REMOVED);
+				if (isAllRemoved) { // all removed: set start to left bracket
+					pos= getScanner().getTokenStartOffset(ITerminalSymbols.TokenNameLESS, pos);
+				}
+				pos= new ListRewriter().rewriteList(parent, property, pos, keyword + String.valueOf('<'), ", "); //$NON-NLS-1$ //$NON-NLS-2$
+				if (isAllRemoved) { // all removed: remove right bracked
+					int endPos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameGREATER, pos); // set pos to '>'
+					doTextRemove(pos, endPos - pos, getEditGroup(children[children.length - 1]));
+					return endPos;
+				} else if (isAllOfKind(children, RewriteEvent.INSERTED)) {
+					doTextInsert(pos, String.valueOf('>'), getEditGroup(children[children.length - 1]));
+					return pos;
+				}
+			} catch (CoreException e) {
+				handleException(e);
+			}
+		} else {
+			pos= doVisit(parent, property, pos);
+		}
+		if (pos != offset) { // list contained some type -> parse after closing bracket
+			try {
+				return getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameGREATER, pos);
+			} catch (CoreException e) {
+				handleException(e);
+			}
+		}
+		return pos;
+	}
+	
+	private boolean isAllOfKind(RewriteEvent[] children, int kind) {
+		for (int i= 0; i < children.length; i++) {
+			if (children[i].getChangeKind() != kind) {
+				return false;
+			}
+		}
+		return true;
+	}	
+	
 	private int rewriteNodeList(ASTNode parent, StructuralPropertyDescriptor property, int pos, String keyword, String separator) {
 		RewriteEvent event= getEvent(parent, property);
 		if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) {
@@ -1011,21 +1053,24 @@
 	
 
 	private void rewriteModifiers(ASTNode parent, StructuralPropertyDescriptor property, int offset) {
-		
 		RewriteEvent event= getEvent(parent, property);
 		if (event == null || event.getChangeKind() != RewriteEvent.REPLACED) {
 			return;
 		}
-		
-		int oldModifiers= ((Integer) event.getOriginalValue()).intValue();
-		int newModifiers= ((Integer) event.getNewValue()).intValue();
-		TextEditGroup editGroup= getEditGroup(event);
-		
 		try {
-			int tok= getScanner().readNext(offset, true);
-			int startPos= getScanner().getCurrentStartOffset();
-			int endPos= startPos;
+			int oldModifiers= ((Integer) event.getOriginalValue()).intValue();
+			int newModifiers= ((Integer) event.getNewValue()).intValue();
+			TextEditGroup editGroup= getEditGroup(event);
+		
+			TokenScanner scanner= getScanner();
+
+			int tok= scanner.readNext(offset, false);
+			int startPos= scanner.getCurrentStartOffset();
+			int nextStart= startPos;
 			loop: while (true) {
+				if (TokenScanner.isComment(tok)) {
+					tok= scanner.readNext(true); // next non-comment token
+				}
 				boolean keep= true;
 				switch (tok) {
 					case ITerminalSymbols.TokenNamepublic: keep= Modifier.isPublic(newModifiers); break;
@@ -1042,16 +1087,16 @@
 					default:
 						break loop;
 				}
-				tok= getScanner().readNext(true);
-				int currPos= endPos;
-				endPos= getScanner().getCurrentStartOffset();
+				tok= getScanner().readNext(false); // include comments
+				int currPos= nextStart;
+				nextStart= getScanner().getCurrentStartOffset();
 				if (!keep) {
-					doTextRemove(currPos, endPos - currPos, editGroup);
+					doTextRemove(currPos, nextStart - currPos, editGroup);
 				}
 			} 
 			int addedModifiers= newModifiers & ~oldModifiers;
 			if (addedModifiers != 0) {
-				if (startPos != endPos) {
+				if (startPos != nextStart) {
 					int visibilityModifiers= addedModifiers & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED);
 					if (visibilityModifiers != 0) {
 						StringBuffer buf= new StringBuffer();
@@ -1062,13 +1107,46 @@
 				}
 				StringBuffer buf= new StringBuffer();
 				ASTRewriteFlattener.printModifiers(addedModifiers, buf);
-				doTextInsert(endPos, buf.toString(), editGroup);
+				doTextInsert(nextStart, buf.toString(), editGroup);
 			}
 		} catch (CoreException e) {
-			// ignore
-		}		
+			handleException(e);
+		}
 	}
 	
+	private int rewriteModifiers2(ASTNode node, ChildListPropertyDescriptor property, int pos) {
+		RewriteEvent event= getEvent(node, property);
+		if (event == null || event.getChangeKind() == RewriteEvent.UNCHANGED) {
+			return doVisit(node, property, pos);
+		}
+		RewriteEvent[] children= event.getChildren();
+		boolean isAllInsert= isAllOfKind(children, RewriteEvent.INSERTED);
+		boolean isAllRemove= isAllOfKind(children, RewriteEvent.REMOVED);
+		if (isAllInsert || isAllRemove) {
+			// update pos
+			try {
+				pos= getScanner().getNextStartOffset(pos, false);
+			} catch (CoreException e) {
+				handleException(e);
+			}
+		}
+		int endPos= rewriteNodeList(node, property, pos, "", " "); //$NON-NLS-1$ //$NON-NLS-2$
+
+		if (isAllInsert) {
+			doTextInsert(endPos, " ", getEditGroup(children[children.length - 1])); //$NON-NLS-1$
+		} else if (isAllRemove) {
+			try {
+				int nextPos= getScanner().getNextStartOffset(endPos, false); // to the next token
+				doTextRemove(endPos, nextPos - endPos, getEditGroup(children[children.length - 1]));
+				return nextPos;
+			} catch (CoreException e) {
+				handleException(e);
+			}
+		}
+		return endPos;
+	}
+	
+	
 	private void replaceOperation(int posBeforeOperation, String newOperation, TextEditGroup editGroup) {
 		try {
 			getScanner().readNext(posBeforeOperation, true);
@@ -1170,8 +1248,15 @@
 		if (!hasChildrenChanges(node)) {
 			return doVisitUnchangedChildren(node);
 		}
+		int apiLevel= node.getAST().apiLevel();
+		
 		int pos= rewriteJavadoc(node, TypeDeclaration.JAVADOC_PROPERTY);
-		rewriteModifiers(node, TypeDeclaration.MODIFIERS_PROPERTY, pos);
+		
+		if (apiLevel == AST.JLS2) {
+			rewriteModifiers(node, TypeDeclaration.MODIFIERS_PROPERTY, pos);
+		} else {
+			rewriteModifiers2(node, TypeDeclaration.MODIFIERS2_PROPERTY, pos);
+		}
 		
 		boolean isInterface= ((Boolean) getOriginalValue(node, TypeDeclaration.INTERFACE_PROPERTY)).booleanValue();
 		// modifiers & class/interface
@@ -1194,9 +1279,15 @@
 		// name
 		pos= rewriteRequiredNode(node, TypeDeclaration.NAME_PROPERTY);
 		
+		if (apiLevel >= AST.JLS3) {
+			pos= rewriteOptionalTypeParameters(node, TypeDeclaration.TYPE_PARAMETERS_PROPERTY, pos, " "); //$NON-NLS-1$
+		}
+		
 		// superclass
 		if (!isInterface || invertType) {
-			RewriteEvent superClassEvent= getEvent(node, TypeDeclaration.SUPERCLASS_PROPERTY);
+			ChildPropertyDescriptor superClassProperty= (apiLevel == AST.JLS2) ? TypeDeclaration.SUPERCLASS_PROPERTY : TypeDeclaration.SUPERCLASS_TYPE_PROPERTY;
+
+			RewriteEvent superClassEvent= getEvent(node, superClassProperty);
 			
 			int changeKind= superClassEvent != null ? superClassEvent.getChangeKind() : RewriteEvent.UNCHANGED;
 			switch (changeKind) {
@@ -1222,28 +1313,30 @@
 					break;
 				}
 				case RewriteEvent.UNCHANGED: {
-					pos= doVisit(node, TypeDeclaration.SUPERCLASS_PROPERTY, pos);
+					pos= doVisit(node, superClassProperty, pos);
 				}
 			}
 		}
 		// extended interfaces
-		RewriteEvent interfaceEvent= getEvent(node, TypeDeclaration.SUPER_INTERFACES_PROPERTY);
+		ChildListPropertyDescriptor superInterfaceProperty= (apiLevel == AST.JLS2) ? TypeDeclaration.SUPER_INTERFACES_PROPERTY : TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY;
+
+		RewriteEvent interfaceEvent= getEvent(node, superInterfaceProperty);
 		if (interfaceEvent == null || interfaceEvent.getChangeKind() == RewriteEvent.UNCHANGED) {
 			if (invertType) {
-				List originalNodes= (List) getOriginalValue(node, TypeDeclaration.SUPER_INTERFACES_PROPERTY);
+				List originalNodes= (List) getOriginalValue(node, superInterfaceProperty);
 				if (!originalNodes.isEmpty()) {
 					String keyword= isInterface ? " implements " : " extends "; //$NON-NLS-1$ //$NON-NLS-2$
 					ASTNode firstNode= (ASTNode) originalNodes.get(0);
 					doTextReplace(pos, firstNode.getStartPosition() - pos, keyword, getEditGroup(node, TypeDeclaration.INTERFACE_PROPERTY));
 				}
 			}
-			pos= doVisit(node, TypeDeclaration.SUPER_INTERFACES_PROPERTY, pos);
+			pos= doVisit(node, superInterfaceProperty, pos);
 		} else {
 			String keyword= (isInterface == invertType) ? " implements " : " extends "; //$NON-NLS-1$ //$NON-NLS-2$
 			if (invertType) {
-				List newNodes= (List) getNewValue(node, TypeDeclaration.SUPER_INTERFACES_PROPERTY);
+				List newNodes= (List) interfaceEvent.getNewValue();
 				if (!newNodes.isEmpty()) {
-					List origNodes= (List) getOriginalValue(node, TypeDeclaration.SUPER_INTERFACES_PROPERTY);
+					List origNodes= (List) interfaceEvent.getOriginalValue();
 					int firstStart= pos;
 					if (!origNodes.isEmpty()) {
 						firstStart= ((ASTNode) origNodes.get(0)).getStartPosition();
@@ -1253,7 +1346,7 @@
 					pos= firstStart;
 				}
 			}
-			pos= rewriteNodeList(node, TypeDeclaration.SUPER_INTERFACES_PROPERTY, pos, keyword, ", "); //$NON-NLS-1$
+			pos= rewriteNodeList(node, superInterfaceProperty, pos, keyword, ", "); //$NON-NLS-1$
 		}
 		
 		// type members
@@ -1264,37 +1357,29 @@
 		return false;
 	}
 
-
 	private void rewriteReturnType(MethodDeclaration node, boolean isConstructor, boolean isConstructorChange) {
-		// weakness in the AST: return type always exists, even if missing in source
-		ASTNode originalReturnType= (ASTNode) getOriginalValue(node, MethodDeclaration.RETURN_TYPE_PROPERTY);
+		ChildPropertyDescriptor property= (node.getAST().apiLevel() == AST.JLS2) ? MethodDeclaration.RETURN_TYPE_PROPERTY : MethodDeclaration.RETURN_TYPE2_PROPERTY;
+
+		// weakness in the AST: return type can exist, even if missing in source
+		ASTNode originalReturnType= (ASTNode) getOriginalValue(node, property);
 		boolean returnTypeExists=  originalReturnType != null && originalReturnType.getStartPosition() != -1;
 		if (!isConstructorChange && returnTypeExists) {
-			rewriteRequiredNode(node, MethodDeclaration.RETURN_TYPE_PROPERTY);
+			rewriteRequiredNode(node, property);
 			return;
 		}
-		ASTNode newReturnType= (ASTNode) getNewValue(node, MethodDeclaration.RETURN_TYPE_PROPERTY);
+		// difficult cases: return type insert or remove
+		ASTNode newReturnType= (ASTNode) getNewValue(node, property);
 		if (isConstructorChange || !returnTypeExists && newReturnType != originalReturnType) {
-			try {
-				int startPos= node.getStartPosition();
-				
-				getScanner().setOffset(startPos);
-				int token= getScanner().readNext(true);
-				while (TokenScanner.isModifier(token)) {
-					startPos= getScanner().getCurrentEndOffset();
-					token= getScanner().readNext(true);
-				}
-				
-				TextEditGroup editGroup= getEditGroup(node, MethodDeclaration.RETURN_TYPE_PROPERTY);
-				if (isConstructor || !returnTypeExists) { // insert
-					doTextInsert(startPos, " ", editGroup); //$NON-NLS-1$
-					doTextInsert(startPos, newReturnType, getIndent(startPos), true, editGroup);
-				} else { // remove
-					int len= getExtendedEnd(originalReturnType) - startPos;
-					doTextRemoveAndVisit(startPos, len, originalReturnType, editGroup);
-				}
-			} catch (CoreException e) {
-				handleException(e);
+			// use the start offset of the method name to insert
+			ASTNode originalMethodName= (ASTNode) getOriginalValue(node, MethodDeclaration.NAME_PROPERTY);
+			int nextStart= getExtendedOffset(originalMethodName);
+			TextEditGroup editGroup= getEditGroup(node, property);
+			if (isConstructor || !returnTypeExists) { // insert
+				doTextInsert(nextStart, newReturnType, getIndent(nextStart), true, editGroup);
+				doTextInsert(nextStart, " ", editGroup); //$NON-NLS-1$
+			} else { // remove up to the method name
+				int offset= getExtendedOffset(originalReturnType);
+				doTextRemoveAndVisit(offset, nextStart - offset, originalReturnType, editGroup);
 			}
 		}
 	}
@@ -1308,7 +1393,11 @@
 			return doVisitUnchangedChildren(node);
 		}
 		int pos= rewriteJavadoc(node, MethodDeclaration.JAVADOC_PROPERTY);
-		rewriteModifiers(node, MethodDeclaration.MODIFIERS_PROPERTY, pos);
+		if (node.getAST().apiLevel() == AST.JLS2) {
+			rewriteModifiers(node, MethodDeclaration.MODIFIERS_PROPERTY, pos);
+		} else {
+			rewriteModifiers2(node, MethodDeclaration.MODIFIERS2_PROPERTY, pos);
+		}
 		
 		boolean isConstructorChange= isChanged(node, MethodDeclaration.CONSTRUCTOR_PROPERTY);
 		boolean isConstructor= ((Boolean) getOriginalValue(node, MethodDeclaration.CONSTRUCTOR_PROPERTY)).booleanValue();
@@ -1658,9 +1747,22 @@
 			return doVisitUnchangedChildren(node);
 		}
 		
-		rewriteOptionalQualifier(node, ClassInstanceCreation.EXPRESSION_PROPERTY, node.getStartPosition());
-		
-		int pos= rewriteRequiredNode(node, ClassInstanceCreation.NAME_PROPERTY);
+		int pos= rewriteOptionalQualifier(node, ClassInstanceCreation.EXPRESSION_PROPERTY, node.getStartPosition());
+		if (node.getAST().apiLevel() == AST.JLS2) {
+			pos= rewriteRequiredNode(node, ClassInstanceCreation.NAME_PROPERTY);
+		} else {
+			if (isChanged(node, ClassInstanceCreation.TYPE_ARGUMENTS_PROPERTY)) {
+				try {
+					pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNamenew, pos); //after 'new'
+					rewriteOptionalTypeParameters(node, ClassInstanceCreation.TYPE_ARGUMENTS_PROPERTY, pos, " "); //$NON-NLS-1$
+				} catch (CoreException e) {
+					handleException(e);
+				}
+			} else {
+				doVisit(node, ClassInstanceCreation.TYPE_ARGUMENTS_PROPERTY, 0);
+			}
+			pos= rewriteRequiredNode(node, ClassInstanceCreation.TYPE_PROPERTY);
+		}
 
 		if (isChanged(node, ClassInstanceCreation.ARGUMENTS_PROPERTY)) {
 			try {
@@ -1708,10 +1810,13 @@
 		if (!hasChildrenChanges(node)) {
 			return doVisitUnchangedChildren(node);
 		}
-		
+		int pos= node.getStartPosition();
+		if (node.getAST().apiLevel() >= AST.JLS3) {
+			pos= rewriteOptionalTypeParameters(node, ConstructorInvocation.TYPE_ARGUMENTS_PROPERTY, pos, ""); //$NON-NLS-1$
+		}
 		try {
-			int startpos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameLPAREN, node.getStartPosition());
-			rewriteNodeList(node, ConstructorInvocation.ARGUMENTS_PROPERTY, startpos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+			pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameLPAREN, pos);
+			rewriteNodeList(node, ConstructorInvocation.ARGUMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
 		} catch (CoreException e) {
 			handleException(e);
 		}
@@ -1809,7 +1914,12 @@
 		}
 		int pos= rewriteJavadoc(node, FieldDeclaration.JAVADOC_PROPERTY);
 
-		rewriteModifiers(node, FieldDeclaration.MODIFIERS_PROPERTY, pos);
+		if (node.getAST().apiLevel() == AST.JLS2) {
+			rewriteModifiers(node, FieldDeclaration.MODIFIERS_PROPERTY, pos);
+		} else {
+			rewriteModifiers2(node, FieldDeclaration.MODIFIERS2_PROPERTY, pos);
+		}
+		
 		pos= rewriteRequiredNode(node, FieldDeclaration.TYPE_PROPERTY);
 		rewriteNodeList(node, FieldDeclaration.FRAGMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
 		return false;
@@ -1919,6 +2029,23 @@
 		if (!hasChildrenChanges(node)) {
 			return doVisitUnchangedChildren(node);
 		}
+		if (node.getAST().apiLevel() >= AST.JLS3) {
+			RewriteEvent event= getEvent(node, ImportDeclaration.STATIC_PROPERTY);
+			if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) {
+				boolean wasStatic= ((Boolean) event.getOriginalValue()).booleanValue();
+				int pos= node.getStartPosition();
+				if (wasStatic) {
+					try {
+						int endPos= getScanner().getTokenStartOffset(ITerminalSymbols.TokenNameimport, pos);
+						doTextRemove(pos, endPos - pos, getEditGroup(event));
+					} catch (CoreException e) {
+						handleException(e);
+					}
+				} else {
+					doTextInsert(pos, "static ", getEditGroup(event)); //$NON-NLS-1$
+				}
+			}
+		}
 		
 		int pos= rewriteRequiredNode(node, ImportDeclaration.NAME_PROPERTY);
 		
@@ -2000,7 +2127,11 @@
 			return doVisitUnchangedChildren(node);
 		}
 		int pos= rewriteJavadoc(node, Initializer.JAVADOC_PROPERTY);
-		rewriteModifiers(node, Initializer.MODIFIERS_PROPERTY, pos);
+		if (node.getAST().apiLevel() == AST.JLS2) {
+			rewriteModifiers(node, Initializer.MODIFIERS_PROPERTY, pos);
+		} else {
+			rewriteModifiers2(node, Initializer.MODIFIERS2_PROPERTY, pos);
+		}
 		rewriteRequiredNode(node, Initializer.BODY_PROPERTY);
 		return false;
 	}
@@ -2053,10 +2184,12 @@
 			return doVisitUnchangedChildren(node);
 		}
 		
-		rewriteOptionalQualifier(node, MethodInvocation.EXPRESSION_PROPERTY, node.getStartPosition());
+		int pos= rewriteOptionalQualifier(node, MethodInvocation.EXPRESSION_PROPERTY, node.getStartPosition());
+		if (node.getAST().apiLevel() >= AST.JLS3) {
+			pos= rewriteOptionalTypeParameters(node, MethodInvocation.TYPE_ARGUMENTS_PROPERTY, pos, " "); //$NON-NLS-1$
+		}
 
-		int pos= rewriteRequiredNode(node, MethodInvocation.NAME_PROPERTY);
-		
+		pos= rewriteRequiredNode(node, MethodInvocation.NAME_PROPERTY);
 		
 		if (isChanged(node, MethodInvocation.ARGUMENTS_PROPERTY)) {
 			// eval position after opening parent
@@ -2103,7 +2236,11 @@
 	public boolean visit(PackageDeclaration node) {
 		if (!hasChildrenChanges(node)) {
 			return doVisitUnchangedChildren(node);
-		}		
+		}
+		if (node.getAST().apiLevel() >= AST.JLS3) {
+			int pos= rewriteJavadoc(node, PackageDeclaration.JAVADOC_PROPERTY);
+			rewriteNodeList(node, PackageDeclaration.ANNOTATIONS_PROPERTY, pos, "", " "); //$NON-NLS-1$ //$NON-NLS-2$
+		}
 		
 		rewriteRequiredNode(node, PackageDeclaration.NAME_PROPERTY);
 		return false;
@@ -2205,10 +2342,29 @@
 		if (!hasChildrenChanges(node)) {
 			return doVisitUnchangedChildren(node);
 		}
+		int pos= node.getStartPosition();
+		if (node.getAST().apiLevel() == AST.JLS2) {
+			rewriteModifiers(node, SingleVariableDeclaration.MODIFIERS_PROPERTY, pos);
+		} else {
+			rewriteModifiers2(node, SingleVariableDeclaration.MODIFIERS2_PROPERTY, pos);
+		}
+		pos= rewriteRequiredNode(node, SingleVariableDeclaration.TYPE_PROPERTY);
+		if (node.getAST().apiLevel() >= AST.JLS3) {
+			if (isChanged(node, SingleVariableDeclaration.VARARGS_PROPERTY)) {
+				if (getNewValue(node, SingleVariableDeclaration.VARARGS_PROPERTY).equals(Boolean.TRUE)) {
+					doTextInsert(pos, "...", getEditGroup(node, SingleVariableDeclaration.VARARGS_PROPERTY)); //$NON-NLS-1$
+				} else {
+					try {
+						int ellipsisEnd= getScanner().getNextEndOffset(pos, true);
+						doTextRemove(pos, ellipsisEnd - pos, getEditGroup(node, SingleVariableDeclaration.VARARGS_PROPERTY)); //$NON-NLS-1$
+					} catch (CoreException e) {
+						handleException(e);
+					}
+				}
+			}
+		}
 		
-		rewriteModifiers(node, SingleVariableDeclaration.MODIFIERS_PROPERTY, node.getStartPosition());
-		rewriteRequiredNode(node, SingleVariableDeclaration.TYPE_PROPERTY);
-		int pos= rewriteRequiredNode(node, SingleVariableDeclaration.NAME_PROPERTY);
+		pos= rewriteRequiredNode(node, SingleVariableDeclaration.NAME_PROPERTY);
 		int extraDims= rewriteExtraDimensions(node, SingleVariableDeclaration.EXTRA_DIMENSIONS_PROPERTY, pos);
 		
 		if (extraDims > 0) {
@@ -2252,6 +2408,10 @@
 		
 		int pos= rewriteOptionalQualifier(node, SuperConstructorInvocation.EXPRESSION_PROPERTY, node.getStartPosition());
 
+		if (node.getAST().apiLevel() >= AST.JLS3) {
+			pos= rewriteOptionalTypeParameters(node, SuperConstructorInvocation.TYPE_ARGUMENTS_PROPERTY, pos, " "); //$NON-NLS-1$
+		}
+		
 		if (isChanged(node, SuperConstructorInvocation.ARGUMENTS_PROPERTY)) {
 			// eval position after opening parent
 			try {
@@ -2287,9 +2447,20 @@
 			return doVisitUnchangedChildren(node);
 		}
 		
-		rewriteOptionalQualifier(node, SuperMethodInvocation.QUALIFIER_PROPERTY, node.getStartPosition());
+		int pos= rewriteOptionalQualifier(node, SuperMethodInvocation.QUALIFIER_PROPERTY, node.getStartPosition());
 		
-		int pos= rewriteRequiredNode(node, SuperMethodInvocation.NAME_PROPERTY);
+		if (node.getAST().apiLevel() >= AST.JLS3) {
+			if (isChanged(node, SuperMethodInvocation.TYPE_ARGUMENTS_PROPERTY)) {
+				try {
+					pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameDOT, pos);
+					rewriteOptionalTypeParameters(node, SuperMethodInvocation.TYPE_ARGUMENTS_PROPERTY, pos, " "); //$NON-NLS-1$
+				} catch (CoreException e) {
+					handleException(e);
+				}
+			}
+		}
+		
+		pos= rewriteRequiredNode(node, SuperMethodInvocation.NAME_PROPERTY);
 		
 		if (isChanged(node, SuperMethodInvocation.ARGUMENTS_PROPERTY)) {
 			// eval position after opening parent
@@ -2434,8 +2605,11 @@
 		if (!hasChildrenChanges(node)) {
 			return doVisitUnchangedChildren(node);
 		}
-		
-		rewriteRequiredNode(node, TypeDeclarationStatement.TYPE_DECLARATION_PROPERTY);	
+		if (node.getAST().apiLevel() == AST.JLS2) {
+			rewriteRequiredNode(node, TypeDeclarationStatement.TYPE_DECLARATION_PROPERTY);	
+		} else {
+			rewriteRequiredNode(node, TypeDeclarationStatement.DECLARATION_PROPERTY);	
+		}
 		return false;
 	}
 
@@ -2460,8 +2634,13 @@
 		}
 		
 		// same code as FieldDeclaration
-		rewriteModifiers(node, VariableDeclarationExpression.MODIFIERS_PROPERTY, node.getStartPosition());		
-		int pos= rewriteRequiredNode(node, VariableDeclarationExpression.TYPE_PROPERTY);
+		int pos= node.getStartPosition();
+		if (node.getAST().apiLevel() == AST.JLS2) {
+			rewriteModifiers(node, VariableDeclarationExpression.MODIFIERS_PROPERTY, pos);
+		} else {
+			rewriteModifiers2(node, VariableDeclarationExpression.MODIFIERS2_PROPERTY, pos);
+		}
+		pos= rewriteRequiredNode(node, VariableDeclarationExpression.TYPE_PROPERTY);
 		rewriteNodeList(node, VariableDeclarationExpression.FRAGMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
 		return false;
 	}
@@ -2502,9 +2681,14 @@
 			return doVisitUnchangedChildren(node);
 		}
 		
-		// same code as FieldDeclaration		
-		rewriteModifiers(node, VariableDeclarationStatement.MODIFIERS_PROPERTY, node.getStartPosition());
-		int pos= rewriteRequiredNode(node, VariableDeclarationStatement.TYPE_PROPERTY);
+		// same code as FieldDeclaration
+		int pos= node.getStartPosition();
+		if (node.getAST().apiLevel() == AST.JLS2) {
+			rewriteModifiers(node, VariableDeclarationStatement.MODIFIERS_PROPERTY, pos);
+		} else {
+			rewriteModifiers2(node, VariableDeclarationStatement.MODIFIERS2_PROPERTY, pos);
+		}
+		pos= rewriteRequiredNode(node, VariableDeclarationStatement.TYPE_PROPERTY);
 		
 		rewriteNodeList(node, VariableDeclarationStatement.FRAGMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
 		return false;
@@ -2657,6 +2841,312 @@
 		return false;
 	}
 
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnnotationTypeDeclaration)
+	 */
+	public boolean visit(AnnotationTypeDeclaration node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		int pos= rewriteJavadoc(node, AnnotationTypeDeclaration.JAVADOC_PROPERTY);
+		rewriteModifiers2(node, AnnotationTypeDeclaration.MODIFIERS2_PROPERTY, pos);
+		pos= rewriteRequiredNode(node, AnnotationTypeDeclaration.NAME_PROPERTY);
+		
+		int startIndent= getIndent(node.getStartPosition()) + 1;
+		int startPos= getPosAfterLeftBrace(pos);
+		rewriteParagraphList(node, AnnotationTypeDeclaration.BODY_DECLARATIONS_PROPERTY, startPos, startIndent, -1, 2);
+		return false;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration)
+	 */
+	public boolean visit(AnnotationTypeMemberDeclaration node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		int pos= rewriteJavadoc(node, AnnotationTypeMemberDeclaration.JAVADOC_PROPERTY);
+		rewriteModifiers2(node, AnnotationTypeMemberDeclaration.MODIFIERS2_PROPERTY, pos);
+		rewriteRequiredNode(node, AnnotationTypeMemberDeclaration.TYPE_PROPERTY);
+		pos= rewriteRequiredNode(node, AnnotationTypeMemberDeclaration.NAME_PROPERTY);
+		
+		try {
+			int changeKind= getChangeKind(node, AnnotationTypeMemberDeclaration.DEFAULT_PROPERTY);
+			if (changeKind == RewriteEvent.INSERTED || changeKind == RewriteEvent.REMOVED) {
+				pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameRPAREN, pos);
+			}
+			rewriteNode(node, AnnotationTypeMemberDeclaration.DEFAULT_PROPERTY, pos, this.formatter.ANNOT_MEMBER_DEFAULT);
+		} catch (CoreException e) {
+			handleException(e);
+		}
+		return false;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnhancedForStatement)
+	 */
+	public boolean visit(EnhancedForStatement node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		rewriteRequiredNode(node, EnhancedForStatement.PARAMETER_PROPERTY);
+		int pos= rewriteRequiredNode(node, EnhancedForStatement.EXPRESSION_PROPERTY);
+
+		RewriteEvent bodyEvent= getEvent(node, EnhancedForStatement.BODY_PROPERTY);
+		if (bodyEvent != null && bodyEvent.getChangeKind() == RewriteEvent.REPLACED) {
+			int startOffset;
+			try {
+				startOffset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameRPAREN, pos);
+				rewriteBodyNode(node, EnhancedForStatement.BODY_PROPERTY, startOffset, -1, getIndent(node.getStartPosition()), this.formatter.FOR_BLOCK); // body
+			} catch (CoreException e) {
+				handleException(e);
+			}
+		} else {
+			doVisit(node, EnhancedForStatement.BODY_PROPERTY, 0);
+		}
+		return false;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnumConstantDeclaration)
+	 */
+	public boolean visit(EnumConstantDeclaration node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		int pos= rewriteJavadoc(node, EnumConstantDeclaration.JAVADOC_PROPERTY);
+		rewriteModifiers2(node, EnumConstantDeclaration.MODIFIERS2_PROPERTY, pos);
+		pos= rewriteRequiredNode(node, EnumConstantDeclaration.NAME_PROPERTY);
+		RewriteEvent argsEvent= getEvent(node, EnumConstantDeclaration.ARGUMENTS_PROPERTY);
+		if (argsEvent != null && argsEvent.getChangeKind() != RewriteEvent.UNCHANGED) {
+			RewriteEvent[] children= argsEvent.getChildren();
+			try {
+				int nextTok= getScanner().readNext(pos, true);
+				boolean hasParents= (nextTok == ITerminalSymbols.TokenNameLPAREN);
+				boolean isAllRemoved= hasParents && isAllOfKind(children, RewriteEvent.REMOVED);
+				String prefix= ""; //$NON-NLS-1$
+				if (!hasParents) {
+					prefix= "("; //$NON-NLS-1$
+				} else if (!isAllRemoved) {
+					pos= getScanner().getCurrentEndOffset();
+				}
+				pos= rewriteNodeList(node, EnumConstantDeclaration.ARGUMENTS_PROPERTY, pos, prefix, ", "); //$NON-NLS-1$ //$NON-NLS-2$
+				
+				if (!hasParents) {
+					doTextInsert(pos, ")", getEditGroup(children[children.length - 1])); //$NON-NLS-1$
+				} else if (isAllRemoved) {
+					int afterClosing= getScanner().getNextEndOffset(pos, true);
+					doTextRemove(pos, afterClosing - pos, getEditGroup(children[children.length - 1]));
+					pos= afterClosing;
+				}
+			} catch (CoreException e) {
+				handleException(e);
+			}
+		} else {
+			pos= doVisit(node, EnumConstantDeclaration.ARGUMENTS_PROPERTY, 0);
+		}
+		
+		if (isChanged(node, EnumConstantDeclaration.ANONYMOUS_CLASS_DECLARATION_PROPERTY)) {
+			int kind= getChangeKind(node, EnumConstantDeclaration.ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+			if (kind == RewriteEvent.REMOVED) {
+				try {
+					// 'pos' can be before brace
+					pos= getScanner().getPreviousTokenEndOffset(ITerminalSymbols.TokenNameLBRACE, pos);
+				} catch (CoreException e) {
+					handleException(e);
+				}
+			} else {
+				pos= node.getStartPosition() + node.getLength(); // insert pos
+			}
+			rewriteNode(node, EnumConstantDeclaration.ANONYMOUS_CLASS_DECLARATION_PROPERTY, pos, ASTRewriteFormatter.SPACE); //$NON-NLS-1$
+		}
+		return false;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnumDeclaration)
+	 */
+	public boolean visit(EnumDeclaration node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		int pos= rewriteJavadoc(node, EnumDeclaration.JAVADOC_PROPERTY);
+		rewriteModifiers2(node, EnumDeclaration.MODIFIERS2_PROPERTY, pos);
+		pos= rewriteRequiredNode(node, EnumDeclaration.NAME_PROPERTY);
+		rewriteNodeList(node, EnumDeclaration.SUPER_INTERFACE_TYPES_PROPERTY, pos, " implements ", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+		
+		pos= rewriteNodeList(node, EnumDeclaration.ENUM_CONSTANTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+
+		RewriteEvent bodyEvent= getEvent(node, EnumDeclaration.BODY_DECLARATIONS_PROPERTY);
+		int indent= 0;
+		if (bodyEvent != null && bodyEvent.getChangeKind() != RewriteEvent.UNCHANGED) {
+			RewriteEvent[] children= bodyEvent.getChildren();
+			try {
+				int token= getScanner().readNext(pos, true);
+				boolean hasSemicolon= token == ITerminalSymbols.TokenNameSEMICOLON;
+				if (!hasSemicolon && isAllOfKind(children, RewriteEvent.INSERTED)) {
+					doTextInsert(pos, ";", getEditGroup(children[0])); //$NON-NLS-1$
+				} else if (hasSemicolon) {
+					int endPos= getScanner().getCurrentEndOffset();
+					if (isAllOfKind(children, RewriteEvent.REMOVED)) {
+						doTextRemove(pos, endPos - pos, getEditGroup(children[0])); //$NON-NLS-1$
+					}
+					pos= endPos;
+				}
+				indent= getIndent(pos);
+			} catch (CoreException e) {
+				handleException(e);
+			}
+		}
+		rewriteParagraphList(node, EnumDeclaration.BODY_DECLARATIONS_PROPERTY, pos, indent, -1, 2);
+		return false;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MarkerAnnotation)
+	 */
+	public boolean visit(MarkerAnnotation node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		rewriteRequiredNode(node, MarkerAnnotation.TYPE_NAME_PROPERTY);
+		return false;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MemberValuePair)
+	 */
+	public boolean visit(MemberValuePair node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		rewriteRequiredNode(node, MemberValuePair.NAME_PROPERTY);
+		rewriteRequiredNode(node, MemberValuePair.VALUE_PROPERTY);
+
+		return false;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Modifier)
+	 */
+	public boolean visit(Modifier node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		String newText= getNewValue(node, Modifier.KEYWORD_PROPERTY).toString(); // type Modifier.ModifierKeyword
+		TextEditGroup group = getEditGroup(node, Modifier.KEYWORD_PROPERTY);
+		doTextReplace(node.getStartPosition(), node.getLength(), newText, group);
+		return false;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.NormalAnnotation)
+	 */
+	public boolean visit(NormalAnnotation node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		int pos= rewriteRequiredNode(node, NormalAnnotation.TYPE_NAME_PROPERTY);
+		if (isChanged(node, NormalAnnotation.VALUES_PROPERTY)) {
+			// eval position after opening parent
+			try {
+				int startOffset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameLESS, pos);
+				rewriteNodeList(node, NormalAnnotation.VALUES_PROPERTY, startOffset, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+			} catch (CoreException e) {
+				handleException(e);
+			}
+		} else {
+			doVisit(node, NormalAnnotation.VALUES_PROPERTY, 0);
+		}
+		return false;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ParameterizedType)
+	 */
+	public boolean visit(ParameterizedType node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		int pos= rewriteRequiredNode(node, ParameterizedType.TYPE_PROPERTY);
+		if (isChanged(node, ParameterizedType.TYPE_ARGUMENTS_PROPERTY)) {
+			// eval position after opening parent
+			try {
+				int startOffset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameLESS, pos);
+				rewriteNodeList(node, ParameterizedType.TYPE_ARGUMENTS_PROPERTY, startOffset, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+			} catch (CoreException e) {
+				handleException(e);
+			}
+		} else {
+			doVisit(node, ParameterizedType.TYPE_ARGUMENTS_PROPERTY, 0);
+		}
+		return false;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.QualifiedType)
+	 */
+	public boolean visit(QualifiedType node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		rewriteRequiredNode(node, QualifiedType.QUALIFIER_PROPERTY);
+		rewriteRequiredNode(node, QualifiedType.NAME_PROPERTY);
+		return false;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SingleMemberAnnotation)
+	 */
+	public boolean visit(SingleMemberAnnotation node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		rewriteRequiredNode(node, SingleMemberAnnotation.TYPE_NAME_PROPERTY);
+		rewriteRequiredNode(node, SingleMemberAnnotation.VALUE_PROPERTY);
+		return false;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeParameter)
+	 */
+	public boolean visit(TypeParameter node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		int pos= rewriteRequiredNode(node, TypeParameter.NAME_PROPERTY);
+		if (isChanged(node, TypeParameter.TYPE_BOUNDS_PROPERTY)) {
+			rewriteNodeList(node, TypeParameter.TYPE_BOUNDS_PROPERTY, pos, " extends ", " & "); //$NON-NLS-1$ //$NON-NLS-2$
+		} else {
+			doVisit(node, TypeParameter.TYPE_BOUNDS_PROPERTY, 0);
+		}
+		return false;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.WildcardType)
+	 */
+	public boolean visit(WildcardType node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		try {
+			int pos= getScanner().getNextEndOffset(node.getStartPosition(), true); // pos after question mark
+			
+			Prefix prefix;
+			if (Boolean.TRUE.equals(getNewValue(node, WildcardType.UPPER_BOUND_PROPERTY))) {
+				prefix= this.formatter.WILDCARD_EXTENDS;
+			} else {
+				prefix= this.formatter.WILDCARD_SUPER;
+			}
+			
+			int boundKindChange= getChangeKind(node, WildcardType.UPPER_BOUND_PROPERTY);
+			if (boundKindChange != RewriteEvent.UNCHANGED) {
+				int boundTypeChange= getChangeKind(node, WildcardType.BOUND_PROPERTY);
+				if (boundTypeChange != RewriteEvent.INSERTED && boundTypeChange != RewriteEvent.REMOVED) {
+					ASTNode type= (ASTNode) getOriginalValue(node, WildcardType.BOUND_PROPERTY);
+					String str= prefix.getPrefix(0, getLineDelimiter());
+					doTextReplace(pos, type.getStartPosition() - pos, str, getEditGroup(node, WildcardType.BOUND_PROPERTY));
+				}
+			}
+			rewriteNode(node, WildcardType.BOUND_PROPERTY, pos, prefix);
+		} catch (CoreException e) {
+			handleException(e);
+		}
+		return false;
+	}
+	
 	final void handleException(Throwable e) {
 		IllegalArgumentException runtimeException= new IllegalArgumentException("Document does not match the AST"); //$NON-NLS-1$
 		runtimeException.initCause(e);
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java
index 7544090..69bc159 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java
@@ -12,18 +12,17 @@
 
 import java.util.List;
 
-import org.eclipse.jface.text.Assert;
-
 import org.eclipse.jdt.core.dom.*;
 
-public class ASTRewriteFlattener extends GenericVisitor {
-
+public class ASTRewriteFlattener extends ASTVisitor {
+	
 	public static String asString(ASTNode node, RewriteEventStore store) {
 		ASTRewriteFlattener flattener= new ASTRewriteFlattener(store);
 		node.accept(flattener);
 		return flattener.getResult();
 	}
 	
+	private final String EMPTY= ""; //$NON-NLS-1$
 	protected StringBuffer result;
 	private RewriteEventStore store;
 
@@ -48,11 +47,6 @@
 	public void reset() {
 		this.result.setLength(0);
 	}
-
-	protected boolean visitNode(ASTNode node) {
-		Assert.isTrue(false, "No implementation to flatten node: " + node.toString());  //$NON-NLS-1$
-		return false;
-	}
 	
 	/**
 	 * Appends the text representation of the given modifier flags, followed by a single space.
@@ -95,7 +89,7 @@
 			buf.append("transient "); //$NON-NLS-1$
 		}
 	}
-	
+		
 	protected List getChildList(ASTNode parent, StructuralPropertyDescriptor childProperty) {
 		return (List) getAttribute(parent, childProperty);
 	}
@@ -126,7 +120,7 @@
 		}
 	}
 	
-	protected void visitList(ASTNode parent, StructuralPropertyDescriptor childProperty, String separator, String lead) {
+	protected void visitList(ASTNode parent, StructuralPropertyDescriptor childProperty, String separator, String lead, String post) {
 		List list= getChildList(parent, childProperty);
 		if (!list.isEmpty()) {
 			this.result.append(lead);
@@ -136,6 +130,7 @@
 				}
 				((ASTNode) list.get(i)).accept(this);
 			}
+			this.result.append(post);
 		}
 	}
 	
@@ -319,8 +314,14 @@
 			expression.accept(this);
 			this.result.append('.');
 		}
-		this.result.append("new "); //$NON-NLS-1$
-		getChildNode(node, ClassInstanceCreation.NAME_PROPERTY).accept(this);
+		this.result.append("new ");//$NON-NLS-1$
+		if (node.getAST().apiLevel() == AST.JLS2) {
+			getChildNode(node, ClassInstanceCreation.NAME_PROPERTY).accept(this);
+		} else {
+			visitList(node, ClassInstanceCreation.TYPE_ARGUMENTS_PROPERTY, String.valueOf(','), String.valueOf('<'), String.valueOf('>'));
+			getChildNode(node, ClassInstanceCreation.TYPE_PROPERTY).accept(this);
+		}
+
 		this.result.append('(');
 		visitList(node, ClassInstanceCreation.ARGUMENTS_PROPERTY, String.valueOf(','));
 		this.result.append(')');
@@ -360,6 +361,9 @@
 	 * @see ASTVisitor#visit(ConstructorInvocation)
 	 */
 	public boolean visit(ConstructorInvocation node) {
+		if (node.getAST().apiLevel() >= AST.JLS3) {
+			visitList(node, ConstructorInvocation.TYPE_ARGUMENTS_PROPERTY, String.valueOf(','), String.valueOf('<'), String.valueOf('>'));
+		}
 		this.result.append("this("); //$NON-NLS-1$
 		visitList(node, ConstructorInvocation.ARGUMENTS_PROPERTY, String.valueOf(','));
 		this.result.append(");"); //$NON-NLS-1$
@@ -427,7 +431,11 @@
 		if (javadoc != null) {
 			javadoc.accept(this);
 		}
-		printModifiers(getIntAttribute(node, FieldDeclaration.MODIFIERS_PROPERTY), this.result);
+		if (node.getAST().apiLevel() == AST.JLS2) {
+			printModifiers(getIntAttribute(node, FieldDeclaration.MODIFIERS_PROPERTY), this.result);
+		} else {
+			visitList(node, FieldDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), EMPTY, String.valueOf(' '));
+		}
 		getChildNode(node, FieldDeclaration.TYPE_PROPERTY).accept(this);
 		this.result.append(' ');
 		visitList(node, FieldDeclaration.FRAGMENTS_PROPERTY, String.valueOf(','));
@@ -474,6 +482,11 @@
 	 */
 	public boolean visit(ImportDeclaration node) {
 		this.result.append("import "); //$NON-NLS-1$
+		if (node.getAST().apiLevel() >= AST.JLS3) {
+			if (getBooleanAttribute(node, ImportDeclaration.STATIC_PROPERTY)) {
+				this.result.append("static ");//$NON-NLS-1$
+			}
+		}
 		getChildNode(node, ImportDeclaration.NAME_PROPERTY).accept(this);
 		if (getBooleanAttribute(node, ImportDeclaration.ON_DEMAND_PROPERTY)) {
 			this.result.append(".*"); //$NON-NLS-1$
@@ -522,7 +535,11 @@
 		if (javadoc != null) {
 			javadoc.accept(this);
 		}
-		printModifiers(getIntAttribute(node, Initializer.MODIFIERS_PROPERTY), this.result);
+		if (node.getAST().apiLevel() == AST.JLS2) {
+			printModifiers(getIntAttribute(node, Initializer.MODIFIERS_PROPERTY), this.result);
+		} else {
+			visitList(node, Initializer.MODIFIERS2_PROPERTY, String.valueOf(' '), EMPTY, String.valueOf(' '));
+		}
 		getChildNode(node, Initializer.BODY_PROPERTY).accept(this);
 		return false;
 	}
@@ -559,9 +576,25 @@
 		if (javadoc != null) {
 			javadoc.accept(this);
 		}
-		printModifiers(getIntAttribute(node, MethodDeclaration.MODIFIERS_PROPERTY), this.result);
+		if (node.getAST().apiLevel() == AST.JLS2) {
+			printModifiers(getIntAttribute(node, MethodDeclaration.MODIFIERS_PROPERTY), this.result);
+		} else {
+			visitList(node, MethodDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), EMPTY, String.valueOf(' '));
+			visitList(node, MethodDeclaration.TYPE_PARAMETERS_PROPERTY, String.valueOf(','), String.valueOf('<'), String.valueOf('>'));
+		}
+				
 		if (!getBooleanAttribute(node, MethodDeclaration.CONSTRUCTOR_PROPERTY)) {
-			getChildNode(node, MethodDeclaration.RETURN_TYPE_PROPERTY).accept(this);
+			if (node.getAST().apiLevel() == AST.JLS2) {
+				getChildNode(node, MethodDeclaration.RETURN_TYPE_PROPERTY).accept(this);
+			} else {
+				ASTNode returnType = getChildNode(node, MethodDeclaration.RETURN_TYPE2_PROPERTY);
+				if (returnType != null) {
+					returnType.accept(this);
+				} else {
+					// methods really ought to have a return type
+					this.result.append("void");//$NON-NLS-1$
+				}
+			}
 			this.result.append(' ');
 		}
 		getChildNode(node, MethodDeclaration.NAME_PROPERTY).accept(this);
@@ -572,7 +605,7 @@
 		for (int i = 0; i < extraDims; i++) {
 			this.result.append("[]"); //$NON-NLS-1$
 		}		
-		visitList(node, MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY, String.valueOf(','), " throws "); //$NON-NLS-1$
+		visitList(node, MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY, String.valueOf(','), " throws ", EMPTY); //$NON-NLS-1$
 		ASTNode body= getChildNode(node, MethodDeclaration.BODY_PROPERTY);
 		if (body == null) {
 			this.result.append(';');
@@ -591,6 +624,10 @@
 			expression.accept(this);
 			this.result.append('.');
 		}
+		if (node.getAST().apiLevel() >= AST.JLS3) {
+			visitList(node, MethodInvocation.TYPE_ARGUMENTS_PROPERTY, String.valueOf(','), String.valueOf('<'), String.valueOf('>'));
+		}
+
 		getChildNode(node, MethodInvocation.NAME_PROPERTY).accept(this);
 		this.result.append('(');
 		visitList(node, MethodInvocation.ARGUMENTS_PROPERTY, String.valueOf(','));
@@ -618,6 +655,13 @@
 	 * @see ASTVisitor#visit(PackageDeclaration)
 	 */
 	public boolean visit(PackageDeclaration node) {
+		if (node.getAST().apiLevel() >= AST.JLS3) {
+			ASTNode javadoc = getChildNode(node, PackageDeclaration.JAVADOC_PROPERTY);
+			if (javadoc != null) {
+				javadoc.accept(this);
+			}
+			visitList(node, PackageDeclaration.ANNOTATIONS_PROPERTY, String.valueOf(' '));
+		}
 		this.result.append("package "); //$NON-NLS-1$
 		getChildNode(node, PackageDeclaration.NAME_PROPERTY).accept(this);
 		this.result.append(';');
@@ -703,8 +747,17 @@
 	 * @see ASTVisitor#visit(SingleVariableDeclaration)
 	 */
 	public boolean visit(SingleVariableDeclaration node) {
-		printModifiers(getIntAttribute(node, SingleVariableDeclaration.MODIFIERS_PROPERTY), this.result);
+		if (node.getAST().apiLevel() == AST.JLS2) {
+			printModifiers(getIntAttribute(node, SingleVariableDeclaration.MODIFIERS_PROPERTY), this.result);
+		} else {
+			visitList(node, SingleVariableDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), EMPTY, String.valueOf(' '));
+		}
 		getChildNode(node, SingleVariableDeclaration.TYPE_PROPERTY).accept(this);
+		if (node.getAST().apiLevel() >= AST.JLS3) {
+			if (getBooleanAttribute(node, SingleVariableDeclaration.VARARGS_PROPERTY)) {
+				this.result.append("...");//$NON-NLS-1$
+			}
+		}
 		this.result.append(' ');
 		getChildNode(node, SingleVariableDeclaration.NAME_PROPERTY).accept(this);
 		int extraDimensions= getIntAttribute(node, SingleVariableDeclaration.EXTRA_DIMENSIONS_PROPERTY);
@@ -736,6 +789,9 @@
 			expression.accept(this);
 			this.result.append('.');
 		}
+		if (node.getAST().apiLevel() >= AST.JLS3) {
+			visitList(node, SuperConstructorInvocation.TYPE_ARGUMENTS_PROPERTY, String.valueOf(','), String.valueOf('<'), String.valueOf('>'));
+		}
 		this.result.append("super("); //$NON-NLS-1$
 		visitList(node, SuperConstructorInvocation.ARGUMENTS_PROPERTY, String.valueOf(','));
 		this.result.append(");"); //$NON-NLS-1$
@@ -766,6 +822,9 @@
 			this.result.append('.');
 		}
 		this.result.append("super."); //$NON-NLS-1$
+		if (node.getAST().apiLevel() >= AST.JLS3) {
+			visitList(node, SuperMethodInvocation.TYPE_ARGUMENTS_PROPERTY, String.valueOf(','), String.valueOf('<'), String.valueOf('>'));
+		}
 		getChildNode(node, SuperMethodInvocation.NAME_PROPERTY).accept(this);
 		this.result.append('(');
 		visitList(node, SuperMethodInvocation.ARGUMENTS_PROPERTY, String.valueOf(','));
@@ -855,25 +914,39 @@
 	 * @see ASTVisitor#visit(TypeDeclaration)
 	 */
 	public boolean visit(TypeDeclaration node) {
+		int apiLevel= node.getAST().apiLevel();
+		
 		ASTNode javadoc= getChildNode(node, TypeDeclaration.JAVADOC_PROPERTY);
 		if (javadoc != null) {
 			javadoc.accept(this);
 		}
-		printModifiers(getIntAttribute(node, TypeDeclaration.MODIFIERS_PROPERTY), this.result);
-		
+
+		if (apiLevel == AST.JLS2) {
+			printModifiers(getIntAttribute(node, TypeDeclaration.MODIFIERS_PROPERTY), this.result);
+		} else {
+			visitList(node, TypeDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), EMPTY, String.valueOf(' '));
+		}
+	
 		boolean isInterface= getBooleanAttribute(node, TypeDeclaration.INTERFACE_PROPERTY);
 		this.result.append(isInterface ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
 		getChildNode(node, TypeDeclaration.NAME_PROPERTY).accept(this);
+		if (apiLevel >= AST.JLS3) {
+			visitList(node, TypeDeclaration.TYPE_PARAMETERS_PROPERTY, String.valueOf(','), String.valueOf('<'), String.valueOf('>'));
+		}
+
 		this.result.append(' ');
-		ASTNode superclass= getChildNode(node, TypeDeclaration.SUPERCLASS_PROPERTY);
+		
+		ChildPropertyDescriptor superClassProperty= (apiLevel == AST.JLS2) ? TypeDeclaration.SUPERCLASS_PROPERTY : TypeDeclaration.SUPERCLASS_TYPE_PROPERTY;
+		ASTNode superclass= getChildNode(node, superClassProperty);
 		if (superclass != null) {
 			this.result.append("extends "); //$NON-NLS-1$
 			superclass.accept(this);
 			this.result.append(' ');
 		}
 		
+		ChildListPropertyDescriptor superInterfaceProperty= (apiLevel == AST.JLS2) ? TypeDeclaration.SUPER_INTERFACES_PROPERTY : TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY;
 		String lead= isInterface ? "extends " : "implements ";  //$NON-NLS-1$//$NON-NLS-2$
-		visitList(node, TypeDeclaration.SUPER_INTERFACES_PROPERTY, String.valueOf(','), lead);
+		visitList(node, superInterfaceProperty, String.valueOf(','), lead, EMPTY);
 		this.result.append('{');
 		visitList(node, TypeDeclaration.BODY_DECLARATIONS_PROPERTY, null);
 		this.result.append('}');
@@ -884,7 +957,11 @@
 	 * @see ASTVisitor#visit(TypeDeclarationStatement)
 	 */
 	public boolean visit(TypeDeclarationStatement node) {
-		getChildNode(node, TypeDeclarationStatement.TYPE_DECLARATION_PROPERTY).accept(this);
+		if (node.getAST().apiLevel() == AST.JLS2) {
+			getChildNode(node, TypeDeclarationStatement.TYPE_DECLARATION_PROPERTY).accept(this);
+		} else {
+			getChildNode(node, TypeDeclarationStatement.DECLARATION_PROPERTY).accept(this);
+		}
 		return false;
 	}
 
@@ -901,7 +978,11 @@
 	 * @see ASTVisitor#visit(VariableDeclarationExpression)
 	 */
 	public boolean visit(VariableDeclarationExpression node) {
-		printModifiers(getIntAttribute(node, VariableDeclarationExpression.MODIFIERS_PROPERTY), this.result);
+		if (node.getAST().apiLevel() == AST.JLS2) {
+			printModifiers(getIntAttribute(node, VariableDeclarationExpression.MODIFIERS_PROPERTY), this.result);
+		} else {
+			visitList(node, VariableDeclarationExpression.MODIFIERS2_PROPERTY, String.valueOf(' '), EMPTY, String.valueOf(' '));
+		}
 		getChildNode(node, VariableDeclarationExpression.TYPE_PROPERTY).accept(this);
 		this.result.append(' ');
 		visitList(node, VariableDeclarationExpression.FRAGMENTS_PROPERTY, String.valueOf(','));
@@ -929,7 +1010,11 @@
 	 * @see ASTVisitor#visit(VariableDeclarationStatement)
 	 */
 	public boolean visit(VariableDeclarationStatement node) {
-		printModifiers(getIntAttribute(node, VariableDeclarationStatement.MODIFIERS_PROPERTY), this.result);
+		if (node.getAST().apiLevel() == AST.JLS2) {
+			printModifiers(getIntAttribute(node, VariableDeclarationStatement.MODIFIERS_PROPERTY), this.result);
+		} else {
+			visitList(node, VariableDeclarationStatement.MODIFIERS2_PROPERTY, String.valueOf(' '), EMPTY, String.valueOf(' '));
+		}
 		getChildNode(node, VariableDeclarationStatement.TYPE_PROPERTY).accept(this);
 		this.result.append(' ');
 		visitList(node, VariableDeclarationStatement.FRAGMENTS_PROPERTY, String.valueOf(','));
@@ -1031,4 +1116,200 @@
 		this.result.append(getAttribute(node, TextElement.TEXT_PROPERTY));
 		return false;
 	}
+	/*
+	 * @see ASTVisitor#visit(AnnotationTypeDeclaration)
+	 * @since 3.0
+	 */
+	public boolean visit(AnnotationTypeDeclaration node) {
+		ASTNode javadoc= getChildNode(node, AnnotationTypeDeclaration.JAVADOC_PROPERTY);
+		if (javadoc != null) {
+			javadoc.accept(this);
+		}
+		visitList(node, AnnotationTypeDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), EMPTY, String.valueOf(' '));
+		this.result.append("@interface ");//$NON-NLS-1$
+		getChildNode(node, AnnotationTypeDeclaration.NAME_PROPERTY).accept(this);
+		this.result.append('{');
+		visitList(node, AnnotationTypeDeclaration.BODY_DECLARATIONS_PROPERTY, EMPTY); 
+		this.result.append('}');
+		return false;
+	}
+	
+	/*
+	 * @see ASTVisitor#visit(AnnotationTypeMemberDeclaration)
+	 * @since 3.0
+	 */
+	public boolean visit(AnnotationTypeMemberDeclaration node) {
+		ASTNode javadoc= getChildNode(node, AnnotationTypeMemberDeclaration.JAVADOC_PROPERTY);
+		if (javadoc != null) {
+			javadoc.accept(this);
+		}
+		visitList(node, AnnotationTypeMemberDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), EMPTY, String.valueOf(' '));
+		getChildNode(node, AnnotationTypeMemberDeclaration.TYPE_PROPERTY).accept(this);
+		this.result.append(' ');
+		getChildNode(node, AnnotationTypeMemberDeclaration.NAME_PROPERTY).accept(this);
+		this.result.append("()");//$NON-NLS-1$
+		ASTNode def= getChildNode(node, AnnotationTypeMemberDeclaration.DEFAULT_PROPERTY);
+		if (def != null) {
+			this.result.append(" default ");//$NON-NLS-1$
+			def.accept(this);
+		}
+		this.result.append(';');
+		return false;
+	}
+
+	/*
+	 * @see ASTVisitor#visit(EnhancedForStatement)
+	 * @since 3.0
+	 */
+	public boolean visit(EnhancedForStatement node) {
+		this.result.append("for (");//$NON-NLS-1$
+		getChildNode(node, EnhancedForStatement.PARAMETER_PROPERTY).accept(this);
+		this.result.append(':');
+		getChildNode(node, EnhancedForStatement.EXPRESSION_PROPERTY).accept(this);
+		this.result.append(')');
+		getChildNode(node, EnhancedForStatement.BODY_PROPERTY).accept(this);
+		return false;
+	}
+
+	/*
+	 * @see ASTVisitor#visit(EnumConstantDeclaration)
+	 * @since 3.0
+	 */
+	public boolean visit(EnumConstantDeclaration node) {
+		ASTNode javadoc= getChildNode(node, EnumConstantDeclaration.JAVADOC_PROPERTY);
+		if (javadoc != null) {
+			javadoc.accept(this);
+		}
+		visitList(node, EnumConstantDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), EMPTY, String.valueOf(' '));
+		getChildNode(node, EnumConstantDeclaration.NAME_PROPERTY).accept(this);
+		visitList(node, EnumConstantDeclaration.ARGUMENTS_PROPERTY, String.valueOf(','), String.valueOf('('), String.valueOf(')'));
+		ASTNode classDecl= getChildNode(node, EnumConstantDeclaration.ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+		if (classDecl != null) {
+			classDecl.accept(this);
+		}
+		return false;
+	}
+
+	/*
+	 * @see ASTVisitor#visit(EnumDeclaration)
+	 * @since 3.0
+	 */
+	public boolean visit(EnumDeclaration node) {
+		ASTNode javadoc= getChildNode(node, EnumDeclaration.JAVADOC_PROPERTY);
+		if (javadoc != null) {
+			javadoc.accept(this);
+		}
+		visitList(node, EnumDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), EMPTY, String.valueOf(' '));
+		this.result.append("enum ");//$NON-NLS-1$
+		getChildNode(node, EnumDeclaration.NAME_PROPERTY).accept(this);
+		this.result.append(' ');
+		visitList(node, EnumDeclaration.SUPER_INTERFACE_TYPES_PROPERTY, String.valueOf(','), "implements ", EMPTY); //$NON-NLS-1$
+
+		this.result.append('{');
+		visitList(node, EnumDeclaration.ENUM_CONSTANTS_PROPERTY, String.valueOf(','), EMPTY, EMPTY); //$NON-NLS-1$
+		visitList(node, EnumDeclaration.BODY_DECLARATIONS_PROPERTY, EMPTY, String.valueOf(';'), EMPTY); //$NON-NLS-1$
+		this.result.append('}');
+		return false;
+	}
+	/*
+	 * @see ASTVisitor#visit(MarkerAnnotation)
+	 * @since 3.0
+	 */
+	public boolean visit(MarkerAnnotation node) {
+		this.result.append('@');
+		getChildNode(node, MarkerAnnotation.TYPE_NAME_PROPERTY).accept(this);
+		return false;
+	}
+	
+	/*
+	 * @see ASTVisitor#visit(MemberValuePair)
+	 * @since 3.0
+	 */
+	public boolean visit(MemberValuePair node) {
+		getChildNode(node, MemberValuePair.NAME_PROPERTY).accept(this);
+		this.result.append('=');
+		getChildNode(node, MemberValuePair.VALUE_PROPERTY).accept(this);
+		return false;
+	}
+	/*
+	 * @see ASTVisitor#visit(Modifier)
+	 * @since 3.0
+	 */
+	public boolean visit(Modifier node) {
+		this.result.append(getAttribute(node, Modifier.KEYWORD_PROPERTY).toString());
+		return false;
+	}
+	
+	/*
+	 * @see ASTVisitor#visit(NormalAnnotation)
+	 * @since 3.0
+	 */
+	public boolean visit(NormalAnnotation node) {
+		this.result.append('@');
+		getChildNode(node, NormalAnnotation.TYPE_NAME_PROPERTY).accept(this);
+		this.result.append('(');
+		visitList(node, NormalAnnotation.VALUES_PROPERTY, ", "); //$NON-NLS-1$
+		this.result.append(')');
+		return false;
+	}
+	/*
+	 * @see ASTVisitor#visit(ParameterizedType)
+	 * @since 3.0
+	 */
+	public boolean visit(ParameterizedType node) {
+		getChildNode(node, ParameterizedType.TYPE_PROPERTY).accept(this);
+		this.result.append('<');
+		visitList(node, ParameterizedType.TYPE_ARGUMENTS_PROPERTY, ", "); //$NON-NLS-1$
+		this.result.append('>');
+		return false;
+	}
+
+	/*
+	 * @see ASTVisitor#visit(QualifiedType)
+	 * @since 3.0
+	 */
+	public boolean visit(QualifiedType node) {
+		getChildNode(node, QualifiedType.QUALIFIER_PROPERTY).accept(this);
+		this.result.append('.');
+		getChildNode(node, QualifiedType.NAME_PROPERTY).accept(this);
+		return false;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SingleMemberAnnotation)
+	 */
+	public boolean visit(SingleMemberAnnotation node) {
+		this.result.append('@');
+		getChildNode(node, SingleMemberAnnotation.TYPE_NAME_PROPERTY).accept(this);
+		this.result.append('(');
+		getChildNode(node, SingleMemberAnnotation.VALUE_PROPERTY).accept(this);
+		this.result.append(')');
+		return false;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeParameter)
+	 */
+	public boolean visit(TypeParameter node) {
+		getChildNode(node, TypeParameter.NAME_PROPERTY).accept(this);
+		visitList(node, TypeParameter.TYPE_BOUNDS_PROPERTY, " & ", " extends ", EMPTY); //$NON-NLS-1$ //$NON-NLS-2$
+		return false;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.WildcardType)
+	 */
+	public boolean visit(WildcardType node) {
+		this.result.append('?');
+		ASTNode bound = getChildNode(node, WildcardType.BOUND_PROPERTY);
+		if (bound != null) {
+			if (getBooleanAttribute(node, WildcardType.UPPER_BOUND_PROPERTY)) {
+				this.result.append(" extends ");//$NON-NLS-1$
+			} else {
+				this.result.append(" super ");//$NON-NLS-1$
+			}
+			bound.accept(this);
+		}
+		return false;
+	}
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java
index b1476ee..574ccc3 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java
@@ -14,6 +14,12 @@
 import java.util.Collection;
 import java.util.Map;
 
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+
 import org.eclipse.jface.text.Assert;
 import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.jface.text.BadPositionCategoryException;
@@ -21,21 +27,17 @@
 import org.eclipse.jface.text.Document;
 import org.eclipse.jface.text.Position;
 
-import org.eclipse.text.edits.DeleteEdit;
-import org.eclipse.text.edits.InsertEdit;
-import org.eclipse.text.edits.MultiTextEdit;
-import org.eclipse.text.edits.ReplaceEdit;
-import org.eclipse.text.edits.TextEdit;
-
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.ToolFactory;
-import org.eclipse.jdt.core.dom.ASTNode;
-import org.eclipse.jdt.core.dom.Block;
-import org.eclipse.jdt.core.dom.Expression;
-import org.eclipse.jdt.core.dom.Statement;
 import org.eclipse.jdt.core.formatter.CodeFormatter;
 import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
 
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Block;
+import org.eclipse.jdt.core.dom.BodyDeclaration;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.Statement;
+
 /* package */ class ASTRewriteFormatter {
 
 	public static class NodeMarker extends Position {
@@ -210,7 +212,7 @@
     /**
      * Creates a string that represents the given number of indents (can be spaces or tabs..)
      * @param indent
-     * @return
+     * @return Returns the created indent
      */
     public String createIndentString(int indent) {
         StringBuffer buf= new StringBuffer(indent * this.singleIndentString.length());
@@ -274,19 +276,22 @@
 			}
 		} else if (node instanceof Expression && node.getNodeType() != ASTNode.VARIABLE_DECLARATION_EXPRESSION) {
 			code= CodeFormatter.K_EXPRESSION;
+		} else if (node instanceof BodyDeclaration) {
+			code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
 		} else {
 			switch (node.getNodeType()) {
-				case ASTNode.METHOD_DECLARATION:
-				case ASTNode.TYPE_DECLARATION:
-				case ASTNode.FIELD_DECLARATION:
-				case ASTNode.INITIALIZER:
-					code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
-					break;
 				case ASTNode.ARRAY_TYPE:
+				case ASTNode.PARAMETERIZED_TYPE:
 				case ASTNode.PRIMITIVE_TYPE:
+				case ASTNode.QUALIFIED_TYPE:
 				case ASTNode.SIMPLE_TYPE:
 					suffix= " x;"; //$NON-NLS-1$
-					code= CodeFormatter.K_EXPRESSION;
+					code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
+					break;
+				case ASTNode.WILDCARD_TYPE:
+					prefix= "A<"; //$NON-NLS-1$
+					suffix= "> x;"; //$NON-NLS-1$
+					code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
 					break;
 				case ASTNode.COMPILATION_UNIT:
 					code= CodeFormatter.K_COMPILATION_UNIT;
@@ -319,15 +324,29 @@
 					suffix= ";"; //$NON-NLS-1$
 					code= CodeFormatter.K_STATEMENTS;
 					break;
+				case ASTNode.MEMBER_VALUE_PAIR:
+					prefix= "@Author("; //$NON-NLS-1$
+					suffix= ") class x {}"; //$NON-NLS-1$
+					code= CodeFormatter.K_COMPILATION_UNIT;
+					break;
+				case ASTNode.MODIFIER:
+					suffix= " class x {}"; //$NON-NLS-1$
+					code= CodeFormatter.K_COMPILATION_UNIT;				
+					break;
+				case ASTNode.TYPE_PARAMETER:
+					prefix= "class X<"; //$NON-NLS-1$
+					suffix= "> {}"; //$NON-NLS-1$
+					code= CodeFormatter.K_COMPILATION_UNIT;
+					break;
 				case ASTNode.MEMBER_REF:
 				case ASTNode.METHOD_REF:
 				case ASTNode.METHOD_REF_PARAMETER:
 				case ASTNode.TAG_ELEMENT:
 				case ASTNode.TEXT_ELEMENT:
-					// not supported:
+					// Javadoc formatting not yet supported:
 				    return null;
 				default:
-					Assert.isTrue(false, "Node type not covered: " + node.getClass().getName()); //$NON-NLS-1$
+					//Assert.isTrue(false, "Node type not covered: " + node.getClass().getName()); //$NON-NLS-1$
 					return null;
 			}
 		}
@@ -506,7 +525,12 @@
 	public final Prefix METHOD_BODY= new FormattingPrefix("void a() {}", ") {" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
 	public final Prefix FINALLY_BLOCK= new FormattingPrefix("try {} finally {}", "} finally {", CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
 	public final Prefix CATCH_BLOCK= new FormattingPrefix("try {} catch(Exception e) {}", "} c" , CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
-
+	public final Prefix ANNOT_MEMBER_DEFAULT= new FormattingPrefix("String value() default 1;", ") default 1" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
+	public final Prefix ENUM_BODY_START= new FormattingPrefix("enum E { A(){void foo(){}} }", "){v" , CodeFormatter.K_COMPILATION_UNIT); //$NON-NLS-1$ //$NON-NLS-2$
+	public final Prefix ENUM_BODY_END= new FormattingPrefix("enum E { A(){void foo(){ }}, B}", "}}," , CodeFormatter.K_COMPILATION_UNIT); //$NON-NLS-1$ //$NON-NLS-2$
+	public final Prefix WILDCARD_EXTENDS= new FormattingPrefix("A<? extends B> a;", "? extends B" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
+	public final Prefix WILDCARD_SUPER= new FormattingPrefix("A<? super B> a;", "? super B" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
+	
 	public final BlockContext IF_BLOCK_WITH_ELSE= new BlockFormattingPrefixSuffix("if (true)", "else{}", 8); //$NON-NLS-1$ //$NON-NLS-2$
 	public final BlockContext IF_BLOCK_NO_ELSE= new BlockFormattingPrefix("if (true)", 8); //$NON-NLS-1$ //$NON-NLS-2$
 	public final BlockContext ELSE_AFTER_STATEMENT= new BlockFormattingPrefix("if (true) foo(); else ", 15); //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/GenericVisitor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/GenericVisitor.java
deleted file mode 100644
index c345682..0000000
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/GenericVisitor.java
+++ /dev/null
@@ -1,400 +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 Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.core.dom.rewrite;
-
-import org.eclipse.jdt.core.dom.*;
-
-public class GenericVisitor extends ASTVisitor {
-	
-	//---- Hooks for subclasses -------------------------------------------------
-
-	protected boolean visitNode(ASTNode node) {
-		return true;
-	}
-	
-	protected void endVisitNode(ASTNode node) {
-		// do nothing
-	}
-
-	public boolean visit(AnonymousClassDeclaration node) {
-		return visitNode(node);
-	}
-	public boolean visit(ArrayAccess node) {
-		return visitNode(node);
-	}
-	public boolean visit(ArrayCreation node) {
-		return visitNode(node);
-	}
-	public boolean visit(ArrayInitializer node) {
-		return visitNode(node);
-	}
-	public boolean visit(ArrayType node) {
-		return visitNode(node);
-	}
-	public boolean visit(AssertStatement node) {
-		return visitNode(node);
-	}
-	public boolean visit(Assignment node) {
-		return visitNode(node);
-	}
-	public boolean visit(Block node) {
-		return visitNode(node);
-	}
-	public boolean visit(BooleanLiteral node) {
-		return visitNode(node);
-	}
-	public boolean visit(BreakStatement node) {
-		return visitNode(node);
-	}
-	public boolean visit(CastExpression node) {
-		return visitNode(node);
-	}
-	public boolean visit(CatchClause node) {
-		return visitNode(node);
-	}
-	public boolean visit(CharacterLiteral node) {
-		return visitNode(node);
-	}
-	public boolean visit(ClassInstanceCreation node) {
-		return visitNode(node);
-	}
-	public boolean visit(CompilationUnit node) {
-		return visitNode(node);
-	}
-	public boolean visit(ConditionalExpression node) {
-		return visitNode(node);
-	}
-	public boolean visit(ConstructorInvocation node) {
-		return visitNode(node);
-	}
-	public boolean visit(ContinueStatement node) {
-		return visitNode(node);
-	}
-	public boolean visit(DoStatement node) {
-		return visitNode(node);
-	}
-	public boolean visit(EmptyStatement node) {
-		return visitNode(node);
-	}
-	public boolean visit(ExpressionStatement node) {
-		return visitNode(node);
-	}
-	public boolean visit(FieldAccess node) {
-		return visitNode(node);
-	}
-	public boolean visit(FieldDeclaration node) {
-		return visitNode(node);
-	}
-	public boolean visit(ForStatement node) {
-		return visitNode(node);
-	}
-	public boolean visit(IfStatement node) {
-		return visitNode(node);
-	}
-	public boolean visit(ImportDeclaration node) {
-		return visitNode(node);
-	}
-	public boolean visit(InfixExpression node) {
-		return visitNode(node);
-	}
-	public boolean visit(InstanceofExpression node) {
-		return visitNode(node);
-	}
-	public boolean visit(Initializer node) {
-		return visitNode(node);
-	}
-	public boolean visit(Javadoc node) {
-		return visitNode(node);
-	}
-	public boolean visit(LabeledStatement node) {
-		return visitNode(node);
-	}
-	public boolean visit(MethodDeclaration node) {
-		return visitNode(node);
-	}
-	public boolean visit(MethodInvocation node) {
-		return visitNode(node);
-	}
-	public boolean visit(NullLiteral node) {
-		return visitNode(node);
-	}
-	public boolean visit(NumberLiteral node) {
-		return visitNode(node);
-	}
-	public boolean visit(PackageDeclaration node) {
-		return visitNode(node);
-	}
-	public boolean visit(ParenthesizedExpression node) {
-		return visitNode(node);
-	}
-	public boolean visit(PostfixExpression node) {
-		return visitNode(node);
-	}
-	public boolean visit(PrefixExpression node) {
-		return visitNode(node);
-	}
-	public boolean visit(PrimitiveType node) {
-		return visitNode(node);
-	}
-	public boolean visit(QualifiedName node) {
-		return visitNode(node);
-	}
-	public boolean visit(ReturnStatement node) {
-		return visitNode(node);
-	}
-	public boolean visit(SimpleName node) {
-		return visitNode(node);
-	}
-	public boolean visit(SimpleType node) {
-		return visitNode(node);
-	}
-	public boolean visit(StringLiteral node) {
-		return visitNode(node);
-	}
-	public boolean visit(SuperConstructorInvocation node) {
-		return visitNode(node);
-	}
-	public boolean visit(SuperFieldAccess node) {
-		return visitNode(node);
-	}
-	public boolean visit(SuperMethodInvocation node) {
-		return visitNode(node);
-	}
-	public boolean visit(SwitchCase node) {
-		return visitNode(node);
-	}
-	public boolean visit(SwitchStatement node) {
-		return visitNode(node);
-	}
-	public boolean visit(SynchronizedStatement node) {
-		return visitNode(node);
-	}
-	public boolean visit(ThisExpression node) {
-		return visitNode(node);
-	}
-	public boolean visit(ThrowStatement node) {
-		return visitNode(node);
-	}
-	public boolean visit(TryStatement node) {
-		return visitNode(node);
-	}
-	public boolean visit(TypeDeclaration node) {
-		return visitNode(node);
-	}
-	public boolean visit(TypeDeclarationStatement node) {
-		return visitNode(node);
-	}
-	public boolean visit(TypeLiteral node) {
-		return visitNode(node);
-	}
-	public boolean visit(SingleVariableDeclaration node) {
-		return visitNode(node);
-	}
-	public boolean visit(VariableDeclarationExpression node) {
-		return visitNode(node);
-	}
-	public boolean visit(VariableDeclarationStatement node) {
-		return visitNode(node);
-	}
-	public boolean visit(VariableDeclarationFragment node) {
-		return visitNode(node);
-	}
-	public boolean visit(WhileStatement node) {
-		return visitNode(node);
-	}
-
-	public void endVisit(AnonymousClassDeclaration node) {
-		endVisitNode(node);
-	}
-	public void endVisit(ArrayAccess node) {
-		endVisitNode(node);
-	}
-	public void endVisit(ArrayCreation node) {
-		endVisitNode(node);
-	}
-	public void endVisit(ArrayInitializer node) {
-		endVisitNode(node);
-	}
-	public void endVisit(ArrayType node) {
-		endVisitNode(node);
-	}
-	public void endVisit(AssertStatement node) {
-		endVisitNode(node);
-	}
-	public void endVisit(Assignment node) {
-		endVisitNode(node);
-	}
-	public void endVisit(Block node) {
-		endVisitNode(node);
-	}
-	public void endVisit(BooleanLiteral node) {
-		endVisitNode(node);
-	}
-	public void endVisit(BreakStatement node) {
-		endVisitNode(node);
-	}
-	public void endVisit(CastExpression node) {
-		endVisitNode(node);
-	}
-	public void endVisit(CatchClause node) {
-		endVisitNode(node);
-	}
-	public void endVisit(CharacterLiteral node) {
-		endVisitNode(node);
-	}
-	public void endVisit(ClassInstanceCreation node) {
-		endVisitNode(node);
-	}
-	public void endVisit(CompilationUnit node) {
-		endVisitNode(node);
-	}
-	public void endVisit(ConditionalExpression node) {
-		endVisitNode(node);
-	}
-	public void endVisit(ConstructorInvocation node) {
-		endVisitNode(node);
-	}
-	public void endVisit(ContinueStatement node) {
-		endVisitNode(node);
-	}
-	public void endVisit(DoStatement node) {
-		endVisitNode(node);
-	}
-	public void endVisit(EmptyStatement node) {
-		endVisitNode(node);
-	}
-	public void endVisit(ExpressionStatement node) {
-		endVisitNode(node);
-	}
-	public void endVisit(FieldAccess node) {
-		endVisitNode(node);
-	}
-	public void endVisit(FieldDeclaration node) {
-		endVisitNode(node);
-	}
-	public void endVisit(ForStatement node) {
-		endVisitNode(node);
-	}
-	public void endVisit(IfStatement node) {
-		endVisitNode(node);
-	}
-	public void endVisit(ImportDeclaration node) {
-		endVisitNode(node);
-	}
-	public void endVisit(InfixExpression node) {
-		endVisitNode(node);
-	}
-	public void endVisit(InstanceofExpression node) {
-		endVisitNode(node);
-	}
-	public void endVisit(Initializer node) {
-		endVisitNode(node);
-	}
-	public void endVisit(Javadoc node) {
-		endVisitNode(node);
-	}
-	public void endVisit(LabeledStatement node) {
-		endVisitNode(node);
-	}
-	public void endVisit(MethodDeclaration node) {
-		endVisitNode(node);
-	}
-	public void endVisit(MethodInvocation node) {
-		endVisitNode(node);
-	}
-	public void endVisit(NullLiteral node) {
-		endVisitNode(node);
-	}
-	public void endVisit(NumberLiteral node) {
-		endVisitNode(node);
-	}
-	public void endVisit(PackageDeclaration node) {
-		endVisitNode(node);
-	}
-	public void endVisit(ParenthesizedExpression node) {
-		endVisitNode(node);
-	}
-	public void endVisit(PostfixExpression node) {
-		endVisitNode(node);
-	}
-	public void endVisit(PrefixExpression node) {
-		endVisitNode(node);
-	}
-	public void endVisit(PrimitiveType node) {
-		endVisitNode(node);
-	}
-	public void endVisit(QualifiedName node) {
-		endVisitNode(node);
-	}
-	public void endVisit(ReturnStatement node) {
-		endVisitNode(node);
-	}
-	public void endVisit(SimpleName node) {
-		endVisitNode(node);
-	}
-	public void endVisit(SimpleType node) {
-		endVisitNode(node);
-	}
-	public void endVisit(StringLiteral node) {
-		endVisitNode(node);
-	}
-	public void endVisit(SuperConstructorInvocation node) {
-		endVisitNode(node);
-	}
-	public void endVisit(SuperFieldAccess node) {
-		endVisitNode(node);
-	}
-	public void endVisit(SuperMethodInvocation node) {
-		endVisitNode(node);
-	}
-	public void endVisit(SwitchCase node) {
-		endVisitNode(node);
-	}
-	public void endVisit(SwitchStatement node) {
-		endVisitNode(node);
-	}
-	public void endVisit(SynchronizedStatement node) {
-		endVisitNode(node);
-	}
-	public void endVisit(ThisExpression node) {
-		endVisitNode(node);
-	}
-	public void endVisit(ThrowStatement node) {
-		endVisitNode(node);
-	}
-	public void endVisit(TryStatement node) {
-		endVisitNode(node);
-	}
-	public void endVisit(TypeDeclaration node) {
-		endVisitNode(node);
-	}
-	public void endVisit(TypeDeclarationStatement node) {
-		endVisitNode(node);
-	}
-	public void endVisit(TypeLiteral node) {
-		endVisitNode(node);
-	}
-	public void endVisit(SingleVariableDeclaration node) {
-		endVisitNode(node);
-	}
-	public void endVisit(VariableDeclarationExpression node) {
-		endVisitNode(node);
-	}
-	public void endVisit(VariableDeclarationStatement node) {
-		endVisitNode(node);
-	}
-	public void endVisit(VariableDeclarationFragment node) {
-		endVisitNode(node);
-	}
-	public void endVisit(WhileStatement node) {
-		endVisitNode(node);
-	}
-}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/Indents.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/Indents.java
index 540481b..c5fbb72 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/Indents.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/Indents.java
@@ -33,7 +33,7 @@
 	 * Indent char is a space char but not a line delimiters.
 	 * <code>== Character.isWhitespace(ch) && ch != '\n' && ch != '\r'</code>
 	 * @param ch
-	 * @return
+	 * @return Returns true if this the character is a indent delimiter character
 	 */
 	public static boolean isIndentChar(char ch) {
 		return Character.isWhitespace(ch) && !isLineDelimiterChar(ch);
@@ -84,7 +84,7 @@
 	 * @param line The line to trim the indent
 	 * @param indentsToRemove The indent level to remove
 	 * @param tabWidth The current tab width
-	 * @return
+	 * @return Returns the trimed line
 	 */
 	public static String trimIndent(String line, int indentsToRemove, int tabWidth) {
 		if (line == null || indentsToRemove <= 0)
@@ -198,7 +198,7 @@
 	 * @param tabWidth The current tab width setting
 	 * @param newIndent The new Indent string
 	 * @param lineDelim THe current line delimiter
-	 * @return
+	 * @return Returns the newly indented code
 	 */
 	public static String changeIndent(String code, int codeIndentLevel, int tabWidth, String newIndent, String lineDelim) {
 		try {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEventStore.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEventStore.java
index 584b46a..c9512e7 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEventStore.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEventStore.java
@@ -376,7 +376,7 @@
 	 * Kind is either ORIGINAL, NEW, or BOTH
 	 * @param value
 	 * @param kind
-	 * @return
+	 * @return Returns the event with the given value of <code>null</code>.
 	 */
 	public RewriteEvent findEvent(Object value, int kind) {
 		for (int i= 0; i < this.events.size(); i++) {
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetAllocationExpression.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetAllocationExpression.java
index 0b05b41..4123b8d 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetAllocationExpression.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetAllocationExpression.java
@@ -11,9 +11,10 @@
 package org.eclipse.jdt.internal.eval;
 
 import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.CastExpression;
+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.lookup.ArrayBinding;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
@@ -38,9 +39,9 @@
 	boolean valueRequired) {
 
 	int pc = codeStream.position;
-	ReferenceBinding allocatedType = this.binding.declaringClass;
+	ReferenceBinding allocatedType = this.codegenBinding.declaringClass;
 
-	if (this.binding.canBeSeenBy(allocatedType, this, currentScope)) {
+	if (this.codegenBinding.canBeSeenBy(allocatedType, this, currentScope)) {
 		codeStream.new_(allocatedType);
 		if (valueRequired) {
 			codeStream.dup();
@@ -70,22 +71,22 @@
 				this);
 		}
 		// invoke constructor
-		codeStream.invokespecial(this.binding);
+		codeStream.invokespecial(this.codegenBinding);
 	} else {
 		// private emulation using reflect
-		((CodeSnippetCodeStream) codeStream).generateEmulationForConstructor(currentScope, this.binding);
+		((CodeSnippetCodeStream) codeStream).generateEmulationForConstructor(currentScope, this.codegenBinding);
 		// generate arguments
 		if (this.arguments != null) {
 			int argsLength = this.arguments.length;
 			codeStream.generateInlinedValue(argsLength);
-			codeStream.newArray(currentScope, new ArrayBinding(currentScope.getType(TypeConstants.JAVA_LANG_OBJECT), 1));
+			codeStream.newArray(currentScope.createArrayType(currentScope.getType(TypeConstants.JAVA_LANG_OBJECT, 3), 1));
 			codeStream.dup();
 			for (int i = 0; i < argsLength; i++) {
 				codeStream.generateInlinedValue(i);
 				this.arguments[i].generateCode(currentScope, codeStream, true);
-				TypeBinding parameterBinding = this.binding.parameters[i];
+				TypeBinding parameterBinding = this.codegenBinding.parameters[i];
 				if (parameterBinding.isBaseType() && parameterBinding != NullBinding) {
-					((CodeSnippetCodeStream)codeStream).generateObjectWrapperForType(this.binding.parameters[i]);
+					((CodeSnippetCodeStream)codeStream).generateObjectWrapperForType(this.codegenBinding.parameters[i]);
 				}
 				codeStream.aastore();
 				if (i < argsLength - 1) {
@@ -94,7 +95,7 @@
 			}
 		} else {
 			codeStream.generateInlinedValue(0);
-			codeStream.newArray(currentScope, new ArrayBinding(currentScope.getType(TypeConstants.JAVA_LANG_OBJECT), 1));			
+			codeStream.newArray(currentScope.createArrayType(currentScope.getType(TypeConstants.JAVA_LANG_OBJECT, 3), 1));			
 		}
 		((CodeSnippetCodeStream) codeStream).invokeJavaLangReflectConstructorNewInstance();
 		codeStream.checkcast(allocatedType);
@@ -112,21 +113,30 @@
 	// not supported yet
 }
 public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
-	// do nothing
+		if (!flowInfo.isReachable()) return;
+
+		// if constructor from parameterized type got found, use the original constructor at codegen time
+		this.codegenBinding = this.binding.original();
 }
 public TypeBinding resolveType(BlockScope scope) {
 	// Propagate the type checking to the arguments, and check if the constructor is defined.
 	this.constant = NotAConstant;
-	this.resolvedType = this.type.resolveType(scope); // will check for null after args are resolved
+	this.resolvedType = this.type.resolveType(scope, true /* check bounds*/); // will check for null after args are resolved
 
 	// buffering the arguments' types
+	boolean argsContainCast = false;
 	TypeBinding[] argumentTypes = NoParameters;
 	if (this.arguments != null) {
 		boolean argHasError = false;
 		int length = this.arguments.length;
 		argumentTypes = new TypeBinding[length];
 		for (int i = 0; i < length; i++) {
-			if ((argumentTypes[i] = this.arguments[i].resolveType(scope)) == null) {
+			Expression argument = this.arguments[i];
+			if (argument instanceof CastExpression) {
+				argument.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+				argsContainCast = true;
+			}
+			if ((argumentTypes[i] = argument.resolveType(scope)) == null) {
 				argHasError = true;
 			}
 		}
@@ -183,10 +193,21 @@
 	if (isMethodUseDeprecated(this.binding, scope)) {
 		scope.problemReporter().deprecatedMethod(this.binding, this);
 	}
-	if (this.arguments != null) {
-		for (int i = 0; i < this.arguments.length; i++) {
-			this.arguments[i].implicitWidening(this.binding.parameters[i], argumentTypes[i]);
+	if (arguments != null) {
+		for (int i = 0; i < arguments.length; i++) {
+		    TypeBinding parameterType = binding.parameters[i];
+		    TypeBinding argumentType = argumentTypes[i];
+			arguments[i].computeConversion(scope, parameterType, argumentType);
+			if (argumentType.needsUncheckedConversion(parameterType)) {
+				scope.problemReporter().unsafeRawConversion(arguments[i], argumentType, parameterType);
+			}
 		}
+		if (argsContainCast) {
+			CastExpression.checkNeedForArgumentCasts(scope, null, allocatedType, binding, this.arguments, argumentTypes, this);
+		}
+	}
+	if (allocatedType.isRawType() && this.binding.hasSubstitutedParameters()) {
+	    scope.problemReporter().unsafeRawInvocation(this, this.binding);
 	}
 	return allocatedType;
 }
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java
index 203abb5..0ddf602 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java
@@ -16,6 +16,7 @@
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.FieldReference;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
@@ -56,7 +57,7 @@
 
 	this.constantPoolOffset = this.headerOffset;
 	this.headerOffset += 2;
-	this.constantPool = new CodeSnippetConstantPool(this);
+	this.constantPool = new ConstantPool(this);
 	int accessFlags = aType.getAccessFlags();
 	
 	if (aType.isClass()) {
@@ -84,15 +85,15 @@
 	// now we continue to generate the bytes inside the contents array
 	this.contents[this.contentsOffset++] = (byte) (accessFlags >> 8);
 	this.contents[this.contentsOffset++] = (byte) accessFlags;
-	int classNameIndex = this.constantPool.literalIndex(aType);
+	int classNameIndex = this.constantPool.literalIndexForType(aType.constantPoolName());
 	this.contents[this.contentsOffset++] = (byte) (classNameIndex >> 8);
 	this.contents[this.contentsOffset++] = (byte) classNameIndex;
 	int superclassNameIndex;
 	if (aType.isInterface()) {
-		superclassNameIndex = this.constantPool.literalIndexForJavaLangObject();
+		superclassNameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName);
 	} else {
 		superclassNameIndex =
-			(aType.superclass == null ? 0 : this.constantPool.literalIndex(aType.superclass));
+			(aType.superclass == null ? 0 : this.constantPool.literalIndexForType(aType.superclass.constantPoolName()));
 	}
 	this.contents[this.contentsOffset++] = (byte) (superclassNameIndex >> 8);
 	this.contents[this.contentsOffset++] = (byte) superclassNameIndex;
@@ -102,7 +103,7 @@
 	this.contents[this.contentsOffset++] = (byte) interfacesCount;
 	if (superInterfacesBinding != null) {
 		for (int i = 0; i < interfacesCount; i++) {
-			int interfaceIndex = this.constantPool.literalIndex(superInterfacesBinding[i]);
+			int interfaceIndex = this.constantPool.literalIndexForType(superInterfacesBinding[i].constantPoolName());
 			this.contents[this.contentsOffset++] = (byte) (interfaceIndex >> 8);
 			this.contents[this.contentsOffset++] = (byte) interfaceIndex;
 		}
@@ -140,7 +141,7 @@
 	FieldBinding[] fields = typeBinding.fields;
 	if ((fields != null) && (fields != NoFields)) {
 		for (int i = 0, max = fields.length; i < max; i++) {
-			if (fields[i].constant == null) {
+			if (fields[i].constant() == null) {
 				FieldReference.getConstantFor(fields[i], null, false, null);
 			}
 		}
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetCodeStream.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetCodeStream.java
index 45653e5..123b89c 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetCodeStream.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetCodeStream.java
@@ -11,7 +11,7 @@
 package org.eclipse.jdt.internal.eval;
 
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
-import org.eclipse.jdt.internal.compiler.codegen.QualifiedNamesConstants;
+import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
 import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
@@ -24,6 +24,7 @@
 public class CodeSnippetCodeStream extends CodeStream {
 	static InvocationSite NO_INVOCATION_SITE = 
 		new InvocationSite(){	
+			public TypeBinding[] genericTypeArguments() { return null; }
 			public boolean isSuperAccess(){ return false; }
 			public boolean isTypeAccess() { return false; }
 			public void setActualReceiverType(ReferenceBinding receiverType) {}
@@ -37,7 +38,7 @@
  * @param classFile org.eclipse.jdt.internal.compiler.ClassFile
  */
 public CodeSnippetCodeStream(org.eclipse.jdt.internal.compiler.ClassFile classFile) {
-	super(classFile);
+	super(classFile, JDK1_4);
 }
 protected void checkcast(int baseId) {
 	this.countLabels = 0;
@@ -48,28 +49,28 @@
 	this.bCodeStream[this.classFileOffset++] = OPC_checkcast;
 	switch (baseId) {
 		case T_byte :
-			writeUnsignedShort(this.constantPool.literalIndexForJavaLangByte());
+			writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangByteConstantPoolName));
 			break;
 		case T_short :
-			writeUnsignedShort(this.constantPool.literalIndexForJavaLangShort());
+			writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangShortConstantPoolName));
 			break;
 		case T_char :
-			writeUnsignedShort(this.constantPool.literalIndexForJavaLangCharacter());
+			writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangCharacterConstantPoolName));
 			break;
 		case T_int :
-			writeUnsignedShort(this.constantPool.literalIndexForJavaLangInteger());
+			writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangIntegerConstantPoolName));
 			break;
 		case T_long :
-			writeUnsignedShort(this.constantPool.literalIndexForJavaLangLong());
+			writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangLongConstantPoolName));
 			break;
 		case T_float :
-			writeUnsignedShort(this.constantPool.literalIndexForJavaLangFloat());
+			writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangFloatConstantPoolName));
 			break;
 		case T_double :
-			writeUnsignedShort(this.constantPool.literalIndexForJavaLangDouble());
+			writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangDoubleConstantPoolName));
 			break;
 		case T_boolean :
-			writeUnsignedShort(this.constantPool.literalIndexForJavaLangBoolean());
+			writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangBooleanConstantPoolName));
 	}
 }
 public void generateEmulatedAccessForMethod(Scope scope, MethodBinding methodBinding) {
@@ -98,7 +99,7 @@
 	this.invokeClassForName();
 	int paramLength = methodBinding.parameters.length;
 	this.generateInlinedValue(paramLength);
-	this.newArray(scope, new ArrayBinding(scope.getType(TypeConstants.JAVA_LANG_CLASS), 1));
+	this.newArray(scope.createArrayType(scope.getType(TypeConstants.JAVA_LANG_CLASS, 3), 1));
 	if (paramLength > 0) {
 		this.dup();
 		for (int i = 0; i < paramLength; i++) {
@@ -154,7 +155,7 @@
 	this.ldc(String.valueOf(methodBinding.selector));
 	int paramLength = methodBinding.parameters.length;
 	this.generateInlinedValue(paramLength);
-	this.newArray(scope, new ArrayBinding(scope.getType(TypeConstants.JAVA_LANG_CLASS), 1));
+	this.newArray(scope.createArrayType(scope.getType(TypeConstants.JAVA_LANG_CLASS, 3), 1));
 	if (paramLength > 0) {
 		this.dup();
 		for (int i = 0; i < paramLength; i++) {
@@ -196,34 +197,7 @@
 	/* The top of stack must be encapsulated inside 
 	 * a wrapper object if it corresponds to a base type
 	 */
-	char[][] wrapperTypeCompoundName = null;
-	switch (valueType.id) {
-		case T_int : // new: java.lang.Integer
-			wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Integer".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
-			break;
-		case T_boolean : // new: java.lang.Boolean
-			wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Boolean".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
-			break;
-		case T_byte : // new: java.lang.Byte
-			wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Byte".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
-			break;
-		case T_char : // new: java.lang.Character
-			wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Character".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
-			break;
-		case T_float : // new: java.lang.Float
-			wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Float".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
-			break;
-		case T_double : // new: java.lang.Double
-			wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Double".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
-			break;
-		case T_short : // new: java.lang.Short
-			wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Short".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
-			break;
-		case T_long : // new: java.lang.Long
-			wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Long".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
-			break;
-	}
-	TypeBinding wrapperType = this.methodDeclaration.scope.getType(wrapperTypeCompoundName);
+	TypeBinding wrapperType = this.methodDeclaration.scope.boxing(valueType);
 	new_(wrapperType);
 	if (valueType.id == T_long || valueType.id == T_double) {
 		dup_x2();
@@ -235,172 +209,267 @@
 	}
 	MethodBinding methodBinding = this.methodDeclaration.scope.getMethod(
 				wrapperType, 
-				QualifiedNamesConstants.Init, 
+				ConstantPool.Init, 
 				new TypeBinding[] {valueType}, 
 				NO_INVOCATION_SITE);
 	invokespecial(methodBinding);
 }
 public void getBaseTypeValue(int baseTypeID) {
-	this.countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	this.position++;
-	this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
 	switch (baseTypeID) {
 		case T_byte :
 			// invokevirtual: byteValue()
-			writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangByteByteValue());
+			this.invoke(
+					OPC_invokevirtual,
+					0, // argCount
+					1, // return type size
+					ConstantPool.JavaLangByteConstantPoolName,
+					ConstantPool.BYTEVALUE_BYTE_METHOD_NAME,
+					ConstantPool.BYTEVALUE_BYTE_METHOD_SIGNATURE);
 			break;
 		case T_short :
 			// invokevirtual: shortValue()
-			writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangShortShortValue());
+			this.invoke(
+					OPC_invokevirtual,
+					0, // argCount
+					1, // return type size
+					ConstantPool.JavaLangShortConstantPoolName,
+					ConstantPool.SHORTVALUE_SHORT_METHOD_NAME,
+					ConstantPool.SHORTVALUE_SHORT_METHOD_SIGNATURE);
 			break;
 		case T_char :
 			// invokevirtual: charValue()
-			writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangCharacterCharValue());
+			this.invoke(
+					OPC_invokevirtual,
+					0, // argCount
+					1, // return type size
+					ConstantPool.JavaLangCharacterConstantPoolName,
+					ConstantPool.CHARVALUE_CHARACTER_METHOD_NAME,
+					ConstantPool.CHARVALUE_CHARACTER_METHOD_SIGNATURE);
 			break;
 		case T_int :
 			// invokevirtual: intValue()
-			writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangIntegerIntValue());
+			this.invoke(
+					OPC_invokevirtual,
+					0, // argCount
+					1, // return type size
+					ConstantPool.JavaLangIntegerConstantPoolName,
+					ConstantPool.INTVALUE_INTEGER_METHOD_NAME,
+					ConstantPool.INTVALUE_INTEGER_METHOD_SIGNATURE);
 			break;
 		case T_long :
 			// invokevirtual: longValue()
-			this.stackDepth++;
-			if (this.stackDepth > this.stackMax)
-				this.stackMax = this.stackDepth;
-			writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangLongLongValue());
+			this.invoke(
+					OPC_invokevirtual,
+					0, // argCount
+					2, // return type size
+					ConstantPool.JavaLangLongConstantPoolName,
+					ConstantPool.LONGVALUE_LONG_METHOD_NAME,
+					ConstantPool.LONGVALUE_LONG_METHOD_SIGNATURE);
 			break;
 		case T_float :
 			// invokevirtual: floatValue()
-			writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangFloatFloatValue());
+			this.invoke(
+					OPC_invokevirtual,
+					0, // argCount
+					1, // return type size
+					ConstantPool.JavaLangFloatConstantPoolName,
+					ConstantPool.FLOATVALUE_FLOAT_METHOD_NAME,
+					ConstantPool.FLOATVALUE_FLOAT_METHOD_SIGNATURE);
 			break;
 		case T_double :
 			// invokevirtual: doubleValue()
-			this.stackDepth++;
-			if (this.stackDepth > this.stackMax)
-				this.stackMax = this.stackDepth;
-			writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangDoubleDoubleValue());
+			this.invoke(
+					OPC_invokevirtual,
+					0, // argCount
+					2, // return type size
+					ConstantPool.JavaLangDoubleConstantPoolName,
+					ConstantPool.DOUBLEVALUE_DOUBLE_METHOD_NAME,
+					ConstantPool.DOUBLEVALUE_DOUBLE_METHOD_SIGNATURE);
 			break;
 		case T_boolean :
 			// invokevirtual: booleanValue()
-			writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangBooleanBooleanValue());
+			this.invoke(
+					OPC_invokevirtual,
+					0, // argCount
+					1, // return type size
+					ConstantPool.JavaLangBooleanConstantPoolName,
+					ConstantPool.BOOLEANVALUE_BOOLEAN_METHOD_NAME,
+					ConstantPool.BOOLEANVALUE_BOOLEAN_METHOD_SIGNATURE);
 	}
 }
 protected void invokeAccessibleObjectSetAccessible() {
 	// invokevirtual: java.lang.reflect.AccessibleObject.setAccessible(Z)V;
-	this.countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	this.position++;
-	this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
-	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangReflectAccessibleObjectSetAccessible());
-	this.stackDepth-=2;
+	this.invoke(
+			OPC_invokevirtual,
+			1, // argCount
+			0, // return type size
+			ConstantPool.JAVALANGREFLECTACCESSIBLEOBJECT_CONSTANTPOOLNAME,
+			ConstantPool.SETACCESSIBLE_NAME,
+			ConstantPool.SETACCESSIBLE_SIGNATURE);
 }
 protected void invokeArrayNewInstance() {
-	// invokestatic: java.lang.reflect.Array.newInstance(Ljava.lang.Class;int[])Ljava.lang.reflect.Array;
-	this.countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	this.position++;
-	this.bCodeStream[this.classFileOffset++] = OPC_invokestatic;
-	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangReflectArrayNewInstance());
-	this.stackDepth--;
+	// invokestatic: java.lang.reflect.Array.newInstance(Ljava.lang.Class;int[])Ljava.lang.Object;
+	this.invoke(
+			OPC_invokestatic,
+			2, // argCount
+			1, // return type size
+			ConstantPool.JAVALANGREFLECTARRAY_CONSTANTPOOLNAME,
+			ConstantPool.NewInstance,
+			ConstantPool.NewInstanceSignature);
 }
 protected void invokeClassGetDeclaredConstructor() {
 	// invokevirtual: java.lang.Class getDeclaredConstructor([Ljava.lang.Class)Ljava.lang.reflect.Constructor;
-	this.countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	this.position++;
-	this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
-	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangClassGetDeclaredConstructor());
-	this.stackDepth--;
+	this.invoke(
+			OPC_invokevirtual,
+			1, // argCount
+			1, // return type size
+			ConstantPool.JavaLangClassConstantPoolName,
+			ConstantPool.GETDECLAREDCONSTRUCTOR_NAME,
+			ConstantPool.GETDECLAREDCONSTRUCTOR_SIGNATURE);
 }
 protected void invokeClassGetDeclaredField() {
 	// invokevirtual: java.lang.Class.getDeclaredField(Ljava.lang.String)Ljava.lang.reflect.Field;
-	this.countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	this.position++;
-	this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
-	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangClassGetDeclaredField());
-	this.stackDepth--;
+	this.invoke(
+			OPC_invokevirtual,
+			1, // argCount
+			1, // return type size
+			ConstantPool.JavaLangClassConstantPoolName,
+			ConstantPool.GETDECLAREDFIELD_NAME,
+			ConstantPool.GETDECLAREDFIELD_SIGNATURE);
 }
 protected void invokeClassGetDeclaredMethod() {
 	// invokevirtual: java.lang.Class getDeclaredMethod(Ljava.lang.String, [Ljava.lang.Class)Ljava.lang.reflect.Method;
-	this.countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	this.position++;
-	this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
-	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangClassGetDeclaredMethod());
-	this.stackDepth-=2;
+	this.invoke(
+			OPC_invokevirtual,
+			2, // argCount
+			1, // return type size
+			ConstantPool.JavaLangClassConstantPoolName,
+			ConstantPool.GETDECLAREDMETHOD_NAME,
+			ConstantPool.GETDECLAREDMETHOD_SIGNATURE);
 }
 protected void invokeJavaLangReflectConstructorNewInstance() {
 	// invokevirtual: java.lang.reflect.Constructor.newInstance([Ljava.lang.Object;)Ljava.lang.Object;
-	this.countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	this.position++;
-	this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
-	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangReflectConstructorNewInstance());
-	this.stackDepth--;
+	this.invoke(
+			OPC_invokevirtual,
+			1, // argCount
+			1, // return type size
+			ConstantPool.JavaLangReflectConstructor,
+			ConstantPool.NewInstance,
+			ConstantPool.JavaLangReflectConstructorNewInstanceSignature);
 }
 protected void invokeJavaLangReflectFieldGetter(int typeID) {
-	this.countLabels = 0;
-	int usedTypeID;
-	if (typeID == T_null)
-		usedTypeID = T_Object;
-	else
-		usedTypeID = typeID;
-	// invokevirtual
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
+	int returnTypeSize = 1;
+	char[] signature = null;
+	char[] selector = null;
+	switch (typeID) {
+		case T_int :
+			selector = ConstantPool.GET_INT_METHOD_NAME;
+			signature = ConstantPool.GET_INT_METHOD_SIGNATURE;
+			break;
+		case T_byte :
+			selector = ConstantPool.GET_BYTE_METHOD_NAME;
+			signature = ConstantPool.GET_BYTE_METHOD_SIGNATURE;
+			break;
+		case T_short :
+			selector = ConstantPool.GET_SHORT_METHOD_NAME;
+			signature = ConstantPool.GET_SHORT_METHOD_SIGNATURE;
+			break;
+		case T_long :
+			selector = ConstantPool.GET_LONG_METHOD_NAME;
+			signature = ConstantPool.GET_LONG_METHOD_SIGNATURE;
+			returnTypeSize = 2;
+			break;
+		case T_float :
+			selector = ConstantPool.GET_FLOAT_METHOD_NAME;
+			signature = ConstantPool.GET_FLOAT_METHOD_SIGNATURE;
+			break;
+		case T_double :
+			selector = ConstantPool.GET_DOUBLE_METHOD_NAME;
+			signature = ConstantPool.GET_DOUBLE_METHOD_SIGNATURE;
+			returnTypeSize = 2;
+			break;
+		case T_char :
+			selector = ConstantPool.GET_CHAR_METHOD_NAME;
+			signature = ConstantPool.GET_CHAR_METHOD_SIGNATURE;
+			break;
+		case T_boolean :
+			selector = ConstantPool.GET_BOOLEAN_METHOD_NAME;
+			signature = ConstantPool.GET_BOOLEAN_METHOD_SIGNATURE;
+			break;
+		default :
+			selector = ConstantPool.GET_OBJECT_METHOD_NAME;
+			signature = ConstantPool.GET_OBJECT_METHOD_SIGNATURE;
+			break;
 	}
-	this.position++;
-	this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
-	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexJavaLangReflectFieldGetter(typeID));
-	if ((usedTypeID != T_long) && (usedTypeID != T_double)) {
-		this.stackDepth--;
-	}
+	this.invoke(
+			OPC_invokevirtual,
+			1, // argCount
+			returnTypeSize, // return type size
+			ConstantPool.JAVALANGREFLECTFIELD_CONSTANTPOOLNAME,
+			selector,
+			signature);
 }
 protected void invokeJavaLangReflectFieldSetter(int typeID) {
-	this.countLabels = 0;
-	int usedTypeID;
-	if (typeID == T_null)
-		usedTypeID = T_Object;
-	else
-		usedTypeID = typeID;
-	// invokevirtual
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
+	int argCount = 2;
+	char[] signature = null;
+	char[] selector = null;
+	switch (typeID) {
+		case T_int :
+			selector = ConstantPool.SET_INT_METHOD_NAME;
+			signature = ConstantPool.SET_INT_METHOD_SIGNATURE;
+			break;
+		case T_byte :
+			selector = ConstantPool.SET_BYTE_METHOD_NAME;
+			signature = ConstantPool.SET_BYTE_METHOD_SIGNATURE;
+			break;
+		case T_short :
+			selector = ConstantPool.SET_SHORT_METHOD_NAME;
+			signature = ConstantPool.SET_SHORT_METHOD_SIGNATURE;
+			break;
+		case T_long :
+			selector = ConstantPool.SET_LONG_METHOD_NAME;
+			signature = ConstantPool.SET_LONG_METHOD_SIGNATURE;
+			argCount = 3;
+			break;
+		case T_float :
+			selector = ConstantPool.SET_FLOAT_METHOD_NAME;
+			signature = ConstantPool.SET_FLOAT_METHOD_SIGNATURE;
+			break;
+		case T_double :
+			selector = ConstantPool.SET_DOUBLE_METHOD_NAME;
+			signature = ConstantPool.SET_DOUBLE_METHOD_SIGNATURE;
+			argCount = 3;
+			break;
+		case T_char :
+			selector = ConstantPool.SET_CHAR_METHOD_NAME;
+			signature = ConstantPool.SET_CHAR_METHOD_SIGNATURE;
+			break;
+		case T_boolean :
+			selector = ConstantPool.SET_BOOLEAN_METHOD_NAME;
+			signature = ConstantPool.SET_BOOLEAN_METHOD_SIGNATURE;
+			break;
+		default :
+			selector = ConstantPool.SET_OBJECT_METHOD_NAME;
+			signature = ConstantPool.SET_OBJECT_METHOD_SIGNATURE;
+			break;
 	}
-	this.position++;
-	this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
-	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexJavaLangReflectFieldSetter(typeID));
-	if ((usedTypeID != T_long) && (usedTypeID != T_double)) {
-		this.stackDepth-=3;
-	} else {
-		this.stackDepth-=4;
-	}
+	this.invoke(
+			OPC_invokevirtual,
+			argCount, // argCount
+			0, // return type size
+			ConstantPool.JAVALANGREFLECTFIELD_CONSTANTPOOLNAME,
+			selector,
+			signature);
 }
 protected void invokeJavaLangReflectMethodInvoke() {
 	// invokevirtual: java.lang.reflect.Method.invoke(Ljava.lang.Object;[Ljava.lang.Object;)Ljava.lang.Object;
-	this.countLabels = 0;
-	if (classFileOffset + 2 >= bCodeStream.length) {
-		resizeByteArray();
-	}
-	this.position++;
-	this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
-	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangReflectMethodInvoke());
-	this.stackDepth-=2;
+	this.invoke(
+			OPC_invokevirtual,
+			2, // argCount
+			1, // return type size
+			ConstantPool.JAVALANGREFLECTMETHOD_CONSTANTPOOLNAME,
+			ConstantPool.INVOKE_METHOD_METHOD_NAME,
+			ConstantPool.INVOKE_METHOD_METHOD_SIGNATURE);
 }
 private final void resizeByteArray() {
 	int length = bCodeStream.length;
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetConstantPool.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetConstantPool.java
deleted file mode 100644
index 90347b6..0000000
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetConstantPool.java
+++ /dev/null
@@ -1,1855 +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 Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.eval;
-
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
-import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
-import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
-
-/**
- * This constant pool is used to manage well known methods and fields related specifically to the
- * code snippet code generation (java.lang.reflect classes).
- */
-public class CodeSnippetConstantPool extends ConstantPool implements TypeConstants {
-
-	// predefined type constant names
-	static final char[][] JAVA_LANG_REFLECT_FIELD = new char[][] {JAVA, LANG, REFLECT, "Field".toCharArray()}; //$NON-NLS-1$
-	static final char[][] JAVA_LANG_REFLECT_ACCESSIBLEOBJECT = new char[][] {JAVA, LANG, REFLECT, "AccessibleObject".toCharArray()}; //$NON-NLS-1$
-	static final char[][] JAVA_LANG_REFLECT_METHOD = new char[][] {JAVA, LANG, REFLECT, "Method".toCharArray()}; //$NON-NLS-1$
-	static final char[][] JAVA_LANG_REFLECT_ARRAY = new char[][] {JAVA, LANG, REFLECT, "Array".toCharArray()}; //$NON-NLS-1$
-
-	// predefined methods constant names
-	static final char[] GETDECLAREDFIELD_NAME = "getDeclaredField".toCharArray(); //$NON-NLS-1$
-	static final char[] GETDECLAREDFIELD_SIGNATURE = "(Ljava/lang/String;)Ljava/lang/reflect/Field;".toCharArray(); //$NON-NLS-1$
-	static final char[] SETACCESSIBLE_NAME = "setAccessible".toCharArray(); //$NON-NLS-1$
-	static final char[] SETACCESSIBLE_SIGNATURE = "(Z)V".toCharArray(); //$NON-NLS-1$
-	static final char[] JAVALANGREFLECTFIELD_CONSTANTPOOLNAME = "java/lang/reflect/Field".toCharArray(); //$NON-NLS-1$
-	static final char[] JAVALANGREFLECTACCESSIBLEOBJECT_CONSTANTPOOLNAME = "java/lang/reflect/AccessibleObject".toCharArray(); //$NON-NLS-1$
-	static final char[] JAVALANGREFLECTARRAY_CONSTANTPOOLNAME = "java/lang/reflect/Array".toCharArray(); //$NON-NLS-1$
-	static final char[] JAVALANGREFLECTMETHOD_CONSTANTPOOLNAME = "java/lang/reflect/Method".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_INT_METHOD_NAME = "getInt".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_LONG_METHOD_NAME = "getLong".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_DOUBLE_METHOD_NAME = "getDouble".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_FLOAT_METHOD_NAME = "getFloat".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_BYTE_METHOD_NAME = "getByte".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_CHAR_METHOD_NAME = "getChar".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_BOOLEAN_METHOD_NAME = "getBoolean".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_OBJECT_METHOD_NAME = "get".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_SHORT_METHOD_NAME = "getShort".toCharArray(); //$NON-NLS-1$
-	static final char[] ARRAY_NEWINSTANCE_NAME = "newInstance".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_INT_METHOD_SIGNATURE = "(Ljava/lang/Object;)I".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_LONG_METHOD_SIGNATURE = "(Ljava/lang/Object;)J".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_DOUBLE_METHOD_SIGNATURE = "(Ljava/lang/Object;)D".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_FLOAT_METHOD_SIGNATURE = "(Ljava/lang/Object;)F".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_BYTE_METHOD_SIGNATURE = "(Ljava/lang/Object;)B".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_CHAR_METHOD_SIGNATURE = "(Ljava/lang/Object;)C".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_BOOLEAN_METHOD_SIGNATURE = "(Ljava/lang/Object;)Z".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_OBJECT_METHOD_SIGNATURE = "(Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
-	static final char[] GET_SHORT_METHOD_SIGNATURE = "(Ljava/lang/Object;)S".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_INT_METHOD_NAME = "setInt".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_LONG_METHOD_NAME = "setLong".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_DOUBLE_METHOD_NAME = "setDouble".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_FLOAT_METHOD_NAME = "setFloat".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_BYTE_METHOD_NAME = "setByte".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_CHAR_METHOD_NAME = "setChar".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_BOOLEAN_METHOD_NAME = "setBoolean".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_OBJECT_METHOD_NAME = "set".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_SHORT_METHOD_NAME = "setShort".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_INT_METHOD_SIGNATURE = "(Ljava/lang/Object;I)V".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_LONG_METHOD_SIGNATURE = "(Ljava/lang/Object;J)V".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_DOUBLE_METHOD_SIGNATURE = "(Ljava/lang/Object;D)V".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_FLOAT_METHOD_SIGNATURE = "(Ljava/lang/Object;F)V".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_BYTE_METHOD_SIGNATURE = "(Ljava/lang/Object;B)V".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_CHAR_METHOD_SIGNATURE = "(Ljava/lang/Object;C)V".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_BOOLEAN_METHOD_SIGNATURE = "(Ljava/lang/Object;Z)V".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_OBJECT_METHOD_SIGNATURE = "(Ljava/lang/Object;Ljava/lang/Object;)V".toCharArray(); //$NON-NLS-1$
-	static final char[] SET_SHORT_METHOD_SIGNATURE = "(Ljava/lang/Object;S)V".toCharArray(); //$NON-NLS-1$
-	static final char[] GETDECLAREDMETHOD_NAME = "getDeclaredMethod".toCharArray(); //$NON-NLS-1$
-	static final char[] GETDECLAREDMETHOD_SIGNATURE = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;".toCharArray(); //$NON-NLS-1$
-	static final char[] ARRAY_NEWINSTANCE_SIGNATURE = "(Ljava/lang/Class;[I)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
-	static final char[] INVOKE_METHOD_METHOD_NAME = "invoke".toCharArray(); //$NON-NLS-1$
-	static final char[] INVOKE_METHOD_METHOD_SIGNATURE = "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
-	static final char[] BYTEVALUE_BYTE_METHOD_NAME = "byteValue".toCharArray(); //$NON-NLS-1$
-	static final char[] BYTEVALUE_BYTE_METHOD_SIGNATURE = "()B".toCharArray(); //$NON-NLS-1$
-	static final char[] SHORTVALUE_SHORT_METHOD_NAME = "shortValue".toCharArray(); //$NON-NLS-1$
-	static final char[] DOUBLEVALUE_DOUBLE_METHOD_NAME = "doubleValue".toCharArray(); //$NON-NLS-1$
-	static final char[] FLOATVALUE_FLOAT_METHOD_NAME = "floatValue".toCharArray(); //$NON-NLS-1$
-	static final char[] INTVALUE_INTEGER_METHOD_NAME = "intValue".toCharArray(); //$NON-NLS-1$
-	static final char[] CHARVALUE_CHARACTER_METHOD_NAME = "charValue".toCharArray(); //$NON-NLS-1$
-	static final char[] BOOLEANVALUE_BOOLEAN_METHOD_NAME = "booleanValue".toCharArray(); //$NON-NLS-1$
-	static final char[] LONGVALUE_LONG_METHOD_NAME = "longValue".toCharArray(); //$NON-NLS-1$
-	static final char[] SHORTVALUE_SHORT_METHOD_SIGNATURE = "()S".toCharArray(); //$NON-NLS-1$
-	static final char[] DOUBLEVALUE_DOUBLE_METHOD_SIGNATURE = "()D".toCharArray(); //$NON-NLS-1$
-	static final char[] FLOATVALUE_FLOAT_METHOD_SIGNATURE = "()F".toCharArray(); //$NON-NLS-1$
-	static final char[] INTVALUE_INTEGER_METHOD_SIGNATURE = "()I".toCharArray(); //$NON-NLS-1$
-	static final char[] CHARVALUE_CHARACTER_METHOD_SIGNATURE = "()C".toCharArray(); //$NON-NLS-1$
-	static final char[] BOOLEANVALUE_BOOLEAN_METHOD_SIGNATURE = "()Z".toCharArray(); //$NON-NLS-1$
-	static final char[] LONGVALUE_LONG_METHOD_SIGNATURE = "()J".toCharArray(); //$NON-NLS-1$
-	static final char[] GETDECLAREDCONSTRUCTOR_NAME = "getDeclaredConstructor".toCharArray(); //$NON-NLS-1$
-	static final char[] GETDECLAREDCONSTRUCTOR_SIGNATURE = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;".toCharArray(); //$NON-NLS-1$
-	
-	// predefined constant index for well known types
-	static final int JAVA_LANG_REFLECT_FIELD_TYPE = 0;
-	static final int JAVA_LANG_REFLECT_METHOD_TYPE = 1;
-	static final int JAVA_LANG_REFLECT_ACCESSIBLEOBJECT_TYPE = 2;
-	static final int JAVA_LANG_REFLECT_ARRAY_TYPE = 3;
-
-	// predefined constant index for well known methods
-	static final int GETDECLAREDFIELD_CLASS_METHOD = 0;
-	static final int SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD = 1;
-	static final int GET_INT_METHOD = 2;
-	static final int GET_LONG_METHOD = 3;
-	static final int GET_DOUBLE_METHOD = 4;
-	static final int GET_FLOAT_METHOD = 5;
-	static final int GET_BYTE_METHOD = 6;
-	static final int GET_CHAR_METHOD = 7;
-	static final int GET_BOOLEAN_METHOD = 8;
-	static final int GET_OBJECT_METHOD = 9;
-	static final int GET_SHORT_METHOD = 10;
-	static final int SET_INT_METHOD = 11;
-	static final int SET_LONG_METHOD = 12;
-	static final int SET_DOUBLE_METHOD = 13;
-	static final int SET_FLOAT_METHOD = 14;
-	static final int SET_BYTE_METHOD = 15;
-	static final int SET_CHAR_METHOD = 16;
-	static final int SET_BOOLEAN_METHOD = 17;
-	static final int SET_OBJECT_METHOD = 18;
-	static final int SET_SHORT_METHOD = 19;
-	static final int GETDECLAREDMETHOD_CLASS_METHOD = 20;
-	static final int NEWINSTANCE_ARRAY_METHOD = 21;
-	static final int INVOKE_METHOD_METHOD = 22;
-	static final int BYTEVALUE_BYTE_METHOD = 23;
-	static final int SHORTVALUE_SHORT_METHOD = 24;
-	static final int DOUBLEVALUE_DOUBLE_METHOD = 25;
-	static final int FLOATVALUE_FLOAT_METHOD = 26;
-	static final int INTVALUE_INTEGER_METHOD = 27;
-	static final int CHARVALUE_CHARACTER_METHOD = 28;
-	static final int BOOLEANVALUE_BOOLEAN_METHOD = 29;
-	static final int LONGVALUE_LONG_METHOD = 30;
-	static final int GETDECLAREDCONSTRUCTOR_CLASS_METHOD = 31;
-	
-	// predefined constant index for well known name and type for methods
-	static final int GETDECLAREDFIELD_CLASS_METHOD_NAME_AND_TYPE = 0;
-	static final int SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD_NAME_AND_TYPE = 1;
-	static final int GET_INT_METHOD_NAME_AND_TYPE = 2;
-	static final int GET_LONG_METHOD_NAME_AND_TYPE = 3;
-	static final int GET_DOUBLE_METHOD_NAME_AND_TYPE = 4;
-	static final int GET_FLOAT_METHOD_NAME_AND_TYPE = 5;
-	static final int GET_BYTE_METHOD_NAME_AND_TYPE = 6;
-	static final int GET_CHAR_METHOD_NAME_AND_TYPE = 7;
-	static final int GET_BOOLEAN_METHOD_NAME_AND_TYPE = 8;
-	static final int GET_OBJECT_METHOD_NAME_AND_TYPE = 9;
-	static final int GET_SHORT_METHOD_NAME_AND_TYPE = 10;
-	static final int SET_INT_METHOD_NAME_AND_TYPE = 11;
-	static final int SET_LONG_METHOD_NAME_AND_TYPE = 12;
-	static final int SET_DOUBLE_METHOD_NAME_AND_TYPE = 13;
-	static final int SET_FLOAT_METHOD_NAME_AND_TYPE = 14;
-	static final int SET_BYTE_METHOD_NAME_AND_TYPE = 15;
-	static final int SET_CHAR_METHOD_NAME_AND_TYPE = 16;
-	static final int SET_BOOLEAN_METHOD_NAME_AND_TYPE = 17;
-	static final int SET_OBJECT_METHOD_NAME_AND_TYPE = 18;
-	static final int SET_SHORT_METHOD_NAME_AND_TYPE = 19;
-	static final int GETDECLAREDMETHOD_CLASS_METHOD_NAME_AND_TYPE = 20;
-	static final int ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE = 21;
-	static final int INVOKE_METHOD_METHOD_NAME_AND_TYPE = 22;
-	static final int BYTEVALUE_BYTE_METHOD_NAME_AND_TYPE = 23;
-	static final int SHORTVALUE_SHORT_METHOD_NAME_AND_TYPE = 24;
-	static final int DOUBLEVALUE_DOUBLE_METHOD_NAME_AND_TYPE = 25;
-	static final int FLOATVALUE_FLOAT_METHOD_NAME_AND_TYPE = 26;
-	static final int INTVALUE_INTEGER_METHOD_NAME_AND_TYPE = 27;
-	static final int CHARVALUE_CHARACTER_METHOD_NAME_AND_TYPE = 28;
-	static final int BOOLEANVALUE_BOOLEAN_METHOD_NAME_AND_TYPE = 29;
-	static final int LONGVALUE_LONG_METHOD_NAME_AND_TYPE = 30;
-	static final int GETDECLAREDCONSTRUCTOR_CLASS_METHOD_NAME_AND_TYPE = 31;
-	
-	int[] wellKnownTypes = new int[4];
-	int[] wellKnownMethods = new int[32];
-	int[] wellKnownMethodNameAndTypes = new int[32];	
-/**
- * CodeSnippetConstantPool constructor comment.
- * @param classFile org.eclipse.jdt.internal.compiler.ClassFile
- */
-public CodeSnippetConstantPool(org.eclipse.jdt.internal.compiler.ClassFile classFile) {
-	super(classFile);
-}
-/**
- * Return the index of the @methodBinding.
- *
- * Returns -1 if the @methodBinding is not a predefined methodBinding, 
- * the right index otherwise.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- * @return <CODE>int</CODE>
- */
-public int indexOfWellKnownMethodNameAndType(MethodBinding methodBinding) {
-	int index = super.indexOfWellKnownMethodNameAndType(methodBinding);
-	if (index == -1) {
-		char firstChar = methodBinding.selector[0];
-		switch(firstChar) {
-			case 'g':
-				if (methodBinding.parameters.length == 1
-					&& methodBinding.parameters[0].id == T_JavaLangString
-					&& CharOperation.equals(methodBinding.selector, GETDECLAREDFIELD_NAME)
-					&& methodBinding.returnType instanceof ReferenceBinding
-					&& CharOperation.equals(((ReferenceBinding) methodBinding.returnType).compoundName,JAVA_LANG_REFLECT_FIELD)) {
-						return GETDECLAREDFIELD_CLASS_METHOD_NAME_AND_TYPE;
-				}
-				if (methodBinding.parameters.length == 2
-					&& methodBinding.parameters[0].id == T_JavaLangString
-					&& methodBinding.parameters[1].isArrayType()
-					&& ((ArrayBinding) methodBinding.parameters[1]).leafComponentType.id == T_JavaLangClass
-					&& CharOperation.equals(methodBinding.selector, GETDECLAREDMETHOD_NAME)
-					&& methodBinding.returnType instanceof ReferenceBinding
-					&& CharOperation.equals(((ReferenceBinding) methodBinding.returnType).compoundName,JAVA_LANG_REFLECT_METHOD)) {
-						return GETDECLAREDMETHOD_CLASS_METHOD_NAME_AND_TYPE;
-				}
-				if (methodBinding.parameters.length == 1
-					&& methodBinding.parameters[0].isArrayType()
-					&& ((ArrayBinding) methodBinding.parameters[0]).leafComponentType.id == T_JavaLangClass
-					&& CharOperation.equals(methodBinding.selector, GETDECLAREDCONSTRUCTOR_NAME)
-					&& methodBinding.returnType instanceof ReferenceBinding
-					&& CharOperation.equals(((ReferenceBinding) methodBinding.returnType).compoundName,JAVA_LANG_REFLECT_CONSTRUCTOR)) {
-						return GETDECLAREDCONSTRUCTOR_CLASS_METHOD_NAME_AND_TYPE;
-				}
-				if (methodBinding.parameters.length == 1
-					&& methodBinding.parameters[0].id == T_Object) {
-						switch(methodBinding.returnType.id) {
-							case T_int :
-								if (CharOperation.equals(methodBinding.selector, GET_INT_METHOD_NAME)
-									&& methodBinding.returnType.id == T_int) {
-									return GET_INT_METHOD_NAME_AND_TYPE;
-								}
-								break;
-							case T_byte :
-								if (CharOperation.equals(methodBinding.selector, GET_BYTE_METHOD_NAME)
-									&& methodBinding.returnType.id == T_byte) {
-									return GET_BYTE_METHOD_NAME_AND_TYPE;
-								}
-								break;					
-							case T_short :
-								if (CharOperation.equals(methodBinding.selector, GET_SHORT_METHOD_NAME)
-									&& methodBinding.returnType.id == T_short) {
-									return GET_SHORT_METHOD_NAME_AND_TYPE;
-								}
-								break;
-							case T_char :
-								if (CharOperation.equals(methodBinding.selector, GET_CHAR_METHOD_NAME)
-									&& methodBinding.returnType.id == T_char) {
-									return GET_CHAR_METHOD_NAME_AND_TYPE;
-								}
-								break;
-							case T_double :
-								if (CharOperation.equals(methodBinding.selector, GET_DOUBLE_METHOD_NAME)
-									&& methodBinding.returnType.id == T_double) {
-									return GET_DOUBLE_METHOD_NAME_AND_TYPE;
-								}
-								break;
-							case T_float :
-								if (CharOperation.equals(methodBinding.selector, GET_FLOAT_METHOD_NAME)
-									&& methodBinding.returnType.id == T_float) {
-									return GET_FLOAT_METHOD_NAME_AND_TYPE;
-								}
-								break;
-							case T_long :
-								if (CharOperation.equals(methodBinding.selector, GET_LONG_METHOD_NAME)
-									&& methodBinding.returnType.id == T_long) {
-									return GET_LONG_METHOD_NAME_AND_TYPE;
-								}
-								break;
-							case T_boolean :
-								if (CharOperation.equals(methodBinding.selector, GET_BOOLEAN_METHOD_NAME)
-									&& methodBinding.returnType.id == T_boolean) {
-									return GET_BOOLEAN_METHOD_NAME_AND_TYPE;
-								}
-								break;
-							case T_Object :
-								if (CharOperation.equals(methodBinding.selector, GET_OBJECT_METHOD_NAME)
-									&& methodBinding.returnType.id == T_JavaLangObject) {
-									return GET_OBJECT_METHOD_NAME_AND_TYPE;
-								}
-						}
-				}
-				break;
-			case 'i':
-				if (methodBinding.parameters.length == 0
-					&& CharOperation.equals(methodBinding.selector, INTVALUE_INTEGER_METHOD_NAME)
-					&& methodBinding.returnType.id == T_int) {
-						return INTVALUE_INTEGER_METHOD_NAME_AND_TYPE;
-				}
-				if (methodBinding.parameters.length == 2
-					&& methodBinding.parameters[0].id == T_JavaLangObject
-					&& methodBinding.parameters[1].isArrayType()
-					&& ((ArrayBinding) methodBinding.parameters[1]).leafComponentType.id == T_JavaLangObject
-					&& CharOperation.equals(methodBinding.selector, INVOKE_METHOD_METHOD_NAME)
-					&& methodBinding.returnType.id == T_JavaLangObject) {
-						return INVOKE_METHOD_METHOD_NAME_AND_TYPE;
-				}			
-				break;
-			case 's':
-				if (methodBinding.parameters.length == 0
-					&& CharOperation.equals(methodBinding.selector, SHORTVALUE_SHORT_METHOD_NAME)
-					&& methodBinding.returnType.id == T_short) {
-						return SHORTVALUE_SHORT_METHOD_NAME_AND_TYPE;
-				}
-				if (methodBinding.parameters.length == 1
-					&& methodBinding.parameters[0].id == T_boolean
-					&& methodBinding.selector.length == 13
-					&& CharOperation.equals(methodBinding.selector, SETACCESSIBLE_NAME)
-					&& methodBinding.returnType.id == T_void) {
-						return SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD_NAME_AND_TYPE;
-				}
-				if (methodBinding.returnType.id == T_void
-					&& methodBinding.parameters.length == 2
-					&& methodBinding.parameters[0].id == T_Object) {
-						switch(methodBinding.returnType.id) {
-							case T_int :
-								if (methodBinding.parameters[1].id == T_int && CharOperation.equals(methodBinding.selector, SET_INT_METHOD_NAME)
-									&& methodBinding.returnType.id == T_void) {
-									return SET_INT_METHOD_NAME_AND_TYPE;
-								}
-								break;
-							case T_byte :
-								if (methodBinding.parameters[1].id == T_byte && CharOperation.equals(methodBinding.selector, SET_BYTE_METHOD_NAME)
-									&& methodBinding.returnType.id == T_void) {
-									return SET_BYTE_METHOD_NAME_AND_TYPE;
-								}
-								break;					
-							case T_short :
-								if (methodBinding.parameters[1].id == T_short && CharOperation.equals(methodBinding.selector, SET_SHORT_METHOD_NAME)
-									&& methodBinding.returnType.id == T_void) {
-									return SET_SHORT_METHOD_NAME_AND_TYPE;
-								}
-								break;
-							case T_char :
-								if (methodBinding.parameters[1].id == T_char && CharOperation.equals(methodBinding.selector, SET_CHAR_METHOD_NAME)
-									&& methodBinding.returnType.id == T_void) {
-									return SET_CHAR_METHOD_NAME_AND_TYPE;
-								}
-								break;
-							case T_double :
-								if (methodBinding.parameters[1].id == T_double && CharOperation.equals(methodBinding.selector, SET_DOUBLE_METHOD_NAME)
-									&& methodBinding.returnType.id == T_void) {
-									return SET_DOUBLE_METHOD_NAME_AND_TYPE;
-								}
-								break;
-							case T_float :
-								if (methodBinding.parameters[1].id == T_float && CharOperation.equals(methodBinding.selector, SET_FLOAT_METHOD_NAME)
-									&& methodBinding.returnType.id == T_void) {
-									return SET_FLOAT_METHOD_NAME_AND_TYPE;
-								}
-								break;
-							case T_long :
-								if (methodBinding.parameters[1].id == T_long && CharOperation.equals(methodBinding.selector, SET_LONG_METHOD_NAME)
-									&& methodBinding.returnType.id == T_void) {
-									return SET_LONG_METHOD_NAME_AND_TYPE;
-								}
-								break;
-							case T_boolean :
-								if (methodBinding.parameters[1].id == T_boolean && CharOperation.equals(methodBinding.selector, SET_BOOLEAN_METHOD_NAME)
-									&& methodBinding.returnType.id == T_void) {
-									return SET_BOOLEAN_METHOD_NAME_AND_TYPE;
-								}
-								break;
-							case T_Object :
-								if (methodBinding.parameters[1].id == T_Object && CharOperation.equals(methodBinding.selector, SET_OBJECT_METHOD_NAME)
-									&& methodBinding.returnType.id == T_void) {
-									return SET_OBJECT_METHOD_NAME_AND_TYPE;
-								}
-						}
-				}			
-				break;
-			case 'f':
-				if (methodBinding.parameters.length == 0
-					&& CharOperation.equals(methodBinding.selector, FLOATVALUE_FLOAT_METHOD_NAME)
-					&& methodBinding.returnType.id == T_float) {
-						return FLOATVALUE_FLOAT_METHOD_NAME_AND_TYPE;
-				}
-				break;
-			case 'd':
-				if (methodBinding.parameters.length == 0
-					&& CharOperation.equals(methodBinding.selector, DOUBLEVALUE_DOUBLE_METHOD_NAME)
-					&& methodBinding.returnType.id == T_double) {
-						return DOUBLEVALUE_DOUBLE_METHOD_NAME_AND_TYPE;
-				}
-				break;
-			case 'c':
-				if (methodBinding.parameters.length == 0
-					&& CharOperation.equals(methodBinding.selector, CHARVALUE_CHARACTER_METHOD_NAME)
-					&& methodBinding.returnType.id == T_char) {
-						return CHARVALUE_CHARACTER_METHOD_NAME_AND_TYPE;
-				}
-				break;
-			case 'b':
-				if (methodBinding.parameters.length == 0
-					&& CharOperation.equals(methodBinding.selector, BOOLEANVALUE_BOOLEAN_METHOD_NAME)
-					&& methodBinding.returnType.id == T_boolean) {
-						return BOOLEANVALUE_BOOLEAN_METHOD_NAME_AND_TYPE;
-				}
-				if (methodBinding.parameters.length == 0
-					&& CharOperation.equals(methodBinding.selector, BYTEVALUE_BYTE_METHOD_NAME)
-					&& methodBinding.returnType.id == T_byte) {
-						return BYTEVALUE_BYTE_METHOD_NAME_AND_TYPE;
-				}
-				break;
-			case 'l':
-				if (methodBinding.parameters.length == 0
-					&& CharOperation.equals(methodBinding.selector, LONGVALUE_LONG_METHOD_NAME)
-					&& methodBinding.returnType.id == T_long) {
-						return LONGVALUE_LONG_METHOD_NAME_AND_TYPE;
-				}
-				break;
-			case 'n':
-				if (methodBinding.parameters.length == 2
-					&& methodBinding.parameters[0].id == T_JavaLangClass
-					&& methodBinding.parameters[1].isArrayType()
-					&& ((ArrayBinding) methodBinding.parameters[1]).leafComponentType.id == T_int
-					&& CharOperation.equals(methodBinding.selector, ARRAY_NEWINSTANCE_NAME)
-					&& methodBinding.returnType instanceof ReferenceBinding
-					&& CharOperation.equals(((ReferenceBinding) methodBinding.returnType).compoundName,JAVA_LANG_REFLECT_ARRAY)) {
-						return ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE;
-				}
-		}
-
-	}
-	return index;
-}
-/**
- * Return the index of the @methodBinding.
- *
- * Returns -1 if the @methodBinding is not a predefined methodBinding, 
- * the right index otherwise.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- * @return <CODE>int</CODE>
- */
-public int indexOfWellKnownMethods(MethodBinding methodBinding) {
-	int index = super.indexOfWellKnownMethods(methodBinding);
-	if (index == -1) {
-		char firstChar = methodBinding.selector[0];
-		switch(firstChar) {
-			case 'g':
-				if (methodBinding.declaringClass.id == T_JavaLangClass
-					&& methodBinding.parameters.length == 1
-					&& methodBinding.parameters[0].id == T_JavaLangString
-					&& CharOperation.equals(methodBinding.selector, GETDECLAREDFIELD_NAME)) {
-						return GETDECLAREDFIELD_CLASS_METHOD;
-				}
-				if (methodBinding.declaringClass.id == T_JavaLangClass
-					&& methodBinding.parameters.length == 2
-					&& methodBinding.parameters[0].id == T_JavaLangString
-					&& methodBinding.parameters[1].isArrayType()
-					&& ((ArrayBinding) methodBinding.parameters[1]).leafComponentType.id == T_JavaLangClass
-					&& CharOperation.equals(methodBinding.selector, GETDECLAREDMETHOD_NAME)) {
-						return GETDECLAREDMETHOD_CLASS_METHOD;
-				}
-				if (methodBinding.declaringClass.id == T_JavaLangClass
-					&& methodBinding.parameters.length == 1
-					&& methodBinding.parameters[0].isArrayType()
-					&& ((ArrayBinding) methodBinding.parameters[0]).leafComponentType.id == T_JavaLangClass
-					&& CharOperation.equals(methodBinding.selector, GETDECLAREDCONSTRUCTOR_NAME)) {
-						return GETDECLAREDCONSTRUCTOR_CLASS_METHOD;
-				}
-				if (CharOperation.equals(methodBinding.declaringClass.compoundName, JAVA_LANG_REFLECT_FIELD)
-					&& methodBinding.parameters.length == 1
-					&& methodBinding.parameters[0].id == T_Object) {
-						switch(methodBinding.returnType.id) {
-							case T_int :
-								if (CharOperation.equals(methodBinding.selector, GET_INT_METHOD_NAME)) {
-									return GET_INT_METHOD;
-								}
-								break;
-							case T_byte :
-								if (CharOperation.equals(methodBinding.selector, GET_BYTE_METHOD_NAME)) {
-									return GET_BYTE_METHOD;
-								}
-								break;					
-							case T_short :
-								if (CharOperation.equals(methodBinding.selector, GET_SHORT_METHOD_NAME)) {
-									return GET_SHORT_METHOD;
-								}
-								break;
-							case T_char :
-								if (CharOperation.equals(methodBinding.selector, GET_CHAR_METHOD_NAME)) {
-									return GET_CHAR_METHOD;
-								}
-								break;
-							case T_double :
-								if (CharOperation.equals(methodBinding.selector, GET_DOUBLE_METHOD_NAME)) {
-									return GET_DOUBLE_METHOD;
-								}
-								break;
-							case T_float :
-								if (CharOperation.equals(methodBinding.selector, GET_FLOAT_METHOD_NAME)) {
-									return GET_FLOAT_METHOD;
-								}
-								break;
-							case T_long :
-								if (CharOperation.equals(methodBinding.selector, GET_LONG_METHOD_NAME)) {
-									return GET_LONG_METHOD;
-								}
-								break;
-							case T_boolean :
-								if (CharOperation.equals(methodBinding.selector, GET_BOOLEAN_METHOD_NAME)) {
-									return GET_BOOLEAN_METHOD;
-								}
-								break;
-							case T_Object :
-								if (CharOperation.equals(methodBinding.selector, GET_OBJECT_METHOD_NAME)) {
-									return GET_OBJECT_METHOD;
-								}
-						}
-				}
-				break;
-			case 'i':
-				if (methodBinding.declaringClass.id == T_JavaLangInteger
-					&& methodBinding.parameters.length == 0
-					&& CharOperation.equals(methodBinding.selector, INTVALUE_INTEGER_METHOD_NAME)) {
-						return INTVALUE_INTEGER_METHOD;
-				}
-				if (CharOperation.equals(methodBinding.declaringClass.compoundName, JAVA_LANG_REFLECT_METHOD)
-					&& methodBinding.parameters.length == 2
-					&& methodBinding.parameters[0].id == T_JavaLangObject
-					&& methodBinding.parameters[1].isArrayType()
-					&& ((ArrayBinding) methodBinding.parameters[1]).leafComponentType.id == T_JavaLangObject
-					&& CharOperation.equals(methodBinding.selector, INVOKE_METHOD_METHOD_NAME)) {
-						return INVOKE_METHOD_METHOD;
-				}			
-				break;
-			case 'b':
-				if (methodBinding.declaringClass.id == T_JavaLangByte
-					&& methodBinding.parameters.length == 0
-					&& CharOperation.equals(methodBinding.selector, BYTEVALUE_BYTE_METHOD_NAME)) {
-						return BYTEVALUE_BYTE_METHOD;
-				}
-				if (methodBinding.declaringClass.id == T_JavaLangBoolean
-					&& methodBinding.parameters.length == 0
-					&& CharOperation.equals(methodBinding.selector, BOOLEANVALUE_BOOLEAN_METHOD_NAME)) {
-						return BOOLEANVALUE_BOOLEAN_METHOD;
-				}
-				break;
-			case 's': 				
-				if (methodBinding.declaringClass.id == T_JavaLangShort
-					&& methodBinding.parameters.length == 0
-					&& CharOperation.equals(methodBinding.selector, SHORTVALUE_SHORT_METHOD_NAME)) {
-						return SHORTVALUE_SHORT_METHOD;
-				}
-				if (CharOperation.equals(methodBinding.declaringClass.compoundName, JAVA_LANG_REFLECT_ACCESSIBLEOBJECT)
-					&& methodBinding.parameters.length == 1
-					&& methodBinding.parameters[0].id == T_boolean
-					&& methodBinding.selector.length == 13
-					&& CharOperation.equals(methodBinding.selector, SETACCESSIBLE_NAME)) {
-						return SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD;
-				}
-				if (CharOperation.equals(methodBinding.declaringClass.compoundName, JAVA_LANG_REFLECT_FIELD)
-					&& methodBinding.returnType.id == T_void
-					&& methodBinding.parameters.length == 2
-					&& methodBinding.parameters[0].id == T_Object) {
-						switch(methodBinding.returnType.id) {
-							case T_int :
-								if (methodBinding.parameters[1].id == T_int && CharOperation.equals(methodBinding.selector, SET_INT_METHOD_NAME)) {
-									return SET_INT_METHOD;
-								}
-								break;
-							case T_byte :
-								if (methodBinding.parameters[1].id == T_byte && CharOperation.equals(methodBinding.selector, SET_BYTE_METHOD_NAME)) {
-									return SET_BYTE_METHOD;
-								}
-								break;					
-							case T_short :
-								if (methodBinding.parameters[1].id == T_short && CharOperation.equals(methodBinding.selector, SET_SHORT_METHOD_NAME)) {
-									return SET_SHORT_METHOD;
-								}
-								break;
-							case T_char :
-								if (methodBinding.parameters[1].id == T_char && CharOperation.equals(methodBinding.selector, SET_CHAR_METHOD_NAME)) {
-									return SET_CHAR_METHOD;
-								}
-								break;
-							case T_double :
-								if (methodBinding.parameters[1].id == T_double && CharOperation.equals(methodBinding.selector, SET_DOUBLE_METHOD_NAME)) {
-									return SET_DOUBLE_METHOD;
-								}
-								break;
-							case T_float :
-								if (methodBinding.parameters[1].id == T_float && CharOperation.equals(methodBinding.selector, SET_FLOAT_METHOD_NAME)) {
-									return SET_FLOAT_METHOD;
-								}
-								break;
-							case T_long :
-								if (methodBinding.parameters[1].id == T_long && CharOperation.equals(methodBinding.selector, SET_LONG_METHOD_NAME)) {
-									return SET_LONG_METHOD;
-								}
-								break;
-							case T_boolean :
-								if (methodBinding.parameters[1].id == T_boolean && CharOperation.equals(methodBinding.selector, SET_BOOLEAN_METHOD_NAME)) {
-									return SET_BOOLEAN_METHOD;
-								}
-								break;
-							case T_Object :
-								if (methodBinding.parameters[1].id == T_Object && CharOperation.equals(methodBinding.selector, SET_OBJECT_METHOD_NAME)) {
-									return SET_OBJECT_METHOD;
-								}
-						}
-				}			
-				break;
-			case 'f':
-				if (methodBinding.declaringClass.id == T_JavaLangFloat
-					&& methodBinding.parameters.length == 0
-					&& CharOperation.equals(methodBinding.selector, FLOATVALUE_FLOAT_METHOD_NAME)) {
-						return FLOATVALUE_FLOAT_METHOD;
-				}
-				break;
-			case 'd':
-				if (methodBinding.declaringClass.id == T_JavaLangDouble
-					&& methodBinding.parameters.length == 0
-					&& CharOperation.equals(methodBinding.selector, DOUBLEVALUE_DOUBLE_METHOD_NAME)) {
-						return DOUBLEVALUE_DOUBLE_METHOD;
-				}
-				break;
-			case 'c':
-				if (methodBinding.declaringClass.id == T_JavaLangCharacter
-					&& methodBinding.parameters.length == 0
-					&& CharOperation.equals(methodBinding.selector, CHARVALUE_CHARACTER_METHOD_NAME)) {
-						return CHARVALUE_CHARACTER_METHOD;
-				}
-				break;
-			case 'l':
-				if (methodBinding.declaringClass.id == T_JavaLangLong
-					&& methodBinding.parameters.length == 0
-					&& CharOperation.equals(methodBinding.selector, LONGVALUE_LONG_METHOD_NAME)) {
-						return LONGVALUE_LONG_METHOD;
-				}
-				break;
-			case 'n':
-				if (CharOperation.equals(methodBinding.declaringClass.compoundName, JAVA_LANG_REFLECT_ARRAY)
-					&& methodBinding.parameters.length == 2
-					&& methodBinding.parameters[0].id == T_JavaLangClass
-					&& methodBinding.parameters[1].isArrayType()
-					&& ((ArrayBinding) methodBinding.parameters[1]).leafComponentType.id == T_int
-					&& CharOperation.equals(methodBinding.selector, ARRAY_NEWINSTANCE_NAME)) {
-						return NEWINSTANCE_ARRAY_METHOD;
-				}
-				break;
-		}
-	}
-	return index;
-}
-/**
- * Return the index of the @typeBinding
- *
- * Returns -1 if the @typeBinding is not a predefined binding, the right index 
- * otherwise.
- *
- * @param typeBinding org.eclipse.jdt.internal.compiler.lookup.TypeBinding
- * @return <CODE>int</CODE>
- */
-public int indexOfWellKnownTypes(TypeBinding typeBinding) {
-	int index = super.indexOfWellKnownTypes(typeBinding);
-	if (index == -1) {
-		if (!typeBinding.isBaseType() && !typeBinding.isArrayType()) {
-			ReferenceBinding type = (ReferenceBinding) typeBinding;
-			if (type.compoundName.length == 4) {
-				if (CharOperation.equals(JAVA_LANG_REFLECT_FIELD, type.compoundName)) {
-					return JAVA_LANG_REFLECT_FIELD_TYPE;
-				}
-				if (CharOperation.equals(JAVA_LANG_REFLECT_METHOD, type.compoundName)) {
-					return JAVA_LANG_REFLECT_METHOD_TYPE;
-				}
-				if (CharOperation.equals(JAVA_LANG_REFLECT_ARRAY, type.compoundName)) {
-					return JAVA_LANG_REFLECT_ARRAY_TYPE;
-				}
-				if (CharOperation.equals(JAVA_LANG_REFLECT_ACCESSIBLEOBJECT, type.compoundName)) {
-					return JAVA_LANG_REFLECT_ACCESSIBLEOBJECT_TYPE;
-				}
-			}
-		}
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @param aMethodBinding MethodBinding
- * @return <CODE>int</CODE>
- */
-public int literalIndex(MethodBinding aMethodBinding) {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	int indexWellKnownMethod;
-	if ((indexWellKnownMethod = super.indexOfWellKnownMethods(aMethodBinding)) == -1) {
-		if ((indexWellKnownMethod = indexOfWellKnownMethods(aMethodBinding)) == -1) {
-			if (aMethodBinding.declaringClass.isInterface()) {
-				// Lookinf into the interface method ref table
-				if ((index = this.interfaceMethodCache.get(aMethodBinding)) < 0) {
-					classIndex = literalIndex(aMethodBinding.declaringClass);
-					nameAndTypeIndex =
-						literalIndexForMethods(
-							literalIndex(aMethodBinding.constantPoolName()),
-							literalIndex(aMethodBinding.signature()),
-							aMethodBinding);
-					index = this.interfaceMethodCache.put(aMethodBinding, this.currentIndex++);
-					// Write the interface method ref constant into the constant pool
-					// First add the tag
-					writeU1(InterfaceMethodRefTag);
-					// Then write the class index
-					writeU2(classIndex);
-					// The write the nameAndType index
-					writeU2(nameAndTypeIndex);
-				}
-			} else {
-				// Lookinf into the method ref table
-				if ((index = this.methodCache.get(aMethodBinding)) < 0) {
-					classIndex = literalIndex(aMethodBinding.declaringClass);
-					nameAndTypeIndex =
-						literalIndexForMethods(
-							literalIndex(aMethodBinding.constantPoolName()),
-							literalIndex(aMethodBinding.signature()),
-							aMethodBinding);
-					index = this.methodCache.put(aMethodBinding, this.currentIndex++);
-					// Write the method ref constant into the constant pool
-					// First add the tag
-					writeU1(MethodRefTag);
-					// Then write the class index
-					writeU2(classIndex);
-					// The write the nameAndType index
-					writeU2(nameAndTypeIndex);
-				}
-			}
-		} else {
-			// This is a well known method
-			if ((index = this.wellKnownMethods[indexWellKnownMethod]) == 0) {
-				// this methods was not inserted yet
-				if (aMethodBinding.declaringClass.isInterface()) {
-					// Lookinf into the interface method ref table
-					classIndex = literalIndex(aMethodBinding.declaringClass);
-					nameAndTypeIndex =
-						literalIndexForMethods(
-							literalIndex(aMethodBinding.constantPoolName()),
-							literalIndex(aMethodBinding.signature()),
-							aMethodBinding);
-					index = this.wellKnownMethods[indexWellKnownMethod] = this.currentIndex++;
-					// Write the interface method ref constant into the constant pool
-					// First add the tag
-					writeU1(InterfaceMethodRefTag);
-					// Then write the class index
-					writeU2(classIndex);
-					// The write the nameAndType index
-					writeU2(nameAndTypeIndex);
-				} else {
-					// Lookinf into the method ref table
-					classIndex = literalIndex(aMethodBinding.declaringClass);
-					nameAndTypeIndex =
-						literalIndexForMethods(
-							literalIndex(aMethodBinding.constantPoolName()),
-							literalIndex(aMethodBinding.signature()),
-							aMethodBinding);
-					index = this.wellKnownMethods[indexWellKnownMethod] = this.currentIndex++;
-					// Write the method ref constant into the constant pool
-					// First add the tag
-					writeU1(MethodRefTag);
-					// Then write the class index
-					writeU2(classIndex);
-					// The write the nameAndType index
-					writeU2(nameAndTypeIndex);
-				}
-			}
-		}
-	} else {
-		index = super.literalIndex(aMethodBinding);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @param aTypeBinding TypeBinding
- * @return <CODE>int</CODE>
- */
-public int literalIndex(TypeBinding aTypeBinding) {
-	int index;
-	int nameIndex;
-	int indexWellKnownType;
-	if ((indexWellKnownType = super.indexOfWellKnownTypes(aTypeBinding)) == -1) {
-		if ((indexWellKnownType = indexOfWellKnownTypes(aTypeBinding)) == -1) {
-			if ((index = this.classCache.get(aTypeBinding)) < 0) {
-				// The entry doesn't exit yet
-				nameIndex = literalIndex(aTypeBinding.constantPoolName());
-				index = this.classCache.put(aTypeBinding, this.currentIndex++);
-				writeU1(ClassTag);
-				// Then add the 8 bytes representing the long
-				writeU2(nameIndex);
-			}
-		} else {
-			if ((index = this.wellKnownTypes[indexWellKnownType]) == 0) {
-				// Need to insert that binding
-				nameIndex = literalIndex(aTypeBinding.constantPoolName());
-				index = this.wellKnownTypes[indexWellKnownType] = this.currentIndex++;
-				writeU1(ClassTag);
-				// Then add the 8 bytes representing the long
-				writeU2(nameIndex);
-			}
-		}
-	} else {
-		index = super.literalIndex(aTypeBinding);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangBooleanBooleanValue() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = this.wellKnownMethods[BOOLEANVALUE_BOOLEAN_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangBoolean();
-		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[BOOLEANVALUE_BOOLEAN_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(BOOLEANVALUE_BOOLEAN_METHOD_NAME);
-			int typeIndex = literalIndex(BOOLEANVALUE_BOOLEAN_METHOD_SIGNATURE);
-			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[BOOLEANVALUE_BOOLEAN_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = this.wellKnownMethods[BOOLEANVALUE_BOOLEAN_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangByteByteValue() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = this.wellKnownMethods[BYTEVALUE_BYTE_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangByte();
-		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[BYTEVALUE_BYTE_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(BYTEVALUE_BYTE_METHOD_NAME);
-			int typeIndex = literalIndex(BYTEVALUE_BYTE_METHOD_SIGNATURE);
-			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[BYTEVALUE_BYTE_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = this.wellKnownMethods[BYTEVALUE_BYTE_METHOD] = this.currentIndex++;
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangCharacterCharValue() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = this.wellKnownMethods[CHARVALUE_CHARACTER_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangCharacter();
-		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[CHARVALUE_CHARACTER_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(CHARVALUE_CHARACTER_METHOD_NAME);
-			int typeIndex = literalIndex(CHARVALUE_CHARACTER_METHOD_SIGNATURE);
-			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[CHARVALUE_CHARACTER_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = this.wellKnownMethods[CHARVALUE_CHARACTER_METHOD] = this.currentIndex++;
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangClassGetDeclaredConstructor() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = this.wellKnownMethods[GETDECLAREDCONSTRUCTOR_CLASS_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangClass();
-		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[GETDECLAREDCONSTRUCTOR_CLASS_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(GETDECLAREDCONSTRUCTOR_NAME);
-			int typeIndex = literalIndex(GETDECLAREDCONSTRUCTOR_SIGNATURE);
-			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[GETDECLAREDCONSTRUCTOR_CLASS_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = this.wellKnownMethods[GETDECLAREDCONSTRUCTOR_CLASS_METHOD] = this.currentIndex++;
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangClassGetDeclaredField() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = this.wellKnownMethods[GETDECLAREDFIELD_CLASS_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangClass();
-		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[GETDECLAREDFIELD_CLASS_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(GETDECLAREDFIELD_NAME);
-			int typeIndex = literalIndex(GETDECLAREDFIELD_SIGNATURE);
-			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[GETDECLAREDFIELD_CLASS_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = this.wellKnownMethods[GETDECLAREDFIELD_CLASS_METHOD] = this.currentIndex++;
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangClassGetDeclaredMethod() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = this.wellKnownMethods[GETDECLAREDMETHOD_CLASS_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangClass();
-		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[GETDECLAREDMETHOD_CLASS_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(GETDECLAREDMETHOD_NAME);
-			int typeIndex = literalIndex(GETDECLAREDMETHOD_SIGNATURE);
-			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[GETDECLAREDMETHOD_CLASS_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = this.wellKnownMethods[GETDECLAREDMETHOD_CLASS_METHOD] = this.currentIndex++;
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangDoubleDoubleValue() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = this.wellKnownMethods[DOUBLEVALUE_DOUBLE_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangDouble();
-		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[DOUBLEVALUE_DOUBLE_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(DOUBLEVALUE_DOUBLE_METHOD_NAME);
-			int typeIndex = literalIndex(DOUBLEVALUE_DOUBLE_METHOD_SIGNATURE);
-			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[DOUBLEVALUE_DOUBLE_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = this.wellKnownMethods[DOUBLEVALUE_DOUBLE_METHOD] = this.currentIndex++;
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangFloatFloatValue() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = this.wellKnownMethods[FLOATVALUE_FLOAT_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangFloat();
-		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[FLOATVALUE_FLOAT_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(FLOATVALUE_FLOAT_METHOD_NAME);
-			int typeIndex = literalIndex(FLOATVALUE_FLOAT_METHOD_SIGNATURE);
-			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[FLOATVALUE_FLOAT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = this.wellKnownMethods[FLOATVALUE_FLOAT_METHOD] = this.currentIndex++;
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangIntegerIntValue() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = this.wellKnownMethods[INTVALUE_INTEGER_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangInteger();
-		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[INTVALUE_INTEGER_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(INTVALUE_INTEGER_METHOD_NAME);
-			int typeIndex = literalIndex(INTVALUE_INTEGER_METHOD_SIGNATURE);
-			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[INTVALUE_INTEGER_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = this.wellKnownMethods[INTVALUE_INTEGER_METHOD] = this.currentIndex++;
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangLongLongValue() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = this.wellKnownMethods[LONGVALUE_LONG_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangLong();
-		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[LONGVALUE_LONG_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(LONGVALUE_LONG_METHOD_NAME);
-			int typeIndex = literalIndex(LONGVALUE_LONG_METHOD_SIGNATURE);
-			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[LONGVALUE_LONG_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = this.wellKnownMethods[LONGVALUE_LONG_METHOD] = this.currentIndex++;
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangReflectAccessibleObject() {
-	int index;
-	if ((index = this.wellKnownTypes[JAVA_LANG_REFLECT_ACCESSIBLEOBJECT_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(JAVALANGREFLECTACCESSIBLEOBJECT_CONSTANTPOOLNAME);
-		index = this.wellKnownTypes[JAVA_LANG_REFLECT_ACCESSIBLEOBJECT_TYPE] = this.currentIndex++;
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangReflectAccessibleObjectSetAccessible() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = this.wellKnownMethods[SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangReflectAccessibleObject();
-		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(SETACCESSIBLE_NAME);
-			int typeIndex = literalIndex(SETACCESSIBLE_SIGNATURE);
-			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = this.wellKnownMethods[SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD] = this.currentIndex++;
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangReflectArray() {
-	int index;
-	if ((index = this.wellKnownTypes[JAVA_LANG_REFLECT_ARRAY_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(JAVALANGREFLECTARRAY_CONSTANTPOOLNAME);
-		index = this.wellKnownTypes[JAVA_LANG_REFLECT_ARRAY_TYPE] = this.currentIndex++;
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangReflectArrayNewInstance() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = this.wellKnownMethods[NEWINSTANCE_ARRAY_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangReflectArray();
-		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(ARRAY_NEWINSTANCE_NAME);
-			int typeIndex = literalIndex(ARRAY_NEWINSTANCE_SIGNATURE);
-			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = this.wellKnownMethods[NEWINSTANCE_ARRAY_METHOD] = this.currentIndex++;
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangReflectField() {
-	int index;
-	if ((index = this.wellKnownTypes[JAVA_LANG_REFLECT_FIELD_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(JAVALANGREFLECTFIELD_CONSTANTPOOLNAME);
-		index = this.wellKnownTypes[JAVA_LANG_REFLECT_FIELD_TYPE] = this.currentIndex++;
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangReflectMethod() {
-	int index;
-	if ((index = this.wellKnownTypes[JAVA_LANG_REFLECT_METHOD_TYPE]) == 0) {
-		int nameIndex;
-		// The entry doesn't exit yet
-		nameIndex = literalIndex(JAVALANGREFLECTMETHOD_CONSTANTPOOLNAME);
-		index = this.wellKnownTypes[JAVA_LANG_REFLECT_METHOD_TYPE] = this.currentIndex++;
-		writeU1(ClassTag);
-		// Then add the 8 bytes representing the long
-		writeU2(nameIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangReflectMethodInvoke() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = this.wellKnownMethods[INVOKE_METHOD_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangReflectMethod();
-		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[INVOKE_METHOD_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(INVOKE_METHOD_METHOD_NAME);
-			int typeIndex = literalIndex(INVOKE_METHOD_METHOD_SIGNATURE);
-			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[INVOKE_METHOD_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = this.wellKnownMethods[INVOKE_METHOD_METHOD] = this.currentIndex++;
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexForJavaLangShortShortValue() {
-	int index;
-	int nameAndTypeIndex;
-	int classIndex;
-	// Looking into the method ref table
-	if ((index = this.wellKnownMethods[SHORTVALUE_SHORT_METHOD]) == 0) {
-		classIndex = literalIndexForJavaLangShort();
-		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[SHORTVALUE_SHORT_METHOD_NAME_AND_TYPE]) == 0) {
-			int nameIndex = literalIndex(SHORTVALUE_SHORT_METHOD_NAME);
-			int typeIndex = literalIndex(SHORTVALUE_SHORT_METHOD_SIGNATURE);
-			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[SHORTVALUE_SHORT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-			writeU1(NameAndTypeTag);
-			writeU2(nameIndex);
-			writeU2(typeIndex);
-		}
-		index = this.wellKnownMethods[SHORTVALUE_SHORT_METHOD] = this.currentIndex++;
-		// Write the method ref constant into the constant pool
-		// First add the tag
-		writeU1(MethodRefTag);
-		// Then write the class index
-		writeU2(classIndex);
-		// The write the nameAndType index
-		writeU2(nameAndTypeIndex);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding 
- * nameAndType constant with nameIndex, typeIndex.
- *
- * @param nameIndex int
- * @param typeIndex int
- * @param key org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- * @return <CODE>int</CODE>
- */
-public int literalIndexForMethods(int nameIndex, int typeIndex, MethodBinding key) {
-	int index;
-	int indexOfWellKnownMethodNameAndType;
-	if ((indexOfWellKnownMethodNameAndType = super.indexOfWellKnownMethodNameAndType(key)) == -1) {
-		if ((indexOfWellKnownMethodNameAndType = indexOfWellKnownMethodNameAndType(key)) == -1) {
-			// check if the entry exists
-			if ((index = this.nameAndTypeCacheForMethods.get(key)) == -1) {
-				// The entry doesn't exit yet
-				index = this.nameAndTypeCacheForMethods.put(key, this.currentIndex++);
-				writeU1(NameAndTypeTag);
-				writeU2(nameIndex);
-				writeU2(typeIndex);
-			}
-		} else {
-			if ((index = this.wellKnownMethodNameAndTypes[indexOfWellKnownMethodNameAndType]) == 0) {
-				index = this.wellKnownMethodNameAndTypes[indexOfWellKnownMethodNameAndType] = this.currentIndex++;
-				writeU1(NameAndTypeTag);
-				writeU2(nameIndex);
-				writeU2(typeIndex);
-			}
-		}
-	} else {
-		index = super.literalIndexForMethods(nameIndex,typeIndex,key);
-	}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexJavaLangReflectFieldGetter(int typeID) {
-	int index = 0;
-	int nameAndTypeIndex = 0;
-	int classIndex = 0;
-	switch (typeID) {
-		case T_int :
-			if ((index = this.wellKnownMethods[GET_INT_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[GET_INT_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(GET_INT_METHOD_NAME);
-					int typeIndex = literalIndex(GET_INT_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[GET_INT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[GET_INT_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_byte :
-			if ((index = this.wellKnownMethods[GET_BYTE_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[GET_BYTE_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(GET_BYTE_METHOD_NAME);
-					int typeIndex = literalIndex(GET_BYTE_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[GET_BYTE_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[GET_BYTE_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_short :
-			if ((index = this.wellKnownMethods[GET_SHORT_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[GET_SHORT_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(GET_SHORT_METHOD_NAME);
-					int typeIndex = literalIndex(GET_SHORT_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[GET_SHORT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[GET_SHORT_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_long :
-			if ((index = this.wellKnownMethods[GET_LONG_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[GET_LONG_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(GET_LONG_METHOD_NAME);
-					int typeIndex = literalIndex(GET_LONG_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[GET_LONG_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[GET_LONG_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_float :
-			if ((index = this.wellKnownMethods[GET_FLOAT_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[GET_FLOAT_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(GET_FLOAT_METHOD_NAME);
-					int typeIndex = literalIndex(GET_FLOAT_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[GET_FLOAT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[GET_FLOAT_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_double :
-			if ((index = this.wellKnownMethods[GET_DOUBLE_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[GET_DOUBLE_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(GET_DOUBLE_METHOD_NAME);
-					int typeIndex = literalIndex(GET_DOUBLE_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[GET_DOUBLE_METHOD_NAME_AND_TYPE] =
-							this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[GET_DOUBLE_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_char :
-			if ((index = this.wellKnownMethods[GET_CHAR_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[GET_CHAR_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(GET_CHAR_METHOD_NAME);
-					int typeIndex = literalIndex(GET_CHAR_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[GET_CHAR_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[GET_CHAR_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_boolean :
-			if ((index = this.wellKnownMethods[GET_BOOLEAN_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[GET_BOOLEAN_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(GET_BOOLEAN_METHOD_NAME);
-					int typeIndex = literalIndex(GET_BOOLEAN_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[GET_BOOLEAN_METHOD_NAME_AND_TYPE] =
-							this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[GET_BOOLEAN_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		default :
-			if ((index = this.wellKnownMethods[GET_OBJECT_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[GET_OBJECT_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(GET_OBJECT_METHOD_NAME);
-					int typeIndex = literalIndex(GET_OBJECT_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[GET_OBJECT_METHOD_NAME_AND_TYPE] =
-							this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[GET_OBJECT_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-		}
-	return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the 
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return <CODE>int</CODE>
- */
-public int literalIndexJavaLangReflectFieldSetter(int typeID) {
-	int index = 0;
-	int nameAndTypeIndex = 0;
-	int classIndex = 0;
-	switch (typeID) {
-		case T_int :
-			if ((index = this.wellKnownMethods[SET_INT_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[SET_INT_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(SET_INT_METHOD_NAME);
-					int typeIndex = literalIndex(SET_INT_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[SET_INT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[SET_INT_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_byte :
-			if ((index = this.wellKnownMethods[SET_BYTE_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[SET_BYTE_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(SET_BYTE_METHOD_NAME);
-					int typeIndex = literalIndex(SET_BYTE_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[SET_BYTE_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[SET_BYTE_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_short :
-			if ((index = this.wellKnownMethods[SET_SHORT_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[SET_SHORT_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(SET_SHORT_METHOD_NAME);
-					int typeIndex = literalIndex(SET_SHORT_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[SET_SHORT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[SET_SHORT_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_long :
-			if ((index = this.wellKnownMethods[SET_LONG_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[SET_LONG_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(SET_LONG_METHOD_NAME);
-					int typeIndex = literalIndex(SET_LONG_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[SET_LONG_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[SET_LONG_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_float :
-			if ((index = this.wellKnownMethods[SET_FLOAT_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[SET_FLOAT_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(SET_FLOAT_METHOD_NAME);
-					int typeIndex = literalIndex(SET_FLOAT_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[SET_FLOAT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[SET_FLOAT_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_double :
-			if ((index = this.wellKnownMethods[SET_DOUBLE_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[SET_DOUBLE_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(SET_DOUBLE_METHOD_NAME);
-					int typeIndex = literalIndex(SET_DOUBLE_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[SET_DOUBLE_METHOD_NAME_AND_TYPE] =
-							this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[SET_DOUBLE_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_char :
-			if ((index = this.wellKnownMethods[SET_CHAR_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[SET_CHAR_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(SET_CHAR_METHOD_NAME);
-					int typeIndex = literalIndex(SET_CHAR_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[SET_CHAR_METHOD_NAME_AND_TYPE] = this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[SET_CHAR_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		case T_boolean :
-			if ((index = this.wellKnownMethods[SET_BOOLEAN_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[SET_BOOLEAN_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(SET_BOOLEAN_METHOD_NAME);
-					int typeIndex = literalIndex(SET_BOOLEAN_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[SET_BOOLEAN_METHOD_NAME_AND_TYPE] =
-							this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[SET_BOOLEAN_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-			break;
-		default :
-			if ((index = this.wellKnownMethods[SET_OBJECT_METHOD]) == 0) {
-				classIndex = literalIndexForJavaLangReflectField();
-				if ((nameAndTypeIndex =
-					this.wellKnownMethodNameAndTypes[SET_OBJECT_METHOD_NAME_AND_TYPE])
-					== 0) {
-					int nameIndex = literalIndex(SET_OBJECT_METHOD_NAME);
-					int typeIndex = literalIndex(SET_OBJECT_METHOD_SIGNATURE);
-					nameAndTypeIndex =
-						this.wellKnownMethodNameAndTypes[SET_OBJECT_METHOD_NAME_AND_TYPE] =
-							this.currentIndex++;
-					writeU1(NameAndTypeTag);
-					writeU2(nameIndex);
-					writeU2(typeIndex);
-				}
-				index = this.wellKnownMethods[SET_OBJECT_METHOD] = this.currentIndex++;
-				// Write the method ref constant into the constant pool
-				// First add the tag
-				writeU1(MethodRefTag);
-				// Then write the class index
-				writeU2(classIndex);
-				// The write the nameAndType index
-				writeU2(nameAndTypeIndex);
-			}
-		}
-	return index;
-}
-}
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEnvironment.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEnvironment.java
index 38fa6eb..19a8979 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEnvironment.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEnvironment.java
@@ -47,7 +47,7 @@
 		if (binary == null) {
 			return null;
 		} else {
-			return new NameEnvironmentAnswer(binary);
+			return new NameEnvironmentAnswer(binary, null /*no access restriction*/);
 		}
 	}
 	VariablesInfo installedVars = this.context.installedVars;
@@ -62,7 +62,7 @@
 				e.printStackTrace();  // Should never happen since we compiled this type
 				return null;
 			}
-			return new NameEnvironmentAnswer(binary);
+			return new NameEnvironmentAnswer(binary, null /*no access restriction*/);
 		}
 	}
 	return null;
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEvaluator.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEvaluator.java
index b483408..7f1e743 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEvaluator.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEvaluator.java
@@ -129,7 +129,7 @@
 		// Initialize the compiler's lookup environment with the already compiled super classes
 		IBinaryType binary = this.context.getRootCodeSnippetBinary();
 		if (binary != null) {
-			compiler.lookupEnvironment.cacheBinaryType(binary);
+			compiler.lookupEnvironment.cacheBinaryType(binary, null /*no access restriction*/);
 		}
 		VariablesInfo installedVars = this.context.installedVars;
 		if (installedVars != null) {
@@ -141,7 +141,7 @@
 				} catch (ClassFormatException e) {
 					e.printStackTrace(); // Should never happen since we compiled this type
 				}
-				compiler.lookupEnvironment.cacheBinaryType(binaryType);
+				compiler.lookupEnvironment.cacheBinaryType(binaryType, null /*no access restriction*/);
 			}
 		}
 	} else {
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java
index c95c975..c6978b4 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java
@@ -20,10 +20,12 @@
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedFieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
 
 public class CodeSnippetFieldReference extends FieldReference implements ProblemReasons, EvaluationConstants {
 
@@ -82,7 +84,7 @@
 		boolean isStatic = this.codegenBinding.isStatic();
 		this.receiver.generateCode(currentScope, codeStream, !isStatic);
 		if (valueRequired) {
-			if (this.codegenBinding.constant == NotAConstant) {
+			if (!this.codegenBinding.isConstantValue()) {
 				if (this.codegenBinding.declaringClass == null) { // array length
 					codeStream.arraylength();
 				} else {
@@ -106,7 +108,7 @@
 					codeStream.invokeObjectGetClass(); // perform null check
 					codeStream.pop();
 				}
-				codeStream.generateConstant(this.codegenBinding.constant, this.implicitConversion);
+				codeStream.generateConstant(this.codegenBinding.constant(), this.implicitConversion);
 			}
 		} else {
 			if (!isStatic){
@@ -130,21 +132,25 @@
 			codeStream.getfield(this.codegenBinding);
 		}
 		int operationTypeID;
-		if ((operationTypeID = this.implicitConversion >> 4) == T_String) {
-			codeStream.generateStringAppend(currentScope, null, expression);
-		} else {
-			// promote the array reference to the suitable operation type
-			codeStream.generateImplicitConversion(this.implicitConversion);
-			// generate the increment value (will by itself  be promoted to the operation value)
-			if (expression == IntLiteral.One){ // prefix operation
-				codeStream.generateConstant(expression.constant, this.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);
+		switch(operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
+			case T_JavaLangString :
+			case T_JavaLangObject :
+			case T_undefined :
+				codeStream.generateStringConcatenationAppend(currentScope, null, expression);
+				break;
+			default :
+				// promote the array reference to the suitable operation type
+				codeStream.generateImplicitConversion(this.implicitConversion);
+				// generate the increment value (will by itself  be promoted to the operation value)
+				if (expression == IntLiteral.One){ // prefix operation
+					codeStream.generateConstant(expression.constant, this.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, null, valueRequired);
 	} else {
@@ -168,8 +174,8 @@
 							
 		}
 		int operationTypeID;
-		if ((operationTypeID = this.implicitConversion >> 4) == T_String) {
-			codeStream.generateStringAppend(currentScope, null, expression);
+		if ((operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_JavaLangString) {
+			codeStream.generateStringConcatenationAppend(currentScope, null, expression);
 		} else {
 			// promote the array reference to the suitable operation type
 			codeStream.generateImplicitConversion(this.implicitConversion);
@@ -280,63 +286,46 @@
 /*
  * No need to emulate access to protected fields since not implicitly accessed
  */
-public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo){
+public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess){
 	// The private access will be managed through the code generation
 
 	if (!flowInfo.isReachable()) return;
-	
-	// if the binding declaring class is not visible, need special action
-	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
-	// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
-	if (this.delegateThis != null) {
-		if (this.binding.declaringClass != this.delegateThis.type
-			&& this.binding.declaringClass != null
-			&& this.binding.constant == NotAConstant
-			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2 
-					&& !this.binding.isStatic()
-					&& this.binding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
-				|| !this.binding.declaringClass.canBeSeenBy(currentScope))){
-			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(this.binding, (ReferenceBinding)this.delegateThis.type);
-		}
-	} else if (this.binding.declaringClass != this.receiverType
-		&& !this.receiverType.isArrayType()
-		&& this.binding.declaringClass != null // array.length
-		&& this.binding.constant == NotAConstant
-		&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
-				&& this.binding.declaringClass.id != T_Object) //no change for Object fields (in case there was)
-			|| !this.binding.declaringClass.canBeSeenBy(currentScope))){
-			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(this.binding, (ReferenceBinding) this.receiverType);
+	// if field from parameterized type got found, use the original field at codegen time
+	if (this.binding instanceof ParameterizedFieldBinding) {
+	    ParameterizedFieldBinding parameterizedField = (ParameterizedFieldBinding) this.binding;
+	    this.codegenBinding = parameterizedField.originalField;
+	    // extra cast needed if field type was type variable
+	    if (this.codegenBinding.type.isTypeVariable()) {
+	        TypeVariableBinding variableReturnType = (TypeVariableBinding) this.codegenBinding.type;
+	        if (variableReturnType.firstBound != parameterizedField.type) { // no need for extra cast if same as first bound anyway
+			    this.genericCast = parameterizedField.type.erasure();
+	        }
+	    }
+	} else {
+	    this.codegenBinding = this.binding;
 	}
-}
-/*
- * No need to emulate access to protected fields since not implicitly accessed
- */
-public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo){
-	// The private access will be managed through the code generation
-
-	if (!flowInfo.isReachable()) return;
-	
+		
 	// if the binding declaring class is not visible, need special action
 	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
 	// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
 	if (this.delegateThis != null) {
 		if (this.binding.declaringClass != this.delegateThis.type
 			&& this.binding.declaringClass != null
-			&& this.binding.constant == NotAConstant
+			&& !this.binding.isConstantValue()
 			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2 
 					&& !this.binding.isStatic()
-					&& this.binding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
-				|| !this.binding.declaringClass.canBeSeenBy(currentScope))){
-			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(this.binding, (ReferenceBinding)this.delegateThis.type);
+					&& this.binding.declaringClass.id != T_JavaLangObject) // no change for Object fields (if there was any)
+				|| !this.codegenBinding.declaringClass.canBeSeenBy(currentScope))){
+			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(this.codegenBinding, (ReferenceBinding)this.delegateThis.type.erasure());
 		}
 	} else if (this.binding.declaringClass != this.receiverType
 		&& !this.receiverType.isArrayType()
 		&& this.binding.declaringClass != null // array.length
-		&& this.binding.constant == NotAConstant
+		&& !this.binding.isConstantValue()
 		&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
-				&& this.binding.declaringClass.id != T_Object) //no change for Object fields (in case there was)
-			|| !this.binding.declaringClass.canBeSeenBy(currentScope))){
-			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(this.binding, (ReferenceBinding) this.receiverType);
+				&& this.binding.declaringClass.id != T_JavaLangObject) //no change for Object fields (in case there was)
+			|| !this.codegenBinding.declaringClass.canBeSeenBy(currentScope))){
+			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(this.codegenBinding, (ReferenceBinding) this.receiverType.erasure());
 	}
 }
 public TypeBinding resolveType(BlockScope scope) {
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java
index 3ee1b92..7d92c90 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java
@@ -15,8 +15,7 @@
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
-import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
-import org.eclipse.jdt.internal.compiler.lookup.BindingIds;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
@@ -25,6 +24,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
 
 public class CodeSnippetMessageSend extends MessageSend implements ProblemReasons, EvaluationConstants {
 	EvaluationContext evaluationContext;
@@ -49,9 +49,9 @@
 
 	int pc = codeStream.position;
 
-	if (this.binding.canBeSeenBy(this.receiverType, this, currentScope)) {
+	if (this.codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) {
 		// generate receiver/enclosing instance access
-		boolean isStatic = this.binding.isStatic();
+		boolean isStatic = this.codegenBinding.isStatic();
 		// outer access ?
 		if (!isStatic && ((this.bits & DepthMASK) != 0)) {
 			// outer method can be reached through emulation
@@ -74,22 +74,22 @@
 		}
 		// actual message invocation
 		if (isStatic) {
-			codeStream.invokestatic(this.binding);
+			codeStream.invokestatic(this.codegenBinding);
 		} else {
 			if (this.receiver.isSuper()) {
-				codeStream.invokespecial(this.binding);
+				codeStream.invokespecial(this.codegenBinding);
 			} else {
-				if (this.binding.declaringClass.isInterface()) {
-					codeStream.invokeinterface(this.binding);
+				if (this.codegenBinding.declaringClass.isInterface()) {
+					codeStream.invokeinterface(this.codegenBinding);
 				} else {
-					codeStream.invokevirtual(this.binding);
+					codeStream.invokevirtual(this.codegenBinding);
 				}
 			}
 		}
 	} else {
-		((CodeSnippetCodeStream) codeStream).generateEmulationForMethod(currentScope, this.binding);
+		((CodeSnippetCodeStream) codeStream).generateEmulationForMethod(currentScope, this.codegenBinding);
 		// generate receiver/enclosing instance access
-		boolean isStatic = this.binding.isStatic();
+		boolean isStatic = this.codegenBinding.isStatic();
 		// outer access ?
 		if (!isStatic && ((this.bits & DepthMASK) != 0)) {
 			// not supported yet
@@ -105,14 +105,14 @@
 		if (this.arguments != null) {
 			int argsLength = this.arguments.length;
 			codeStream.generateInlinedValue(argsLength);
-			codeStream.newArray(currentScope, new ArrayBinding(currentScope.getType(TypeConstants.JAVA_LANG_OBJECT), 1));
+			codeStream.newArray(currentScope.createArrayType(currentScope.getType(TypeConstants.JAVA_LANG_OBJECT, 3), 1));
 			codeStream.dup();
 			for (int i = 0; i < argsLength; i++) {
 				codeStream.generateInlinedValue(i);
 				this.arguments[i].generateCode(currentScope, codeStream, true);
-				TypeBinding parameterBinding = this.binding.parameters[i];
+				TypeBinding parameterBinding = this.codegenBinding.parameters[i];
 				if (parameterBinding.isBaseType() && parameterBinding != NullBinding) {
-					((CodeSnippetCodeStream)codeStream).generateObjectWrapperForType(this.binding.parameters[i]);
+					((CodeSnippetCodeStream)codeStream).generateObjectWrapperForType(this.codegenBinding.parameters[i]);
 				}
 				codeStream.aastore();
 				if (i < argsLength - 1) {
@@ -121,13 +121,13 @@
 			}
 		} else {
 			codeStream.generateInlinedValue(0);
-			codeStream.newArray(currentScope, new ArrayBinding(currentScope.getType(TypeConstants.JAVA_LANG_OBJECT), 1));			
+			codeStream.newArray(currentScope.createArrayType(currentScope.getType(TypeConstants.JAVA_LANG_OBJECT, 3), 1));			
 		}
 		((CodeSnippetCodeStream) codeStream).invokeJavaLangReflectMethodInvoke();
 
 		// convert the return value to the appropriate type for primitive types
-		if (this.binding.returnType.isBaseType()) {
-			int typeID = this.binding.returnType.id;
+		if (this.codegenBinding.returnType.isBaseType()) {
+			int typeID = this.codegenBinding.returnType.id;
 			if (typeID == T_void) {
 				// remove the null from the stack
 				codeStream.pop();
@@ -135,7 +135,7 @@
 			((CodeSnippetCodeStream) codeStream).checkcast(typeID);
 			((CodeSnippetCodeStream) codeStream).getBaseTypeValue(typeID);
 		} else {
-			codeStream.checkcast(this.binding.returnType);
+			codeStream.checkcast(this.codegenBinding.returnType);
 		}
 	}
 	// operation on the returned value
@@ -144,7 +144,7 @@
 		codeStream.generateImplicitConversion(this.implicitConversion);
 	} else {
 		// pop return value if any
-		switch (this.binding.returnType.id) {
+		switch (this.codegenBinding.returnType.id) {
 			case T_long :
 			case T_double :
 				codeStream.pop2();
@@ -155,23 +155,36 @@
 				codeStream.pop();
 		}
 	}
+	// TODO (philippe) need to revise codegen to include genericCast
 	codeStream.recordPositionsFrom(pc, this.sourceStart);
 }
 public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 
 	if (!flowInfo.isReachable()) return;
+
+	// if method from parameterized type got found, use the original method at codegen time
+	this.codegenBinding = this.binding.original();
+	if (this.codegenBinding != this.binding) {
+	    // extra cast needed if method return type was type variable
+	    if (this.codegenBinding.returnType.isTypeVariable()) {
+	        TypeVariableBinding variableReturnType = (TypeVariableBinding) this.codegenBinding.returnType;
+	        if (variableReturnType.firstBound != this.binding.returnType) { // no need for extra cast if same as first bound anyway
+			    this.valueCast = this.binding.returnType;
+	        }
+	    }
+	} 
 	
 	// if the binding declaring class is not visible, need special action
 	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
 	// NOTE: from target 1.2 on, method's declaring class is touched if any different from receiver type
 	// and not from Object or implicit static method call.	
-	if (this.binding.declaringClass != this.qualifyingType
-		&& !this.qualifyingType.isArrayType()
+	if (this.binding.declaringClass != this.actualReceiverType
+		&& !this.actualReceiverType.isArrayType()
 		&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
-				&& (!this.receiver.isImplicitThis() || !this.binding.isStatic())
-				&& this.binding.declaringClass.id != T_Object) // no change for Object methods
-			|| !this.binding.declaringClass.canBeSeenBy(currentScope))) {
-		this.codegenBinding = currentScope.enclosingSourceType().getUpdatedMethodBinding(this.binding, (ReferenceBinding) this.qualifyingType);
+				&& (!this.receiver.isImplicitThis() || !this.codegenBinding.isStatic())
+				&& this.binding.declaringClass.id != T_JavaLangObject) // no change for Object methods
+			|| !this.codegenBinding.declaringClass.canBeSeenBy(currentScope))) {
+		this.codegenBinding = currentScope.enclosingSourceType().getUpdatedMethodBinding(this.codegenBinding, (ReferenceBinding) this.actualReceiverType.erasure());
 	}	
 }
 public TypeBinding resolveType(BlockScope scope) {
@@ -179,7 +192,7 @@
 	// Base type promotion
 
 	this.constant = NotAConstant;
-	this.qualifyingType = this.receiverType = this.receiver.resolveType(scope); 
+	this.actualReceiverType = this.receiver.resolveType(scope); 
 	// will check for null after args are resolved
 	TypeBinding[] argumentTypes = NoParameters;
 	if (this.arguments != null) {
@@ -192,19 +205,19 @@
 		if (argHasError)
 			return null;
 	}
-	if (this.receiverType == null) 
+	if (this.actualReceiverType == null) 
 		return null;
 
 	// base type cannot receive any message
-	if (this.receiverType.isBaseType()) {
-		scope.problemReporter().errorNoMethodFor(this, this.receiverType, argumentTypes);
+	if (this.actualReceiverType.isBaseType()) {
+		scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
 		return null;
 	}
 
 	this.binding = 
 		this.receiver.isImplicitThis()
 			? scope.getImplicitMethod(this.selector, argumentTypes, this)
-			: scope.getMethod(this.receiverType, this.selector, argumentTypes, this); 
+			: scope.getMethod(this.actualReceiverType, this.selector, argumentTypes, this); 
 	if (!this.binding.isValidBinding()) {
 		if (this.binding instanceof ProblemMethodBinding
 			&& ((ProblemMethodBinding) this.binding).problemId() == NotVisible) {
@@ -227,10 +240,10 @@
 					: localScope.getMethod(this.delegateThis.type, this.selector, argumentTypes, this); 
 			if (!privateBinding.isValidBinding()) {
 				if (this.binding.declaringClass == null) {
-					if (this.receiverType instanceof ReferenceBinding) {
-						this.binding.declaringClass = (ReferenceBinding) this.receiverType;
+					if (this.actualReceiverType instanceof ReferenceBinding) {
+						this.binding.declaringClass = (ReferenceBinding) this.actualReceiverType;
 					} else { // really bad error ....
-						scope.problemReporter().errorNoMethodFor(this, this.receiverType, argumentTypes);
+						scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
 						return null;
 					}
 				}
@@ -241,10 +254,10 @@
 			}
 		} else {
 			if (this.binding.declaringClass == null) {
-				if (this.receiverType instanceof ReferenceBinding) {
-					this.binding.declaringClass = (ReferenceBinding) this.receiverType;
+				if (this.actualReceiverType instanceof ReferenceBinding) {
+					this.binding.declaringClass = (ReferenceBinding) this.actualReceiverType;
 				} else { // really bad error ....
-					scope.problemReporter().errorNoMethodFor(this, this.receiverType, argumentTypes);
+					scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
 					return null;
 				}
 			}
@@ -255,7 +268,7 @@
 	if (!this.binding.isStatic()) {
 		// the "receiver" must not be a type, in other words, a NameReference that the TC has bound to a Type
 		if (this.receiver instanceof NameReference) {
-			if ((((NameReference) this.receiver).bits & BindingIds.TYPE) != 0) {
+			if ((((NameReference) this.receiver).bits & Binding.TYPE) != 0) {
 				scope.problemReporter().mustUseAStaticMethod(this, this.binding);
 				return null;
 			}
@@ -263,7 +276,7 @@
 	}
 	if (this.arguments != null)
 		for (int i = 0; i < this.arguments.length; i++)
-			this.arguments[i].implicitWidening(this.binding.parameters[i], argumentTypes[i]);
+			this.arguments[i].computeConversion(scope, this.binding.parameters[i], argumentTypes[i]);
 
 	//-------message send that are known to fail at compile time-----------
 	if (this.binding.isAbstract()) {
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java
index d0dbf1e..d7f2a4a 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java
@@ -14,6 +14,7 @@
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.parser.Parser;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 import org.eclipse.jdt.internal.compiler.util.Util;
@@ -91,7 +92,7 @@
 	/* recovery */
 	recordLastStatementIfNeeded();
 }
-protected void consumeClassHeaderName() {
+protected void consumeClassHeaderName1() {
 	// ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
 	TypeDeclaration typeDecl;
 	if (this.nestedMethod[this.nestedType] == 0) {
@@ -174,7 +175,7 @@
 		this.expressionStack[this.expressionPtr] = fr;
 	}
 }
-protected void consumeInterfaceHeaderName() {
+protected void consumeInterfaceHeaderName1() {
 	// InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
 	TypeDeclaration typeDecl;
 	if (this.nestedMethod[this.nestedType] == 0) {
@@ -255,7 +256,7 @@
 	}
 	
 	int start = methodDecl.bodyStart-1, end = start;
-	long position = (start << 32) + end;
+	long position = ((long)start << 32) + end;
 	long[] positions = new long[]{position};
 	if (this.evaluationContext.localVariableNames != null) {
 
@@ -500,7 +501,7 @@
 				}
 				consumeClassBodyDeclarationsopt();
 				consumeClassDeclaration();
-				consumeTypeDeclarationsopt();
+				consumeInternalCompilationUnitWithTypes();
 				consumeCompilationUnit();
 			}
 			this.lastAct = ACCEPT_ACTION;
@@ -596,7 +597,7 @@
 					this.identifierPositionStack[this.identifierPtr--],
 					this.evaluationContext); 
 			ref.bits &= ~ASTNode.RestrictiveFlagMASK;
-			ref.bits |= LOCAL | FIELD;
+			ref.bits |= Binding.LOCAL | Binding.FIELD;
 			return ref;
 		}
 
@@ -618,7 +619,7 @@
 				(int) this.identifierPositionStack[this.identifierPtr + length],
 				this.evaluationContext); // sourceEnd
 		ref.bits &= ~ASTNode.RestrictiveFlagMASK;
-		ref.bits |= LOCAL | FIELD;
+		ref.bits |= Binding.LOCAL | Binding.FIELD;
 		return ref;
 	} else {
 		return super.getUnspecifiedReferenceOptimized();
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java
index f6895ec..ebb9f18 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java
@@ -20,6 +20,7 @@
 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.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
@@ -53,28 +54,28 @@
 public TypeBinding checkFieldAccess(BlockScope scope) {
 	// check for forward references
 	this.bits &= ~RestrictiveFlagMASK; // clear bits
-	this.bits |= FIELD;
+	this.bits |= Binding.FIELD;
 	return getOtherFieldBindings(scope);
 }
 public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
 
-	generateReadSequence(currentScope, codeStream);
-	if (this.lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
+	FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
+	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
 		// the last field access is a write access
 		assignment.expression.generateCode(currentScope, codeStream, true);
-		fieldStore(codeStream, this.lastFieldBinding, null, valueRequired);
+		fieldStore(codeStream, lastFieldBinding, null, valueRequired);
 	} else {
-		((CodeSnippetCodeStream) codeStream).generateEmulationForField(this.lastFieldBinding);
+		((CodeSnippetCodeStream) codeStream).generateEmulationForField(lastFieldBinding);
 		codeStream.swap();
 		assignment.expression.generateCode(currentScope, codeStream, true);
 		if (valueRequired) {
-			if ((this.lastFieldBinding.type == LongBinding) || (this.lastFieldBinding.type == DoubleBinding)) {
+			if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
 				codeStream.dup2_x2();
 			} else {
 				codeStream.dup_x2();
 			}
 		}
-		((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(this.lastFieldBinding);	
+		((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(lastFieldBinding);	
 	}
 	if (valueRequired) {
 		codeStream.generateImplicitConversion(assignment.implicitConversion);
@@ -87,34 +88,34 @@
 			codeStream.generateConstant(this.constant, this.implicitConversion);
 		}
 	} else {
-		generateReadSequence(currentScope, codeStream); 
+		FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); 
 		if (valueRequired) {
-			if (this.lastFieldBinding.declaringClass == null) { // array length
+			if (lastFieldBinding.declaringClass == null) { // array length
 				codeStream.arraylength();
 				codeStream.generateImplicitConversion(this.implicitConversion);
 			} else {
-				if (this.lastFieldBinding.constant != NotAConstant) {
-					if (!this.lastFieldBinding.isStatic()){
+				if (lastFieldBinding.isConstantValue()) {
+					if (!lastFieldBinding.isStatic()){
 						codeStream.invokeObjectGetClass();
 						codeStream.pop();
 					}
 					// inline the last field constant
-					codeStream.generateConstant(this.lastFieldBinding.constant, this.implicitConversion);
+					codeStream.generateConstant(lastFieldBinding.constant(), this.implicitConversion);
 				} else {	
-					if (this.lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
-						if (this.lastFieldBinding.isStatic()) {
-							codeStream.getstatic(this.lastFieldBinding);
+					if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
+						if (lastFieldBinding.isStatic()) {
+							codeStream.getstatic(lastFieldBinding);
 						} else {
-							codeStream.getfield(this.lastFieldBinding);
+							codeStream.getfield(lastFieldBinding);
 						}
 					} else {
-						((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(this.lastFieldBinding);
+						((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(lastFieldBinding);
 					}	
 					codeStream.generateImplicitConversion(this.implicitConversion);
 				}
 			}
 		} else {
-			if (this.lastFieldBinding != null && !this.lastFieldBinding.isStatic()){
+			if (lastFieldBinding != null && !lastFieldBinding.isStatic()){
 				codeStream.invokeObjectGetClass(); // perform null check
 				codeStream.pop();
 			}
@@ -124,55 +125,59 @@
 }
 public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
 	
-	generateReadSequence(currentScope, codeStream);
-	if (this.lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
-		if (this.lastFieldBinding.isStatic()){
-			codeStream.getstatic(this.lastFieldBinding);
+	FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
+	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
+		if (lastFieldBinding.isStatic()){
+			codeStream.getstatic(lastFieldBinding);
 		} else {
 			codeStream.dup();
-			codeStream.getfield(this.lastFieldBinding);
+			codeStream.getfield(lastFieldBinding);
 		}
 		// the last field access is a write access
 		// perform the actual compound operation
 		int operationTypeID;
-		if ((operationTypeID = this.implicitConversion >> 4) == T_String) {
-			codeStream.generateStringAppend(currentScope, null, expression);
-		} else {
-			// promote the array reference to the suitable operation type
-			codeStream.generateImplicitConversion(this.implicitConversion);
-			// generate the increment value (will by itself  be promoted to the operation value)
-			if (expression == IntLiteral.One){ // prefix operation
-				codeStream.generateConstant(expression.constant, this.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);
+		switch(operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
+			case T_JavaLangString :
+			case T_JavaLangObject :
+			case T_undefined :
+				codeStream.generateStringConcatenationAppend(currentScope, null, expression);
+				break;
+			default :
+				// promote the array reference to the suitable operation type
+				codeStream.generateImplicitConversion(this.implicitConversion);
+				// generate the increment value (will by itself  be promoted to the operation value)
+				if (expression == IntLiteral.One){ // prefix operation
+					codeStream.generateConstant(expression.constant, this.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);
 		}
 		// actual assignment
-		fieldStore(codeStream, this.lastFieldBinding, null, valueRequired);
+		fieldStore(codeStream, lastFieldBinding, null, valueRequired);
 	} else {
-		if (this.lastFieldBinding.isStatic()){
-			((CodeSnippetCodeStream) codeStream).generateEmulationForField(this.lastFieldBinding);
+		if (lastFieldBinding.isStatic()){
+			((CodeSnippetCodeStream) codeStream).generateEmulationForField(lastFieldBinding);
 			codeStream.swap();
 			codeStream.aconst_null();
 			codeStream.swap();
 
-			((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(this.lastFieldBinding);
+			((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(lastFieldBinding);
 		} else {
-			((CodeSnippetCodeStream) codeStream).generateEmulationForField(this.lastFieldBinding);
+			((CodeSnippetCodeStream) codeStream).generateEmulationForField(lastFieldBinding);
 			codeStream.swap();
 			codeStream.dup();
 
-			((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(this.lastFieldBinding);
+			((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(lastFieldBinding);
 		}
 		// the last field access is a write access
 		// perform the actual compound operation
 		int operationTypeID;
-		if ((operationTypeID = this.implicitConversion >> 4) == T_String) {
-			codeStream.generateStringAppend(currentScope, null, expression);
+		if ((operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_JavaLangString) {
+			codeStream.generateStringConcatenationAppend(currentScope, null, expression);
 		} else {
 			// promote the array reference to the suitable operation type
 			codeStream.generateImplicitConversion(this.implicitConversion);
@@ -192,7 +197,7 @@
 		// current stack is:
 		// field receiver value
 		if (valueRequired) {
-			if ((this.lastFieldBinding.type == LongBinding) || (this.lastFieldBinding.type == DoubleBinding)) {
+			if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
 				codeStream.dup2_x2();
 			} else {
 				codeStream.dup_x2();
@@ -200,29 +205,29 @@
 		}
 		// current stack is:
 		// value field receiver value				
-		((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(this.lastFieldBinding);
+		((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(lastFieldBinding);
 	}
 }
 public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
-	generateReadSequence(currentScope, codeStream);
 
-	if (this.lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
-		if (this.lastFieldBinding.isStatic()){
-			codeStream.getstatic(this.lastFieldBinding);
+    FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
+	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
+		if (lastFieldBinding.isStatic()){
+			codeStream.getstatic(lastFieldBinding);
 		} else {
 			codeStream.dup();
-			codeStream.getfield(this.lastFieldBinding);
+			codeStream.getfield(lastFieldBinding);
 		}	
 		// duplicate the old field value
 		if (valueRequired) {
-			if (this.lastFieldBinding.isStatic()) {
-				if ((this.lastFieldBinding.type == LongBinding) || (this.lastFieldBinding.type == DoubleBinding)) {
+			if (lastFieldBinding.isStatic()) {
+				if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
 					codeStream.dup2();
 				} else {
 					codeStream.dup();
 				}
 			} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
-				if ((this.lastFieldBinding.type == LongBinding) || (this.lastFieldBinding.type == DoubleBinding)) {
+				if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
 					codeStream.dup2_x1();
 				} else {
 					codeStream.dup_x1();
@@ -230,24 +235,24 @@
 			}
 		}
 		codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
-		codeStream.sendOperator(postIncrement.operator, this.lastFieldBinding.type.id);
+		codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id);
 		codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
 		
-		fieldStore(codeStream, this.lastFieldBinding, null, false);
+		fieldStore(codeStream, lastFieldBinding, null, false);
 	} else {
-		((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(this.lastFieldBinding);
+		((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(lastFieldBinding);
 		if (valueRequired) {
-			if ((this.lastFieldBinding.type == LongBinding) || (this.lastFieldBinding.type == DoubleBinding)) {
+			if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
 				codeStream.dup2();
 			} else {
 				codeStream.dup();
 			}
 		}
-		((CodeSnippetCodeStream) codeStream).generateEmulationForField(this.lastFieldBinding);
-		if ((this.lastFieldBinding.type == LongBinding) || (this.lastFieldBinding.type == DoubleBinding)) {
+		((CodeSnippetCodeStream) codeStream).generateEmulationForField(lastFieldBinding);
+		if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
 			codeStream.dup_x2();
 			codeStream.pop();
-			if (this.lastFieldBinding.isStatic()) {
+			if (lastFieldBinding.isStatic()) {
 				codeStream.aconst_null();
 			} else {
 				generateReadSequence(currentScope, codeStream);
@@ -257,7 +262,7 @@
 		} else {
 			codeStream.dup_x1();
 			codeStream.pop();
-			if (this.lastFieldBinding.isStatic()) {
+			if (lastFieldBinding.isStatic()) {
 				codeStream.aconst_null();
 			} else {
 				generateReadSequence(currentScope, codeStream);
@@ -266,45 +271,44 @@
 			codeStream.pop();					
 		}
 		codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
-		codeStream.sendOperator(postIncrement.operator, this.lastFieldBinding.type.id);
+		codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id);
 		codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
-		((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(this.lastFieldBinding);
+		((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(lastFieldBinding);
 	}
 }
 /*
  * Generate code for all bindings (local and fields) excluding the last one, which may then be generated code
  * for a read or write access.
  */
-public void generateReadSequence(BlockScope currentScope, CodeStream codeStream) {
+public FieldBinding generateReadSequence(BlockScope currentScope, CodeStream codeStream) {
+    
 	// determine the rank until which we now we do not need any actual value for the field access
 	int otherBindingsCount = this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length;
-
 	boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic();
+	FieldBinding lastFieldBinding = null;
+	TypeBinding lastGenericCast = null;
+	
 	switch (this.bits & RestrictiveFlagMASK) {
-		case FIELD :
-			this.lastFieldBinding = (FieldBinding) this.codegenBinding;
+		case Binding.FIELD :
+			lastFieldBinding = (FieldBinding) this.codegenBinding;
+			lastGenericCast = this.genericCast;
 			// if first field is actually constant, we can inline it
-			if (this.lastFieldBinding.constant != NotAConstant) {
+			if (lastFieldBinding.isConstantValue()) {
 				break;
 			}
 			if (needValue) {
-				if (this.lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
-					if (!this.lastFieldBinding.isStatic()) {
+				if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
+					if (!lastFieldBinding.isStatic()) {
 						if ((this.bits & DepthMASK) != 0) {
 							ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
 							Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
-							if (emulationPath == null) {
-								// internal error, per construction we should have found it
-								currentScope.problemReporter().needImplementation();
-							} else {
-								codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
-							}
+							codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
 						} else {
 							generateReceiver(codeStream);
 						}
 					}
 				} else {
-					if (!this.lastFieldBinding.isStatic()) {
+					if (!lastFieldBinding.isStatic()) {
 						if ((this.bits & DepthMASK) != 0) {
 							// internal error, per construction we should have found it
 							// not yet supported
@@ -318,25 +322,19 @@
 				}				
 			}
 			break;
-		case LOCAL : // reading the first local variable
+		case Binding.LOCAL : // reading the first local variable
 			if (!needValue) break; // no value needed
-			this.lastFieldBinding = null;
 			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 			// regular local variable read
-			if (localBinding.constant != NotAConstant) {
-				codeStream.generateConstant(localBinding.constant, 0);
+			if (localBinding.isConstantValue()) {
+				codeStream.generateConstant(localBinding.constant(), 0);
 				// no implicit conversion
 			} else {
 				// outer local?
-				if ((this.bits & DepthMASK) != 0) {
+				if ((bits & DepthMASK) != 0) {
 					// outer local can be reached either through a synthetic arg or a synthetic field
 					VariableBinding[] path = currentScope.getEmulationPath(localBinding);
-					if (path == null) {
-						// emulation was not possible (should not happen per construction)
-						currentScope.problemReporter().needImplementation();
-					} else {
-						codeStream.generateOuterAccess(path, this, localBinding, currentScope);
-					}
+					codeStream.generateOuterAccess(path, this, localBinding, currentScope);
 				} else {
 					codeStream.load(localBinding);
 				}
@@ -348,39 +346,43 @@
 	if (this.otherCodegenBindings != null) {
 		for (int i = 0; i < otherBindingsCount; i++) {
 			FieldBinding nextField = this.otherCodegenBindings[i];
-			if (this.lastFieldBinding != null) {
+			TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i];
+			if (lastFieldBinding != null) {
 				needValue = !nextField.isStatic();
 				if (needValue) {
-					if (this.lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
-						if (this.lastFieldBinding.constant != NotAConstant) {
-							if (this.lastFieldBinding != this.codegenBinding && !this.lastFieldBinding.isStatic()) {
+					if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
+						if (lastFieldBinding.isConstantValue()) {
+							if (lastFieldBinding != this.codegenBinding && !lastFieldBinding.isStatic()) {
 								codeStream.invokeObjectGetClass(); // perform null check
 								codeStream.pop();
 							}
-							codeStream.generateConstant(this.lastFieldBinding.constant, 0);
-						} else if (this.lastFieldBinding.isStatic()) {
-							codeStream.getstatic(this.lastFieldBinding);
+							codeStream.generateConstant(lastFieldBinding.constant(), 0);
+						} else if (lastFieldBinding.isStatic()) {
+							codeStream.getstatic(lastFieldBinding);
 						} else {
-							codeStream.getfield(this.lastFieldBinding);
+							codeStream.getfield(lastFieldBinding);
 						}
 					} else {
-						((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(this.lastFieldBinding);
+						((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(lastFieldBinding);
 					}
+					if (lastGenericCast != null) codeStream.checkcast(lastGenericCast);
 				} else {
-					if (this.codegenBinding != this.lastFieldBinding && !this.lastFieldBinding.isStatic()){
+					if (this.codegenBinding != lastFieldBinding && !lastFieldBinding.isStatic()){
 						codeStream.invokeObjectGetClass(); // perform null check
 						codeStream.pop();
 					}						
 				}
 			}
-			this.lastFieldBinding = nextField;
-			if (this.lastFieldBinding != null && !this.lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
-				if (this.lastFieldBinding.isStatic()) {
+			lastFieldBinding = nextField;
+			lastGenericCast = nextGenericCast;
+			if (lastFieldBinding != null && !lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
+				if (lastFieldBinding.isStatic()) {
 					codeStream.aconst_null();
 				}
 			}
 		}			
 	}
+	return lastFieldBinding;
 }
 
 public void generateReceiver(CodeStream codeStream) {
@@ -393,7 +395,7 @@
 	// At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid)
 
 	int length = this.tokens.length;
-	if ((this.bits & FIELD) != 0) {
+	if ((this.bits & Binding.FIELD) != 0) {
 		if (!((FieldBinding) this.binding).isStatic()) { //must check for the static status....
 			if (this.indexOfFirstFieldBinding == 1) {
 				//the field is the first token of the qualified reference....
@@ -425,9 +427,9 @@
 	
 	// fill the first constant (the one of the binding)
 	this.constant =
-		((this.bits & FIELD) != 0)
+		((this.bits & Binding.FIELD) != 0)
 			? FieldReference.getConstantFor((FieldBinding) this.binding, this, false, scope)
-			: ((VariableBinding) this.binding).constant;
+			: ((VariableBinding) this.binding).constant();
 
 	// iteration on each field	
 	while (index < length) {
@@ -474,23 +476,24 @@
 	}
 	return (this.otherBindings[otherBindingsLength - 1]).type;
 }
-/**
- * Check and/or redirect the field access to the delegate receiver if any
- */
-public TypeBinding getReceiverType(BlockScope currentScope) {
-	if (this.receiverType != null) return this.receiverType;
-	Scope scope = currentScope.parent;
-	while (true) {
-			switch (scope.kind) {
-				case Scope.CLASS_SCOPE :
-					return this.receiverType = ((ClassScope) scope).referenceContext.binding;
-				default:
-					scope = scope.parent;
-			}
+	/**
+	 * Check and/or redirect the field access to the delegate receiver if any
+	 */
+	public TypeBinding getReceiverType(BlockScope currentScope) {
+		Scope scope = currentScope.parent;
+		while (true) {
+				switch (scope.kind) {
+					case Scope.CLASS_SCOPE :
+						return ((ClassScope) scope).referenceContext.binding;
+					default:
+						scope = scope.parent;
+				}
+		}
 	}
-}
-		
-	public void manageSyntheticReadAccessIfNecessary(
+	/**
+	 * index is <0 to denote write access emulation
+	 */		
+	public void manageSyntheticAccessIfNecessary(
 		BlockScope currentScope,
 		FieldBinding fieldBinding,
 		TypeBinding lastReceiverType,
@@ -499,71 +502,47 @@
 
 		if (!flowInfo.isReachable()) return;
 	
-
 		// if the binding declaring class is not visible, need special action
 		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
 		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
-		boolean useDelegate = index == 0 && this.delegateThis != null;
+		boolean useDelegate;
+		if (index < 0) { // write-access?
+		    useDelegate = fieldBinding == this.binding && this.delegateThis != null;
+		} else {
+			useDelegate = index == 0 && this.delegateThis != null;
+		}
+		
 		if (useDelegate) {
 			lastReceiverType = this.delegateThis.type;
 		}
 		if (fieldBinding.declaringClass != lastReceiverType
 			&& !lastReceiverType.isArrayType()			
 			&& fieldBinding.declaringClass != null
-			&& fieldBinding.constant == NotAConstant
+			&& !fieldBinding.isConstantValue()
 			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
-					&& (index > 0 || this.indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
-					&& fieldBinding.declaringClass.id != T_Object)
+					&& ((index < 0 ? fieldBinding != binding : index > 0) || this.indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
+					&& fieldBinding.declaringClass.id != T_JavaLangObject)
 				|| !(useDelegate
 						? new CodeSnippetScope(currentScope).canBeSeenByForCodeSnippet(fieldBinding.declaringClass, (ReferenceBinding) this.delegateThis.type)
 						: fieldBinding.declaringClass.canBeSeenBy(currentScope)))){
-			if (index == 0){
-				this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
+		    if (index < 0) { // write-access?
+				if (fieldBinding == this.binding){
+					this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType.erasure());
+				} else {
+					if (this.otherCodegenBindings == this.otherBindings){
+						int l = this.otherBindings.length;
+						System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l);
+					}
+					this.otherCodegenBindings[this.otherCodegenBindings.length-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType.erasure());
+				}
+		    } if (index == 0){
+				this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType.erasure());
 			} else {
 				if (this.otherCodegenBindings == this.otherBindings){
 					int l = this.otherBindings.length;
 					System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l);
 				}
-				this.otherCodegenBindings[index-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
-			}
-		}
-	}
-	/*
-	 * No need to emulate access to protected fields since not implicitly accessed
-	 */
-	public void manageSyntheticWriteAccessIfNecessary(
-		BlockScope currentScope,
-		FieldBinding fieldBinding,
-		TypeBinding lastReceiverType,
-		FlowInfo flowInfo) {
-
-		if (!flowInfo.isReachable()) return;
-	
-		// if the binding declaring class is not visible, need special action
-		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
-		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
-		boolean useDelegate = fieldBinding == this.binding && this.delegateThis != null;
-		if (useDelegate) {
-			lastReceiverType = this.delegateThis.type;
-		}
-		if (fieldBinding.declaringClass != lastReceiverType
-			&& !lastReceiverType.isArrayType()			
-			&& fieldBinding.declaringClass != null
-			&& fieldBinding.constant == NotAConstant
-			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
-					&& (fieldBinding != this.binding || this.indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
-					&& fieldBinding.declaringClass.id != T_Object)
-				|| !(useDelegate
-						? new CodeSnippetScope(currentScope).canBeSeenByForCodeSnippet(fieldBinding.declaringClass, (ReferenceBinding) this.delegateThis.type)
-						: fieldBinding.declaringClass.canBeSeenBy(currentScope)))){
-			if (fieldBinding == this.binding){
-				this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
-			} else {
-				if (this.otherCodegenBindings == this.otherBindings){
-					int l = this.otherBindings.length;
-					System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l);
-				}
-				this.otherCodegenBindings[this.otherCodegenBindings.length-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
+				this.otherCodegenBindings[index-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType.erasure());
 			}
 		}
 	}
@@ -627,7 +606,7 @@
 	CodeSnippetScope localScope = new CodeSnippetScope(scope);
 	if ((this.codegenBinding = this.binding = localScope.getBinding(this.tokens, this.bits & RestrictiveFlagMASK, this, (ReferenceBinding) this.delegateThis.type)).isValidBinding()) {
 		this.bits &= ~RestrictiveFlagMASK; // clear bits
-		this.bits |= FIELD;
+		this.bits |= Binding.FIELD;
 		return getOtherFieldBindings(scope);
 	}
 	//========error cases===============
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetReturnStatement.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetReturnStatement.java
index c3cc5d0..7658691 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetReturnStatement.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetReturnStatement.java
@@ -56,7 +56,7 @@
 	codeStream.aload_0();
 
 	// push the 2 parameters of "setResult(Object, Class)"
-	if (this.expression == null || this.expressionType == VoidBinding) { // expressionType == VoidBinding if code snippet is the expression "System.out.println()"
+	if (this.expression == null || this.expression.resolvedType == VoidBinding) { // expressionType == VoidBinding if code snippet is the expression "System.out.println()"
 		// push null
 		codeStream.aconst_null();
 
@@ -64,7 +64,7 @@
 		codeStream.generateClassLiteralAccessForType(VoidBinding, null);
 	} else {
 		// swap with expression
-		int valueTypeID = this.expressionType.id;
+		int valueTypeID = this.expression.resolvedType.id;
 		if (valueTypeID == T_long || valueTypeID == T_double) {
 			codeStream.dup_x2();
 			codeStream.pop();
@@ -73,17 +73,23 @@
 		}
 
 		// generate wrapper if needed
-		if (this.expressionType.isBaseType() && this.expressionType != NullBinding) { 
-			((CodeSnippetCodeStream)codeStream).generateObjectWrapperForType(this.expressionType);
+		if (this.expression.resolvedType.isBaseType() && this.expression.resolvedType != NullBinding) { 
+			((CodeSnippetCodeStream)codeStream).generateObjectWrapperForType(this.expression.resolvedType);
 		}
 
 		// generate the expression type
-		codeStream.generateClassLiteralAccessForType(this.expressionType, null);
+		codeStream.generateClassLiteralAccessForType(this.expression.resolvedType, null);
 	}
 
 	// generate the invoke virtual to "setResult(Object,Class)"
 	codeStream.invokevirtual(this.setResultMethod);
 }
+/**
+ * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+ */
+public TypeBinding[] genericTypeArguments() {
+	return null;
+}
 public boolean isSuperAccess() {
 	return false;
 }
@@ -99,7 +105,7 @@
 }
 public void resolve(BlockScope scope) {
 	if (this.expression != null) {
-		if ((this.expressionType = this.expression.resolveType(scope)) != null) {
+		if (this.expression.resolveType(scope) != null) {
 			TypeBinding javaLangClass = scope.getJavaLangClass();
 			if (!javaLangClass.isValidBinding()) {
 				scope.problemReporter().codeSnippetMissingClass("java.lang.Class", this.sourceStart, this.sourceEnd); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java
index 10c42cb..b1cffbe 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java
@@ -11,7 +11,6 @@
 package org.eclipse.jdt.internal.eval;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
 import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
@@ -27,6 +26,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.Scope;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
 
@@ -420,8 +420,9 @@
 		// argument type compatibility check
 		for (int i = 0; i < foundSize; i++) {
 			MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
-			if (areParametersAssignable(methodBinding.parameters, argumentTypes))
-				candidates[candidatesCount++] = methodBinding;
+			MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
+			if (compatibleMethod != null)
+				candidates[candidatesCount++] = compatibleMethod;
 		}
 		if (candidatesCount == 1) {
 			//compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
@@ -475,9 +476,9 @@
 				NotVisible);
 		}	
 		if (candidates[0].declaringClass.isClass()) {
-			return mostSpecificClassMethodBinding(candidates, visiblesCount);
+			return mostSpecificClassMethodBinding(candidates, visiblesCount, invocationSite);
 		} else {
-			return mostSpecificInterfaceMethodBinding(candidates, visiblesCount);
+			return mostSpecificInterfaceMethodBinding(candidates, visiblesCount, invocationSite);
 		}
 	}
 
@@ -488,7 +489,7 @@
 	if (methodBinding != null) {
 		// handle the method clone() specially... cannot be protected or throw exceptions
 		if (argumentTypes == NoParameters && CharOperation.equals(selector, CLONE))
-			return new MethodBinding((methodBinding.modifiers ^ AccProtected) | AccPublic, CLONE, methodBinding.returnType, argumentTypes, null, object);
+			return new MethodBinding((methodBinding.modifiers & ~AccProtected) | AccPublic, CLONE, methodBinding.returnType, argumentTypes, null, object);
 		if (canBeSeenByForCodeSnippet(methodBinding, receiverType, invocationSite, this))
 			return methodBinding;
 	}
@@ -498,10 +499,12 @@
 	if (methodBinding == null)
 		return new ProblemMethodBinding(selector, argumentTypes, NotFound);
 	if (methodBinding.isValidBinding()) {
-		if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
+	    MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
+	    if (compatibleMethod == null)
 			return new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotFound);
+	    methodBinding = compatibleMethod;
 		if (!canBeSeenByForCodeSnippet(methodBinding, receiverType, invocationSite, this))
-			return new ProblemMethodBinding(selector, methodBinding.parameters, methodBinding.declaringClass, NotVisible);
+			return new ProblemMethodBinding(methodBinding, selector, methodBinding.parameters, NotVisible);
 	}
 	return methodBinding;
 }
@@ -538,7 +541,7 @@
 */
 
 public Binding getBinding(char[][] compoundName, int mask, InvocationSite invocationSite, ReferenceBinding receiverType) {
-	Binding binding = getBinding(compoundName[0], mask | TYPE | PACKAGE, invocationSite, true /*resolve*/);
+	Binding binding = getBinding(compoundName[0], mask | Binding.TYPE | Binding.PACKAGE, invocationSite, true /*resolve*/);
 	invocationSite.setFieldIndex(1);
 	if (!binding.isValidBinding() || binding instanceof VariableBinding)
 		return binding;
@@ -587,13 +590,13 @@
 			return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), binding.problemId());
 	}
 
-	if ((mask & FIELD) != 0 && (binding instanceof FieldBinding)) { // was looking for a field and found a field
+	if ((mask & Binding.FIELD) != 0 && (binding instanceof FieldBinding)) { // was looking for a field and found a field
 		FieldBinding field = (FieldBinding) binding;
 		if (!field.isStatic())
 			return new ProblemFieldBinding(field.declaringClass, CharOperation.subarray(compoundName, 0, currentIndex), NonStaticReferenceInStaticContext);
 		return binding;
 	}
-	if ((mask & TYPE) != 0 && (binding instanceof ReferenceBinding)) { // was looking for a type and found a type
+	if ((mask & Binding.TYPE) != 0 && (binding instanceof ReferenceBinding)) { // was looking for a type and found a type
 		return binding;
 	}
 
@@ -617,17 +620,19 @@
 			return methodBinding;
 		}
 	}
-	MethodBinding[] methods = receiverType.getMethods(ConstructorDeclaration.ConstantPoolName);
+	MethodBinding[] methods = receiverType.getMethods(TypeConstants.INIT);
 	if (methods == NoMethods) {
-		return new ProblemMethodBinding(ConstructorDeclaration.ConstantPoolName, argumentTypes, NotFound);
+		return new ProblemMethodBinding(TypeConstants.INIT, argumentTypes, NotFound);
 	}
 	MethodBinding[] compatible = new MethodBinding[methods.length];
 	int compatibleIndex = 0;
-	for (int i = 0, length = methods.length; i < length; i++)
-		if (areParametersAssignable(methods[i].parameters, argumentTypes))
-			compatible[compatibleIndex++] = methods[i];
+	for (int i = 0, length = methods.length; i < length; i++) {
+	    MethodBinding compatibleMethod = computeCompatibleMethod(methods[i], argumentTypes, invocationSite);
+		if (compatibleMethod != null)
+			compatible[compatibleIndex++] = compatibleMethod;
+	}
 	if (compatibleIndex == 0)
-		return new ProblemMethodBinding(ConstructorDeclaration.ConstantPoolName, argumentTypes, NotFound); // need a more descriptive error... cannot convert from X to Y
+		return new ProblemMethodBinding(TypeConstants.INIT, argumentTypes, NotFound); // need a more descriptive error... cannot convert from X to Y
 
 	MethodBinding[] visible = new MethodBinding[compatibleIndex];
 	int visibleIndex = 0;
@@ -641,9 +646,9 @@
 		return visible[0];
 	}
 	if (visibleIndex == 0) {
-		return new ProblemMethodBinding(ConstructorDeclaration.ConstantPoolName, compatible[0].parameters, NotVisible);
+		return new ProblemMethodBinding(compatible[0], TypeConstants.INIT, compatible[0].parameters, NotVisible);
 	}
-	return mostSpecificClassMethodBinding(visible, visibleIndex);
+	return mostSpecificClassMethodBinding(visible, visibleIndex, invocationSite);
 }
 /* API
 
@@ -713,18 +718,22 @@
 		ProblemMethodBinding insideProblem = null;
 		if (methodBinding.isValidBinding()) {
 			if (!isExactMatch) {
-				if (!areParametersAssignable(methodBinding.parameters, argumentTypes)) {
+	    	    MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
+				if (compatibleMethod == null) {
 					fuzzyProblem = new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotFound);
-				} else if (!canBeSeenByForCodeSnippet(methodBinding, receiverType, invocationSite, this)) {	
-					// using <classScope> instead of <this> for visibility check does grant all access to innerclass
-					fuzzyProblem = new ProblemMethodBinding(selector, argumentTypes, methodBinding.declaringClass, NotVisible);
+				} else {
+				    methodBinding = compatibleMethod;
+				    if (!canBeSeenByForCodeSnippet(methodBinding, receiverType, invocationSite, this)) {	
+						// using <classScope> instead of <this> for visibility check does grant all access to innerclass
+						fuzzyProblem = new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotVisible);
+				    }
 				}
 			}
 			if (fuzzyProblem == null && !methodBinding.isStatic()) {
 				if (insideConstructorCall) {
-					insideProblem = new ProblemMethodBinding(methodBinding.selector, methodBinding.parameters, NonStaticReferenceInConstructorInvocation);
+					insideProblem = new ProblemMethodBinding(methodBinding, methodBinding.selector, methodBinding.parameters, NonStaticReferenceInConstructorInvocation);
 				} else if (insideStaticContext) {
-					insideProblem = new ProblemMethodBinding(methodBinding.selector, methodBinding.parameters, NonStaticReferenceInStaticContext);
+					insideProblem = new ProblemMethodBinding(methodBinding, methodBinding.selector, methodBinding.parameters, NonStaticReferenceInStaticContext);
 				}
 			}
 			if (receiverType == methodBinding.declaringClass || (receiverType.getMethods(selector)) != NoMethods) {
@@ -741,7 +750,7 @@
 				// if a method was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
 				// NOTE: Unlike fields, a non visible method hides a visible method
 				if (foundMethod.declaringClass != methodBinding.declaringClass) // ie. have we found the same method - do not trust field identity yet
-					return new ProblemMethodBinding(methodBinding.selector, methodBinding.parameters, InheritedNameHidesEnclosingName);
+					return new ProblemMethodBinding(methodBinding, methodBinding.selector, methodBinding.parameters, InheritedNameHidesEnclosingName);
 			}
 		}
 
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java
index 25d95c2..256a671 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java
@@ -52,7 +52,7 @@
 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
 
 	switch (this.bits & RestrictiveFlagMASK) {
-		case FIELD : // reading a field
+		case Binding.FIELD : // reading a field
 			// check if reading a final blank field
 			FieldBinding fieldBinding;
 			if ((fieldBinding = (FieldBinding) this.binding).isBlankFinal() 
@@ -62,7 +62,7 @@
 				}
 			}
 			break;
-		case LOCAL : // reading a local variable
+		case Binding.LOCAL : // reading a local variable
 			LocalVariableBinding localBinding;
 			if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) {
 				currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
@@ -85,7 +85,7 @@
 	}
 	FieldBinding fieldBinding = (FieldBinding) this.binding;
 	this.bits &= ~RestrictiveFlagMASK; // clear bits
-	this.bits |= FIELD;
+	this.bits |= Binding.FIELD;
 	if (!fieldBinding.isStatic()) {
 		// must check for the static status....
 		if (this.evaluationContext.isStatic) {
@@ -120,15 +120,15 @@
 			&& ((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.implicitConversion >> 4) != T_String) // exclude string concatenation which would occur backwards
-			&& ((operation.right.implicitConversion >> 4) != T_String)) { // exclude string concatenation which would occur backwards
+			&& (((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
 			variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[WRITE], operation.left, operator, operation.right.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
 			return;
 		}
 	}
 	switch (this.bits & RestrictiveFlagMASK) {
-		case FIELD : // assigning to a field
+		case Binding.FIELD : // assigning to a field
 			FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
 			if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
 				if (!fieldBinding.isStatic()) { // need a receiver?
@@ -172,7 +172,7 @@
 				}
 			}
 			return;
-		case LOCAL : // assigning to a local variable
+		case Binding.LOCAL : // assigning to a local variable
 			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 			if (localBinding.resolvedPosition != -1) {
 				assignment.expression.generateCode(currentScope, codeStream, true);
@@ -217,10 +217,10 @@
 		}
 	} else {
 		switch (this.bits & RestrictiveFlagMASK) {
-			case FIELD : // reading a field
+			case Binding.FIELD : // reading a field
 				FieldBinding fieldBinding;
 				if (valueRequired) {
-					if ((fieldBinding = (FieldBinding) this.codegenBinding).constant == NotAConstant) { // directly use inlined value for constant fields
+					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;
@@ -254,13 +254,14 @@
 							}
 							((CodeSnippetCodeStream)codeStream).generateEmulatedReadAccessForField(fieldBinding);
 						}
+						if (this.genericCast != null) codeStream.checkcast(this.genericCast);		
 						codeStream.generateImplicitConversion(this.implicitConversion);
 					} else { // directly use the inlined value
-						codeStream.generateConstant(fieldBinding.constant, this.implicitConversion);
+						codeStream.generateConstant(fieldBinding.constant(), this.implicitConversion);
 					}
 				}
 				break;
-			case LOCAL : // reading a local
+			case Binding.LOCAL : // reading a local
 				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 				if (valueRequired) {
 					// outer local?
@@ -284,7 +285,7 @@
  */
 public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
 	switch (this.bits & RestrictiveFlagMASK) {
-		case FIELD : // assigning to a field
+		case Binding.FIELD : // assigning to a field
 			FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
 			if (fieldBinding.isStatic()) {
 				if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
@@ -325,14 +326,14 @@
 				}
 			}
 			break;
-		case LOCAL : // assigning to a local variable (cannot assign to outer local)
+		case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
 			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 			Constant assignConstant;
 			int increment;
 			// using incr bytecode if possible
 			switch (localBinding.type.id) {
-				case T_String :
-					codeStream.generateStringAppend(currentScope, this, expression);
+				case T_JavaLangString :
+					codeStream.generateStringConcatenationAppend(currentScope, this, expression);
 					if (valueRequired) {
 						codeStream.dup();
 					}
@@ -364,25 +365,29 @@
 	}
 	// perform the actual compound operation
 	int operationTypeID;
-	if ((operationTypeID = this.implicitConversion >> 4) == T_String || operationTypeID == T_Object) {
-		codeStream.generateStringAppend(currentScope, null, expression);
-	} else {
-		// promote the array reference to the suitable operation type
-		codeStream.generateImplicitConversion(this.implicitConversion);
-		// generate the increment value (will by itself  be promoted to the operation value)
-		if (expression == IntLiteral.One){ // prefix operation
-			codeStream.generateConstant(expression.constant, this.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);
+	switch(operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
+		case T_JavaLangString :
+		case T_JavaLangObject :
+		case T_undefined :
+			codeStream.generateStringConcatenationAppend(currentScope, null, expression);
+			break;
+		default :
+			// promote the array reference to the suitable operation type
+			codeStream.generateImplicitConversion(this.implicitConversion);
+			// generate the increment value (will by itself  be promoted to the operation value)
+			if (expression == IntLiteral.One){ // prefix operation
+				codeStream.generateConstant(expression.constant, this.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);
 	}
 	// store the result back into the variable
 	switch (this.bits & RestrictiveFlagMASK) {
-		case FIELD : // assigning to a field
+		case Binding.FIELD : // assigning to a field
 			FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
 			if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
 				fieldStore(codeStream, fieldBinding, writeAccessor, valueRequired);
@@ -401,7 +406,7 @@
 				((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(fieldBinding);
 			}
 			return;
-		case LOCAL : // assigning to a local variable
+		case Binding.LOCAL : // assigning to a local variable
 			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 			if (valueRequired) {
 				if ((localBinding.type == LongBinding) || (localBinding.type == DoubleBinding)) {
@@ -415,7 +420,7 @@
 }
 public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
 	switch (this.bits & RestrictiveFlagMASK) {
-		case FIELD : // assigning to a field
+		case Binding.FIELD : // assigning to a field
 			FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
 			if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
 				if (fieldBinding.isStatic()) {
@@ -498,7 +503,7 @@
 				((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(fieldBinding);
 			}
 			return;
-		case LOCAL : // assigning to a local variable
+		case Binding.LOCAL : // assigning to a local variable
 			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 			// using incr bytecode if possible
 			if (localBinding.type == IntBinding) {
@@ -537,97 +542,51 @@
  * Check and/or redirect the field access to the delegate receiver if any
  */
 public TypeBinding getReceiverType(BlockScope currentScope) {
-	if (this.receiverType != null) {
-		return this.receiverType;
-	}
 	Scope scope = currentScope.parent;
 	while (true) {
 			switch (scope.kind) {
 				case Scope.CLASS_SCOPE :
-					return this.receiverType = ((ClassScope) scope).referenceContext.binding;
+					return ((ClassScope) scope).referenceContext.binding;
 				default:
 					scope = scope.parent;
 			}
 	}
 }
-public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess) {
 
 	if (this.delegateThis == null) {
-		super.manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
+		super.manageSyntheticAccessIfNecessary(currentScope, flowInfo, isReadAccess);
 		return;
 	}
-	
+
 	if (!flowInfo.isReachable()) return;
 	//If inlinable field, forget the access emulation, the code gen will directly target it
 	if (this.constant != NotAConstant)
-		return;
-	if ((this.bits & FIELD) != 0) {
+		return;	
+	// if field from parameterized type got found, use the original field at codegen time
+	if (this.binding instanceof ParameterizedFieldBinding) {
+	    ParameterizedFieldBinding parameterizedField = (ParameterizedFieldBinding) this.binding;
+	    this.codegenBinding = parameterizedField.originalField;
+	    FieldBinding fieldCodegenBinding = (FieldBinding)this.codegenBinding;
+	    // extra cast needed if field type was type variable
+	    if ((fieldCodegenBinding.type.tagBits & TagBits.HasTypeVariable) != 0) {
+	        this.genericCast = fieldCodegenBinding.type.genericCast(currentScope.boxing(parameterizedField.type)); // runtimeType could be base type in boxing case
+	    }		    
+	}		
+	if ((this.bits & Binding.FIELD) != 0) {
 		FieldBinding fieldBinding = (FieldBinding) this.binding;
-//			if (((this.bits & DepthMASK) != 0)
-//				&& (fieldBinding.isPrivate() // private access
-//					|| (fieldBinding.isProtected() // implicit protected access
-//							&& fieldBinding.declaringClass.getPackage() 
-//								!= this.delegateThis.type.getPackage()))) {
-//				if (this.syntheticAccessors == null)
-//					this.syntheticAccessors = new MethodBinding[2];
-//				this.syntheticAccessors[READ] = 
-//					((SourceTypeBinding)currentScope.enclosingSourceType().
-//						enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT)).
-//							addSyntheticMethod(fieldBinding, true);
-//				currentScope.problemReporter().needToEmulateFieldReadAccess(fieldBinding, this);
-//				return;
-//			}
 		// if the binding declaring class is not visible, need special action
 		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
 		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
 		// and not from Object or implicit static field access.	
 		if (fieldBinding.declaringClass != this.delegateThis.type
 			&& fieldBinding.declaringClass != null
-			&& fieldBinding.constant == NotAConstant
+			&& !fieldBinding.isConstantValue()
 			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2 
 					&& !fieldBinding.isStatic()
-					&& fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
-				|| !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
-			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.delegateThis.type);
-		}
-	}
-}
-public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
-
-	if (this.delegateThis == null) {
-		super.manageSyntheticWriteAccessIfNecessary(currentScope, flowInfo);
-		return;
-	}
-
-	if (!flowInfo.isReachable()) return;
-	if ((this.bits & FIELD) != 0) {
-		FieldBinding fieldBinding = (FieldBinding) this.binding;
-//		if (((this.bits & DepthMASK) != 0) 
-//			&& (fieldBinding.isPrivate() // private access
-//				|| (fieldBinding.isProtected() // implicit protected access
-//						&& fieldBinding.declaringClass.getPackage() 
-//							!= currentScope.enclosingSourceType().getPackage()))) {
-//			if (this.syntheticAccessors == null)
-//				this.syntheticAccessors = new MethodBinding[2];
-//			this.syntheticAccessors[WRITE] = 
-//				((SourceTypeBinding)currentScope.enclosingSourceType().
-//					enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT)).
-//						addSyntheticMethod(fieldBinding, false);
-//			currentScope.problemReporter().needToEmulateFieldWriteAccess(fieldBinding, this);
-//			return;
-//		}
-		// if the binding declaring class is not visible, need special action
-		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
-		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
-		// and not from Object or implicit static field access.	
-		if (fieldBinding.declaringClass != this.delegateThis.type
-			&& fieldBinding.declaringClass != null
-			&& fieldBinding.constant == NotAConstant
-			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2 
-					&& !fieldBinding.isStatic()
-					&& fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
-				|| !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
-			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.delegateThis.type);
+					&& fieldBinding.declaringClass.id != T_JavaLangObject) // no change for Object fields (if there was any)
+				|| !((FieldBinding)this.codegenBinding).declaringClass.canBeSeenBy(currentScope))){
+			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding((FieldBinding)this.codegenBinding, (ReferenceBinding)this.delegateThis.type.erasure());
 		}
 	}
 }
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java
index d529ef8..381a026 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java
@@ -16,7 +16,8 @@
 import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
 import org.eclipse.jdt.internal.compiler.env.IConstants;
-import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * The skeleton of the class 'org.eclipse.jdt.internal.eval.target.CodeSnippet'
@@ -58,37 +59,33 @@
 			this.exceptionTypeNames = exceptionTypeNames;
 			this.isConstructor = isConstructor;
 		}
-		
 		public char[][] getExceptionTypeNames() {
 			return this.exceptionTypeNames;
 		}
-		
 		public char[] getMethodDescriptor() {
 			return this.methodDescriptor;
 		}
-		
 		public int getModifiers() {
 			return IConstants.AccPublic;
 		}
-		
 		public char[] getSelector() {
 			return this.selector;
 		}
-		
 		public boolean isClinit() {
 			return false;
 		}
-		
 		public boolean isConstructor() {
 			return this.isConstructor;
 		}
-		/**
-		 * @see org.eclipse.jdt.internal.compiler.env.IGenericMethod#getArgumentNames()
-		 */
 		public char[][] getArgumentNames() {
 			return null;
 		}
-
+		public char[] getGenericSignature() {
+			return null;
+		}
+		public long getTagBits() {
+			return 0;
+		}
 }
 	
 /**
@@ -103,8 +100,14 @@
 public IBinaryField[] getFields() {
 	return null;
 }
+/**
+ * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
+ */
 public char[] getFileName() {
-	return CharOperation.concat(CODE_SNIPPET_NAME, SuffixConstants.SUFFIX_java); //$NON-NLS-1$
+	return CharOperation.concat(CODE_SNIPPET_NAME, Util.defaultJavaExtension().toCharArray());
+}
+public char[] getGenericSignature() {
+	return null;
 }
 public char[][] getInterfaceNames() {
 	return null;
@@ -130,11 +133,11 @@
 public boolean isBinaryType() {
 	return true;
 }
-public boolean isClass() {
-	return true;
-}
-public boolean isInterface() {
-	return false;
+/**
+ * @see org.eclipse.jdt.internal.compiler.env.IGenericType#getKind()
+ */
+public int getKind() {
+	return IGenericType.CLASS_DECL;
 }
 public boolean isLocal() {
 	return false;
@@ -145,4 +148,7 @@
 public char[] sourceFileName() {
 	return null;
 }
+public long getTagBits() {
+	return 0;
+}
 }
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSuperReference.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSuperReference.java
index a7a0434..46be4a4 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSuperReference.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSuperReference.java
@@ -30,6 +30,13 @@
 	this.evaluationContext = evaluationContext;
 }
 
+/**
+ * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+ */
+public TypeBinding[] genericTypeArguments() {
+	return null;
+}
+
 public TypeBinding resolveType(BlockScope scope) {
 		scope.problemReporter().cannotUseSuperInCodeSnippet(this.sourceStart, this.sourceEnd); //$NON-NLS-1$
 		return null;
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java
index c1288e1..6498553 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java
@@ -61,6 +61,12 @@
 		}
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+	 */
+	public TypeBinding[] genericTypeArguments() {
+		return null;
+	}	
 	public boolean isSuperAccess(){
 		return false;
 	}
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetToCuMapper.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetToCuMapper.java
index f113447..9f36ecc 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetToCuMapper.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetToCuMapper.java
@@ -10,7 +10,10 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.eval;
 
-import org.eclipse.jdt.core.ICompletionRequestor;
+import org.eclipse.jdt.core.CompletionProposal;
+import org.eclipse.jdt.core.CompletionRequestor;
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.codeassist.ISelectionRequestor;
@@ -147,70 +150,44 @@
  * Returns a completion requestor that wraps the given requestor and shift the results
  * according to the start offset and line number offset of the code snippet in the generated compilation unit. 
  */
-public ICompletionRequestor getCompletionRequestor(final ICompletionRequestor originalRequestor) {
-	return new ICompletionRequestor() {
-		public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
-			originalRequestor.acceptAnonymousType(superTypePackageName, superTypeName, parameterPackageNames, parameterTypeNames, parameterNames, completionName, modifiers, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
+public CompletionRequestor getCompletionRequestor(final CompletionRequestor originalRequestor) {
+	return new CompletionRequestor() {
+		public void accept(CompletionProposal proposal) {
+			switch(proposal.getKind()) {
+				case CompletionProposal.TYPE_REF:
+					int flags = proposal.getFlags();
+					if((flags & Flags.AccEnum) == 0 &&
+							(flags & Flags.AccInterface) == 0) {
+						// Remove completion on generated class name or generated global variable class name
+						char[] packageName = proposal.getDeclarationSignature();
+						char[] className = Signature.getSignatureSimpleName(proposal.getSignature());
+						if (CharOperation.equals(packageName, CodeSnippetToCuMapper.this.snippetPackageName) 
+								&& (CharOperation.equals(className, CodeSnippetToCuMapper.this.snippetClassName)
+									|| CharOperation.equals(className, CodeSnippetToCuMapper.this.snippetVarClassName))) return;
+					}
+					break;
+				case CompletionProposal.METHOD_REF:
+				case CompletionProposal.METHOD_DECLARATION:
+					// Remove completion on generated method
+					char[] declaringTypePackageName = Signature.getSignatureSimpleName(proposal.getDeclarationSignature());
+					char[] declaringTypeName = Signature.getSignatureSimpleName(proposal.getDeclarationSignature());
+					char[] selector = proposal.getName();
+					if (CharOperation.equals(declaringTypePackageName, CodeSnippetToCuMapper.this.snippetPackageName) 
+							&& CharOperation.equals(declaringTypeName, CodeSnippetToCuMapper.this.snippetClassName)
+							&& CharOperation.equals(selector, "run".toCharArray())) return; //$NON-NLS-1$
+					break;
+			}
+			proposal.setReplaceRange(
+					proposal.getReplaceStart() - CodeSnippetToCuMapper.this.startPosOffset,
+					proposal.getReplaceEnd() - CodeSnippetToCuMapper.this.startPosOffset);
+			originalRequestor.accept(proposal);
 		}
 		
-		public void acceptClass(char[] packageName, char[] className, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-			// Remove completion on generated class name or generated global variable class name
-			if (CharOperation.equals(packageName, CodeSnippetToCuMapper.this.snippetPackageName) 
-					&& (CharOperation.equals(className, CodeSnippetToCuMapper.this.snippetClassName)
-						|| CharOperation.equals(className, CodeSnippetToCuMapper.this.snippetVarClassName))) return;
-			originalRequestor.acceptClass(packageName, className, completionName, modifiers, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
-		}
-		public void acceptError(IProblem error) {
-
-			error.setSourceStart(error.getSourceStart() - CodeSnippetToCuMapper.this.startPosOffset);
-			error.setSourceEnd(error.getSourceEnd() - CodeSnippetToCuMapper.this.startPosOffset);
-			error.setSourceLineNumber(error.getSourceLineNumber() -  CodeSnippetToCuMapper.this.lineNumberOffset);
-			originalRequestor.acceptError(error);
-		}
-		public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-			originalRequestor.acceptField(declaringTypePackageName, declaringTypeName, name, typePackageName, typeName, completionName, modifiers, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
-		}
-		public void acceptInterface(char[] packageName, char[] interfaceName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-			originalRequestor.acceptInterface(packageName, interfaceName, completionName, modifiers, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
-		}
-		public void acceptKeyword(char[] keywordName, int completionStart, int completionEnd, int relevance) {
-			originalRequestor.acceptKeyword(keywordName, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
-		}
-		public void acceptLabel(char[] labelName, int completionStart, int completionEnd, int relevance) {
-			originalRequestor.acceptLabel(labelName, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
-		}
-		public void acceptLocalVariable(char[] name, char[] typePackageName, char[] typeName, int modifiers, int completionStart, int completionEnd, int relevance) {
-			originalRequestor.acceptLocalVariable(name, typePackageName, typeName, modifiers, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
-		}
-		public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, char[][] parameterNames, char[] returnTypePackageName, char[] returnTypeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-			// Remove completion on generated method
-			if (CharOperation.equals(declaringTypePackageName, CodeSnippetToCuMapper.this.snippetPackageName) 
-					&& CharOperation.equals(declaringTypeName, CodeSnippetToCuMapper.this.snippetClassName)
-					&& CharOperation.equals(selector, "run".toCharArray())) return; //$NON-NLS-1$
-			originalRequestor.acceptMethod(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, parameterNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
-		}
-		public void acceptMethodDeclaration(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, char[][] parameterNames, char[] returnTypePackageName, char[] returnTypeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-			// Remove completion on generated method
-			if (CharOperation.equals(declaringTypePackageName, CodeSnippetToCuMapper.this.snippetPackageName) 
-					&& CharOperation.equals(declaringTypeName, CodeSnippetToCuMapper.this.snippetClassName)
-					&& CharOperation.equals(selector, "run".toCharArray())) return;//$NON-NLS-1$
-			originalRequestor.acceptMethodDeclaration(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, parameterNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
-		}
-		public void acceptModifier(char[] modifierName, int completionStart, int completionEnd, int relevance) {
-			originalRequestor.acceptModifier(modifierName, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
-		}
-		public void acceptPackage(char[] packageName, char[] completionName, int completionStart, int completionEnd, int relevance) {
-			originalRequestor.acceptPackage(packageName, completionName, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
-		}
-		public void acceptType(char[] packageName, char[] typeName, char[] completionName, int completionStart, int completionEnd, int relevance) {
-			// Remove completion on generated class name or generated global variable class name
-			if (CharOperation.equals(packageName, CodeSnippetToCuMapper.this.snippetPackageName) 
-					&& (CharOperation.equals( CodeSnippetToCuMapper.this.snippetClassName, CodeSnippetToCuMapper.this.snippetClassName)
-						|| CharOperation.equals( CodeSnippetToCuMapper.this.snippetClassName, CodeSnippetToCuMapper.this.snippetVarClassName))) return;
-			originalRequestor.acceptType(packageName, typeName, completionName, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
-		}
-		public void acceptVariableName(char[] typePackageName, char[] typeName, char[] name, char[] completionName, int completionStart, int completionEnd, int relevance){
-			originalRequestor.acceptVariableName(typePackageName, typeName, name, completionName, completionStart, completionEnd, relevance);
+		public void completionFailure(IProblem problem) {
+			problem.setSourceStart(problem.getSourceStart() - CodeSnippetToCuMapper.this.startPosOffset);
+			problem.setSourceEnd(problem.getSourceEnd() - CodeSnippetToCuMapper.this.startPosOffset);
+			problem.setSourceLineNumber(problem.getSourceLineNumber() -  CodeSnippetToCuMapper.this.lineNumberOffset);
+			originalRequestor.completionFailure(problem);
 		}
 	};
 }
@@ -271,8 +248,14 @@
  */
 public ISelectionRequestor getSelectionRequestor(final ISelectionRequestor originalRequestor) {
 	return new ISelectionRequestor() {
-		public void acceptClass(char[] packageName, char[] className, boolean needQualification, boolean isDeclaration, int start, int end) {
-			originalRequestor.acceptClass(packageName, className, needQualification, isDeclaration, start, end);
+		public void acceptAnnotation(char[] packageName, char[] annotationName, boolean isDeclaration, char[] uniqueKey, int start, int end) {
+			originalRequestor.acceptAnnotation(packageName, annotationName, isDeclaration, uniqueKey, start, end);
+		}
+		public void acceptClass(char[] packageName, char[] className, boolean isDeclaration, char[] uniqueKey, int start, int end) {
+			originalRequestor.acceptClass(packageName, className, isDeclaration, uniqueKey, start, end);
+		}
+		public void acceptEnum(char[] packageName, char[] enumName, boolean isDeclaration, char[] uniqueKey, int start, int end) {
+			originalRequestor.acceptClass(packageName, enumName, isDeclaration, uniqueKey, start, end);
 		}
 		public void acceptError(IProblem error) {
 			error.setSourceLineNumber(error.getSourceLineNumber() -  CodeSnippetToCuMapper.this.lineNumberOffset);
@@ -280,18 +263,25 @@
 			error.setSourceEnd(error.getSourceEnd() - CodeSnippetToCuMapper.this.startPosOffset);
 			originalRequestor.acceptError(error);
 		}
-		public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, boolean isDeclaration, int start, int end) {
-			originalRequestor.acceptField(declaringTypePackageName, declaringTypeName, name, isDeclaration, start, end);
+		public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, boolean isDeclaration, char[] uniqueKey, int start, int end) {
+			originalRequestor.acceptField(declaringTypePackageName, declaringTypeName, name, isDeclaration, uniqueKey, start, end);
 		}
-		public void acceptInterface(char[] packageName, char[] interfaceName, boolean needQualification, boolean isDeclaration, int start, int end) {
-			originalRequestor.acceptInterface(packageName, interfaceName, needQualification, isDeclaration, start, end);
+		public void acceptInterface(char[] packageName, char[] interfaceName, boolean isDeclaration, char[] uniqueKey, int start, int end) {
+			originalRequestor.acceptInterface(packageName, interfaceName, isDeclaration, uniqueKey, start, end);
 		}
-		public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, boolean isConstructor, boolean isDeclaration, int start, int end) {
-			originalRequestor.acceptMethod(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, isConstructor, isDeclaration, start, end);
+		public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, String enclosingDeclaringTypeSignature, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, String[] parameterSignatures, boolean isConstructor, boolean isDeclaration, char[] uniqueKey, int start, int end) {
+			originalRequestor.acceptMethod(declaringTypePackageName, declaringTypeName, enclosingDeclaringTypeSignature, selector, parameterPackageNames, parameterTypeNames, parameterSignatures, isConstructor, isDeclaration, uniqueKey, start, end);
 		}
 		public void acceptPackage(char[] packageName) {
 			originalRequestor.acceptPackage(packageName);
 		}
+		
+		public void acceptTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] typeParameterName, boolean isDeclaration, int start, int end) {
+			originalRequestor.acceptTypeParameter(declaringTypePackageName, declaringTypeName, typeParameterName, isDeclaration, start, end);
+		}
+		public void acceptMethodTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, int selectorStart, int selectorEnd, char[] typeParameterName,boolean isDeclaration, int start, int end) {
+			originalRequestor.acceptMethodTypeParameter(declaringTypePackageName, declaringTypeName, selector, selectorStart, selectorEnd, typeParameterName, isDeclaration, start, end);
+		}
 	};
 }
 }
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java
index 45a4f89..d2414ec 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java
@@ -12,11 +12,11 @@
 
 import java.util.Map;
 
+import org.eclipse.jdt.core.CompletionRequestor;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.codeassist.CompletionEngine;
-import org.eclipse.jdt.internal.codeassist.ISearchableNameEnvironment;
 import org.eclipse.jdt.internal.codeassist.ISelectionRequestor;
 import org.eclipse.jdt.internal.codeassist.SelectionEngine;
 import org.eclipse.jdt.internal.compiler.ClassFile;
@@ -26,7 +26,8 @@
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
-import org.eclipse.jdt.internal.core.CompletionRequestorWrapper;
+import org.eclipse.jdt.internal.core.SearchableEnvironment;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * @see org.eclipse.jdt.core.eval.IEvaluationContext
@@ -95,7 +96,7 @@
  *  @param options
  *		set of options used to configure the code assist engine.
  */
-public void complete(char[] codeSnippet, int completionPosition, ISearchableNameEnvironment environment, CompletionRequestorWrapper requestor, Map options, IJavaProject project) {
+public void complete(char[] codeSnippet, int completionPosition, SearchableEnvironment environment, CompletionRequestor requestor, Map options, IJavaProject project) {
 	final char[] className = "CodeSnippetCompletion".toCharArray(); //$NON-NLS-1$
 	final CodeSnippetToCuMapper mapper = new CodeSnippetToCuMapper(
 		codeSnippet, 
@@ -110,7 +111,7 @@
 	);
 	ICompilationUnit sourceUnit = new ICompilationUnit() {
 		public char[] getFileName() {
-			return CharOperation.concat(className, SUFFIX_java);
+			return CharOperation.concat(className, Util.defaultJavaExtension().toCharArray());
 		}
 		public char[] getContents() {
 			return mapper.getCUSource();
@@ -123,7 +124,6 @@
 		}
 	};
 	CompletionEngine engine = new CompletionEngine(environment, mapper.getCompletionRequestor(requestor), options, project);
-	requestor.completionEngine = engine;
 	engine.complete(sourceUnit, mapper.startPosOffset + completionPosition, 0);
 }
 /**
@@ -482,7 +482,7 @@
  * 
  *  @param selectionSourceEnd int
  * 
- *  @param environment org.eclipse.jdt.internal.codeassist.ISearchableNameEnvironment
+ *  @param environment org.eclipse.jdt.internal.core.SearchableEnvironment
  *      used to resolve type/package references and search for types/packages
  *      based on partial names.
  *
@@ -497,7 +497,7 @@
 	char[] codeSnippet,
 	int selectionSourceStart,
 	int selectionSourceEnd,
-	ISearchableNameEnvironment environment, 
+	SearchableEnvironment environment, 
 	ISelectionRequestor requestor,
 	Map options) {
 		
@@ -515,7 +515,7 @@
 	);
 	ICompilationUnit sourceUnit = new ICompilationUnit() {
 		public char[] getFileName() {
-			return CharOperation.concat(className, SUFFIX_java);
+			return CharOperation.concat(className, Util.defaultJavaExtension().toCharArray());
 		}
 		public char[] getContents() {
 			return mapper.getCUSource();
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/Evaluator.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/Evaluator.java
index 45d05cc..5e1c26e 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/Evaluator.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/Evaluator.java
@@ -25,7 +25,7 @@
 import org.eclipse.jdt.internal.compiler.IProblemFactory;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
-import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * A evaluator builds a compilation unit and compiles it into class files.
@@ -130,7 +130,7 @@
 	compiler.compile(new ICompilationUnit[] {new ICompilationUnit() {
 		public char[] getFileName() {
 			 // Name of class is name of CU
-			return CharOperation.concat(Evaluator.this.getClassName(), SuffixConstants.SUFFIX_java); //$NON-NLS-1$
+			return CharOperation.concat(Evaluator.this.getClassName(), Util.defaultJavaExtension().toCharArray());
 		}
 		public char[] getContents() {
 			return source;
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/InstallException.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/InstallException.java
index a84d03d..317bc2e 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/InstallException.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/InstallException.java
@@ -15,6 +15,8 @@
  * for any reason.
  */
 public class InstallException extends Exception {
+	
+	private static final long serialVersionUID = -5870897747810654203L;	// backward compatible
 /**
  * Constructs a <code>InstallException</code> with no detail  message.
  */
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/VariablesEvaluator.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/VariablesEvaluator.java
index ed9616b..48b15d0 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/VariablesEvaluator.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/VariablesEvaluator.java
@@ -151,7 +151,7 @@
 	// Initialize the compiler's lookup environment with the already compiled super class
 	IBinaryType binaryType = this.context.getRootCodeSnippetBinary();
 	if (binaryType != null) {
-		compiler.lookupEnvironment.cacheBinaryType(binaryType);
+		compiler.lookupEnvironment.cacheBinaryType(binaryType, null /*no access restriction*/);
 	}
 
 	// and the installed global variable classes
@@ -166,7 +166,7 @@
 			} catch (ClassFormatException e) {
 				e.printStackTrace(); // Should never happen since we compiled this type
 			}
-			compiler.lookupEnvironment.cacheBinaryType(binary);
+			compiler.lookupEnvironment.cacheBinaryType(binary, null /*no access restriction*/);
 		}
 	}
 	
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
index 8906948..f1b76ef 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
@@ -184,6 +184,17 @@
 	public static final String FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_ALLOCATION_EXPRESSION = JavaCore.PLUGIN_ID + ".formatter.alignment_for_arguments_in_allocation_expression";	 //$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option for alignment of arguments in enum constant
+	 *     - option id:         "org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant"
+	 *     - possible values:   values returned by <code>createAlignmentValue(boolean, int, int)</code> call
+	 *     - default:           createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+	 * </pre>
+	 * @see #createAlignmentValue(boolean, int, int)
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_ENUM_CONSTANT = JavaCore.PLUGIN_ID + ".formatter.alignment_for_arguments_in_enum_constant";	 //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option for alignment of arguments in explicit constructor call
 	 *     - option id:         "org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call"
 	 *     - possible values:   values returned by <code>createAlignmentValue(boolean, int, int)</code> call
@@ -316,10 +327,21 @@
 	public static final String FORMATTER_ALIGNMENT_FOR_SUPERCLASS_IN_TYPE_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.alignment_for_superclass_in_type_declaration";	 //$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option for alignment of superinterfaces in enum declaration
+	 *     - option id:         "org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration"
+	 *     - possible values:   values returned by <code>createAlignmentValue(boolean, int, int)</code> call
+	 *     - default:           createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+	 * </pre>
+	 * @see #createAlignmentValue(boolean, int, int)
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_ALIGNMENT_FOR_SUPERINTERFACES_IN_ENUM_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.alignment_for_superinterfaces_in_enum_declaration";	 //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option for alignment of superinterfaces in type declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration"
 	 *     - possible values:   values returned by <code>createAlignmentValue(boolean, int, int)</code> call
-	 *     - default:           createAlignmentValue(false, WRAP_NEXT_SHIFTED, INDENT_DEFAULT)
+	 *     - default:           createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
 	 * </pre>
 	 * @see #createAlignmentValue(boolean, int, int)
 	 * @since 3.0
@@ -359,10 +381,23 @@
 	 * @since 3.0
 	 */
 	public static final String FORMATTER_ALIGN_TYPE_MEMBERS_ON_COLUMNS = JavaCore.PLUGIN_ID + ".formatter.align_type_members_on_columns";	 //$NON-NLS-1$
-	
 	/**
 	 * <pre>
-	 * FORMATTER / Option to position the braces of a anonymous type declaration
+	 * FORMATTER / Option to position the braces of an annotation type declaration
+	 *     - option id:         "org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration"
+	 *     - possible values:   { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
+	 *     - default:           END_OF_LINE
+	 * </pre>
+	 * @see #END_OF_LINE
+	 * @see #NEXT_LINE
+	 * @see #NEXT_LINE_SHIFTED
+	 * @see #NEXT_LINE_ON_WRAP
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_BRACE_POSITION_FOR_ANNOTATION_TYPE_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.brace_position_for_annotation_type_declaration";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to position the braces of an anonymous type declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration"
 	 *     - possible values:   { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
 	 *     - default:           END_OF_LINE
@@ -433,6 +468,34 @@
 	public static final String FORMATTER_BRACE_POSITION_FOR_CONSTRUCTOR_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.brace_position_for_constructor_declaration";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to position the braces of an enum constant
+	 *     - option id:         "org.eclipse.jdt.core.formatter.brace_position_for_enum_constant"
+	 *     - possible values:   { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
+	 *     - default:           END_OF_LINE
+	 * </pre>
+	 * @see #END_OF_LINE
+	 * @see #NEXT_LINE
+	 * @see #NEXT_LINE_SHIFTED
+	 * @see #NEXT_LINE_ON_WRAP
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_BRACE_POSITION_FOR_ENUM_CONSTANT = JavaCore.PLUGIN_ID + ".formatter.brace_position_for_enum_constant";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to position the braces of an enum declaration
+	 *     - option id:         "org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration"
+	 *     - possible values:   { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
+	 *     - default:           END_OF_LINE
+	 * </pre>
+	 * @see #END_OF_LINE
+	 * @see #NEXT_LINE
+	 * @see #NEXT_LINE_SHIFTED
+	 * @see #NEXT_LINE_ON_WRAP
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_BRACE_POSITION_FOR_ENUM_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.brace_position_for_enum_declaration";	//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to position the braces of a method declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.brace_position_for_method_declaration"
 	 *     - possible values:   { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
@@ -605,7 +668,30 @@
 	 * @since 3.0
 	 */
 	public static final String FORMATTER_BLANK_LINES_AT_BEGINNING_OF_METHOD_BODY = JavaCore.PLUGIN_ID + ".formatter.number_of_blank_lines_at_beginning_of_method_body"; //$NON-NLS-1$
-
+	/**
+	 * <pre>
+	 * FORMATTER / Option to indent body declarations compare to its enclosing enum constant header
+	 *     - option id:         "org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header"
+	 *     - possible values:   { TRUE, FALSE }
+	 *     - default:           TRUE
+	 * </pre>
+	 * @see #TRUE
+	 * @see #FALSE
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_ENUM_CONSTANT_HEADER = JavaCore.PLUGIN_ID + ".formatter.indent_body_declarations_compare_to_enum_constant_header";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to indent body declarations compare to its enclosing enum declaration header
+	 *     - option id:         "org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header"
+	 *     - possible values:   { TRUE, FALSE }
+	 *     - default:           TRUE
+	 * </pre>
+	 * @see #TRUE
+	 * @see #FALSE
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_ENUM_DECLARATION_HEADER = JavaCore.PLUGIN_ID + ".formatter.indent_body_declarations_compare_to_enum_declaration_header";	//$NON-NLS-1$
 	/**
 	 * <pre>
 	 * FORMATTER / Option to indent body declarations compare to its enclosing type header
@@ -691,6 +777,19 @@
 	 * @since 3.0
 	 */
 	public static final String FORMATTER_INSERT_NEW_LINE_AFTER_OPENING_BRACE_IN_ARRAY_INITIALIZER = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_after_opening_brace_in_array_initializer";//$NON-NLS-1$
+
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a new line at the end of the current file if missing
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_NEW_LINE_AT_END_OF_FILE_IF_MISSING = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_at_end_of_file_if_missing";//$NON-NLS-1$
 	/**
 	 * <pre>
 	 * FORMATTER / Option to insert a new line before the catch keyword in try statement
@@ -777,6 +876,30 @@
 	public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_BLOCK = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_block";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a new line in an empty enum constant
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ENUM_CONSTANT = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_enum_constant";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a new line in an empty enum declaration
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ENUM_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_enum_declaration";	//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a new line in an empty method body
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -801,6 +924,18 @@
 	public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_TYPE_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_type_declaration";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space after and in wilcard
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_AND_IN_TYPE_PARAMETER = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_and_in_type_parameter"; //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space after an assignment operator
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -813,6 +948,30 @@
 	public static final String FORMATTER_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_assignment_operator"; //$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space after at in annotation
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_AT_IN_ANNOTATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_at_in_annotation"; //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space after at in annotation type declaration
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_AT_IN_ANNOTATION_TYPE_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_at_in_annotation_type_declaration"; //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space after a binary operator
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_binary_operator"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -825,6 +984,30 @@
 	public static final String FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_binary_operator"; //$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space after the closing angle bracket in type arguments
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_closing_angle_bracket_in_type_arguments"; //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space after the closing angle bracket in type parameters
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_PARAMETERS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_closing_angle_bracket_in_type_parameters"; //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space after the closing parenthesis of a cast expression
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -885,6 +1068,18 @@
 	public static final String FORMATTER_INSERT_SPACE_AFTER_COLON_IN_CONDITIONAL = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_colon_in_conditional"; //$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space after colon in a for statement
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COLON_IN_FOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_colon_in_for";	//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space after the colon in a labeled statement
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -909,6 +1104,18 @@
 	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ALLOCATION_EXPRESSION = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_allocation_expression"; //$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space after the comma in annotation
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ANNOTATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_annotation"; //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space after the comma in an array initializer
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -945,6 +1152,30 @@
 	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_CONSTRUCTOR_DECLARATION_THROWS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_constructor_declaration_throws"; //$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space after the comma in the arguments of an enum constant
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ENUM_CONSTANT_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_enum_constant_arguments"; //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space after the comma in enum declarations
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ENUM_DECLARATIONS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_enum_declarations"; //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space after the comma in the arguments of an explicit constructor call
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1041,6 +1272,18 @@
 	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_MULTIPLE_LOCAL_DECLARATIONS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_multiple_local_declarations"; //$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space after the comma in parameterized type reference
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_PARAMETERIZED_TYPE_REFERENCE = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_parameterized_type_reference"; //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space after the comma in superinterfaces names of a type header
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1053,6 +1296,78 @@
 	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_SUPERINTERFACES = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_superinterfaces"; //$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space after the comma in type arguments
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_type_arguments"; //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space after the comma in type parameters
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_TYPE_PARAMETERS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_type_parameters"; //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space after ellipsis
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_ellipsis"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_ELLIPSIS  = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_ellipsis";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space after the opening angle bracket in parameterized type reference
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_ANGLE_BRACKET_IN_PARAMETERIZED_TYPE_REFERENCE = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference";//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space after the opening angle bracket in type arguments
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_opening_angle_bracket_in_type_arguments";//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space after the opening angle bracket in type parameters
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETERS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_opening_angle_bracket_in_type_parameters";//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space after the opening bracket inside an array allocation expression
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1089,6 +1404,18 @@
 	public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_BRACE_IN_ARRAY_INITIALIZER = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_opening_brace_in_array_initializer";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space after the opening parenthesis in annotation
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_ANNOTATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_annotation"; //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space after the opening parenthesis in a cast expression
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1125,6 +1452,18 @@
 	public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_CONSTRUCTOR_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_constructor_declaration";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space after the opening parenthesis in enum constant
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_ENUM_CONSTANT = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_enum_constant"; //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space after the opening parenthesis in a for statement
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1257,6 +1596,18 @@
 	public static final String FORMATTER_INSERT_SPACE_AFTER_QUESTION_IN_CONDITIONAL = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_question_in_conditional"; //$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space after question mark in a wildcard
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_AFTER_QUESTION_IN_WILDCARD = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_question_in_wildcard"; //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space after semicolon in a for statement
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1279,7 +1630,30 @@
 	 * @since 3.0
 	 */
 	public static final String FORMATTER_INSERT_SPACE_AFTER_UNARY_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_unary_operator"; //$NON-NLS-1$
-	
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space before and in wildcard
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_AND_IN_TYPE_PARAMETER = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_and_in_type_parameter";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space before at in annotation type declaration
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_AT_IN_ANNOTATION_TYPE_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_at_in_annotation_type_declaration";	//$NON-NLS-1$
 	/**
 	 * <pre>
 	 * FORMATTER / Option to insert a space before an assignment operator
@@ -1306,6 +1680,42 @@
 	public static final String FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_binary_operator";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space before the closing angle bracket in parameterized type reference
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_ANGLE_BRACKET_IN_PARAMETERIZED_TYPE_REFERENCE = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference";		//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space before the closing angle bracket in type arguments
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_closing_angle_bracket_in_type_arguments";		//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space before the closing angle bracket in type parameters
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_ANGLE_BRACKET_IN_TYPE_PARAMETERS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_closing_angle_bracket_in_type_parameters";		//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space before the closing brace in an array initializer
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1342,6 +1752,18 @@
 	public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_BRACKET_IN_ARRAY_REFERENCE = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_closing_bracket_in_array_reference";//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space before the closing parenthesis in annotation
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_ANNOTATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_annotation";	//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space before the closing parenthesis in a cast expression
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1378,6 +1800,18 @@
 	public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_CONSTRUCTOR_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_constructor_declaration";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space before the closing parenthesis in enum constant
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_ENUM_CONSTANT = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_enum_constant";	//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space before the closing parenthesis in a for statement
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1522,6 +1956,18 @@
 	public static final String FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_DEFAULT = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_colon_in_default";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space before colon in a for statement
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_FOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_colon_in_for";	//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space before colon in a labeled statement
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1546,6 +1992,18 @@
 	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ALLOCATION_EXPRESSION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_allocation_expression";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space before comma in annotation
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ANNOTATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_annotation";	//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space before comma in an array initializer
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1582,6 +2040,30 @@
 	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_CONSTRUCTOR_DECLARATION_THROWS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_constructor_declaration_throws";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space before comma in the arguments of enum constant
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ENUM_CONSTANT_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_enum_constant_arguments";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space before comma in enum declarations
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ENUM_DECLARATIONS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_enum_declarations";	//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space before comma in the arguments of an explicit constructor call
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1678,6 +2160,18 @@
 	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_MULTIPLE_LOCAL_DECLARATIONS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_multiple_local_declarations";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space before comma in parameterized type reference
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_PARAMETERIZED_TYPE_REFERENCE = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_parameterized_type_reference";	//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space before comma in the superinterfaces names in a type header
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1690,6 +2184,90 @@
 	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_SUPERINTERFACES = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_superinterfaces";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space before comma in type arguments
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_TYPE_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_type_arguments";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space before comma in type parameters
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_TYPE_PARAMETERS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_type_parameters";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space before ellipsis
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_ellipsis"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_ELLIPSIS  = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_ellipsis";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space before the opening angle bracket in parameterized type reference
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_PARAMETERIZED_TYPE_REFERENCE  = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space before the opening angle bracket in type arguments
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_opening_angle_bracket_in_type_arguments";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space before the opening angle bracket in type parameters
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETERS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_opening_angle_bracket_in_type_parameters";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space before the opening brace in an annotation type declaration
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ANNOTATION_TYPE_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_opening_brace_in_annotation_type_declaration"; 	//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space before the opening brace in an anonymous type declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1738,6 +2316,30 @@
 	public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_CONSTRUCTOR_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_opening_brace_in_constructor_declaration";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space before the opening brace in an enum constant
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ENUM_CONSTANT = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_opening_brace_in_enum_constant";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space before the opening brace in an enum declaration
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ENUM_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_opening_brace_in_enum_declaration";	//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space before the opening brace in a method declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1810,6 +2412,30 @@
 	public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACKET_IN_ARRAY_TYPE_REFERENCE = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_opening_bracket_in_array_type_reference";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space before the opening parenthesis in annotation
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_ANNOTATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_annotation";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to insert a space before the opening parenthesis in annotation type member declaration
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_ANNOTATION_TYPE_MEMBER_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration";	//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space before the opening parenthesis in a catch
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1834,6 +2460,18 @@
 	public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_CONSTRUCTOR_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_constructor_declaration";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space before the opening parenthesis in enum constant
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_ENUM_CONSTANT = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_enum_constant";	//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space before the opening parenthesis in a for statement
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -1966,6 +2604,18 @@
 	public static final String FORMATTER_INSERT_SPACE_BEFORE_QUESTION_IN_CONDITIONAL = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_question_in_conditional";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space before question mark in a wildcard
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_QUESTION_IN_WILDCARD = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_question_in_wildcard"; //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space before semicolon
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_before_semicolon"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -2039,6 +2689,18 @@
 	public static final String FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_BRACKETS_IN_ARRAY_ALLOCATION_EXPRESSION = JavaCore.PLUGIN_ID + ".formatter.insert_space_between_empty_brackets_in_array_allocation_expression";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space between empty parenthesis in an annotation type member declaration
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_PARENS_IN_ANNOTATION_TYPE_MEMBER_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration";	//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space between empty parenthesis in a constructor declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -2051,6 +2713,18 @@
 	public static final String FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_PARENS_IN_CONSTRUCTOR_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_between_empty_parens_in_constructor_declaration";	//$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a space between empty parenthesis in enum constant
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           DO_NOT_INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.1
+	 */
+	public static final String FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_PARENS_IN_ENUM_CONSTANT = JavaCore.PLUGIN_ID + ".formatter.insert_space_between_empty_parens_in_enum_constant";	//$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a space between empty parenthesis in a method declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/AbortFormatting.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/AbortFormatting.java
index 069c098..48d702f 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/AbortFormatting.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/AbortFormatting.java
@@ -19,6 +19,7 @@
 public class AbortFormatting extends RuntimeException {
 
 	Throwable nestedException;
+	private static final long serialVersionUID = -5796507276311428526L; // backward compatible
 	
 	public AbortFormatting(String message) {
 		super(message);
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java
index abd4b26..ea3a5f3 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java
@@ -20,7 +20,9 @@
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Argument;
 import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
 import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
@@ -54,6 +56,7 @@
 import org.eclipse.jdt.internal.compiler.ast.FieldReference;
 import org.eclipse.jdt.internal.compiler.ast.FloatLiteral;
 import org.eclipse.jdt.internal.compiler.ast.ForStatement;
+import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
 import org.eclipse.jdt.internal.compiler.ast.IfStatement;
 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
 import org.eclipse.jdt.internal.compiler.ast.Initializer;
@@ -62,8 +65,14 @@
 import org.eclipse.jdt.internal.compiler.ast.LabeledStatement;
 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.LongLiteral;
+import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
+import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
 import org.eclipse.jdt.internal.compiler.ast.MessageSend;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
 import org.eclipse.jdt.internal.compiler.ast.StringLiteralConcatenation;
 import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
 import org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression;
@@ -88,10 +97,13 @@
 import org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
 import org.eclipse.jdt.internal.compiler.ast.TryStatement;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
 import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
 import org.eclipse.jdt.internal.compiler.ast.WhileStatement;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
@@ -149,6 +161,11 @@
 		TerminalTokens.TokenNameshort,
 		TerminalTokens.TokenNamevoid
 	};
+	private static final int[] CLOSING_GENERICS_EXPECTEDTOKENS = new int[] {
+		TerminalTokens.TokenNameRIGHT_SHIFT,
+		TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT,
+		TerminalTokens.TokenNameGREATER
+	};
 	private int chunkKind;
 	public int lastLocalDeclarationSourceStart;
 	private Scanner localScanner;
@@ -158,11 +175,13 @@
 	public CodeFormatterVisitor(DefaultCodeFormatterOptions preferences, Map settings, int offset, int length, CodeSnippetParsingUtil codeSnippetParsingUtil) {
 		if (settings != null) {
 			Object assertModeSetting = settings.get(JavaCore.COMPILER_SOURCE);
-			if (assertModeSetting != null) {
-				this.localScanner = new Scanner(true, false, false/*nls*/, JavaCore.VERSION_1_4.equals(assertModeSetting) ? ClassFileConstants.JDK1_4 : ClassFileConstants.JDK1_3/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
-			} else {
-				this.localScanner = new Scanner(true, false, false/*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
-			}
+			long sourceLevel = ClassFileConstants.JDK1_3;
+			if (JavaCore.VERSION_1_4.equals(assertModeSetting)) {
+				sourceLevel = ClassFileConstants.JDK1_4;
+			} else if (JavaCore.VERSION_1_5.equals(assertModeSetting)) {
+				sourceLevel = ClassFileConstants.JDK1_5;
+			}		
+			this.localScanner = new Scanner(true, false, false/*nls*/, sourceLevel/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
 		} else {
 			this.localScanner = new Scanner(true, false, false/*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
 		}
@@ -267,6 +286,47 @@
 		}
 		return false;
 	}
+
+	private ASTNode[] computeMergedMemberDeclarations(ASTNode[] nodes){
+		ArrayList mergedNodes = new ArrayList();
+		for (int i = 0, max = nodes.length; i < max; i++) {
+			ASTNode currentNode = nodes[i];
+			if (currentNode instanceof FieldDeclaration) {
+				FieldDeclaration currentField = (FieldDeclaration) currentNode;
+				if (mergedNodes.size() == 0) {
+					// first node
+					mergedNodes.add(currentNode);
+				} else {
+					// we need to check if the previous merged node is a field declaration
+					ASTNode previousMergedNode = (ASTNode) mergedNodes.get(mergedNodes.size() - 1);
+					if (previousMergedNode instanceof MultiFieldDeclaration) {
+						// we merge the current node
+						MultiFieldDeclaration multiFieldDeclaration = (MultiFieldDeclaration) previousMergedNode;
+						int length = multiFieldDeclaration.declarations.length;
+						System.arraycopy(multiFieldDeclaration.declarations, 0, multiFieldDeclaration.declarations= new FieldDeclaration[length+1], 0, length);
+						multiFieldDeclaration.declarations[length] = currentField;
+					} else if (previousMergedNode instanceof FieldDeclaration) {
+						// need to check we need to create a multiple field declaration
+						if (currentField.declarationSourceStart == ((FieldDeclaration) previousMergedNode).declarationSourceStart) {
+							// we create a multi field declaration
+							mergedNodes.set(mergedNodes.size() - 1, new MultiFieldDeclaration(new FieldDeclaration[]{ (FieldDeclaration)previousMergedNode, currentField}));
+						}
+					} else {
+						mergedNodes.add(currentNode);
+					}
+				}
+			} else {
+				mergedNodes.add(currentNode);
+			}
+		}
+		if (mergedNodes.size() != nodes.length) {
+			ASTNode[] result = new ASTNode[mergedNodes.size()];
+			mergedNodes.toArray(result);
+			return result;
+		} else {
+			return nodes;
+		}
+	}
 	
 	private ASTNode[] computeMergedMemberDeclarations(TypeDeclaration typeDeclaration){
 		
@@ -289,6 +349,16 @@
 			int previousFieldStart = -1;
 			do {
 				if (fieldStart < methodStart && fieldStart < typeStart) {
+					if (field.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+						// filter out enum constants
+						previousFieldStart = fieldStart;
+						if (++fieldIndex < fieldCount) { // find next field if any
+							fieldStart = (field = typeDeclaration.fields[fieldIndex]).declarationSourceStart;
+						} else {
+							fieldStart = Integer.MAX_VALUE;
+						}
+						continue;
+					}
 					// next member is a field
 					if (fieldStart == previousFieldStart){ 
 						ASTNode previousMember = members[index - 1];
@@ -336,47 +406,6 @@
 		}
 		return members;
 	}
-
-	private ASTNode[] computeMergedMemberDeclarations(ASTNode[] nodes){
-		ArrayList mergedNodes = new ArrayList();
-		for (int i = 0, max = nodes.length; i < max; i++) {
-			ASTNode currentNode = nodes[i];
-			if (currentNode instanceof FieldDeclaration) {
-				FieldDeclaration currentField = (FieldDeclaration) currentNode;
-				if (mergedNodes.size() == 0) {
-					// first node
-					mergedNodes.add(currentNode);
-				} else {
-					// we need to check if the previous merged node is a field declaration
-					ASTNode previousMergedNode = (ASTNode) mergedNodes.get(mergedNodes.size() - 1);
-					if (previousMergedNode instanceof MultiFieldDeclaration) {
-						// we merge the current node
-						MultiFieldDeclaration multiFieldDeclaration = (MultiFieldDeclaration) previousMergedNode;
-						int length = multiFieldDeclaration.declarations.length;
-						System.arraycopy(multiFieldDeclaration.declarations, 0, multiFieldDeclaration.declarations= new FieldDeclaration[length+1], 0, length);
-						multiFieldDeclaration.declarations[length] = currentField;
-					} else if (previousMergedNode instanceof FieldDeclaration) {
-						// need to check we need to create a multiple field declaration
-						if (currentField.declarationSourceStart == ((FieldDeclaration) previousMergedNode).declarationSourceStart) {
-							// we create a multi field declaration
-							mergedNodes.set(mergedNodes.size() - 1, new MultiFieldDeclaration(new FieldDeclaration[]{ (FieldDeclaration)previousMergedNode, currentField}));
-						}
-					} else {
-						mergedNodes.add(currentNode);
-					}
-				}
-			} else {
-				mergedNodes.add(currentNode);
-			}
-		}
-		if (mergedNodes.size() != nodes.length) {
-			ASTNode[] result = new ASTNode[mergedNodes.size()];
-			mergedNodes.toArray(result);
-			return result;
-		} else {
-			return nodes;
-		}
-	}
 	
 	private boolean dumpBinaryExpression(
 		BinaryExpression binaryExpression,
@@ -410,7 +439,7 @@
 						}
 						this.scribe.alignFragment(binaryExpressionAlignment, i);
 						this.scribe.printNextToken(operators[i], this.preferences.insert_space_before_binary_operator);
-						if (operators[i] == TerminalTokens.TokenNameMINUS && isMinus()) {
+						if (operators[i] == TerminalTokens.TokenNameMINUS && isNextToken(TerminalTokens.TokenNameMINUS)) {
 							// the next character is a minus (unary operator)
 							this.scribe.space();
 						}
@@ -429,7 +458,7 @@
 		} else {
 			binaryExpression.left.traverse(this, scope);
 			this.scribe.printNextToken(operator, this.preferences.insert_space_before_binary_operator);
-			if (operator == TerminalTokens.TokenNameMINUS && isMinus()) {
+			if (operator == TerminalTokens.TokenNameMINUS && isNextToken(TerminalTokens.TokenNameMINUS)) {
 				// the next character is a minus (unary operator)
 				this.scribe.space();
 			}
@@ -500,52 +529,6 @@
 		}
 		methodDeclaration.traverse(this, scope);
 	}
-	
-	/**
-	 * @param block
-	 * @param scope
-	 * @param block_brace_position
-	 */
-	private void formatBlock(Block block, BlockScope scope, String block_brace_position, boolean insertSpaceBeforeOpeningBrace) {
-		formatOpeningBrace(block_brace_position, insertSpaceBeforeOpeningBrace);
-		final Statement[] statements = block.statements;
-		if (statements != null) {
-			this.scribe.printNewLine();
-			if (this.preferences.indent_statements_compare_to_block) {
-				this.scribe.indent();
-			}
-			formatStatements(scope, statements, true);
-			this.scribe.printComment();
-	
-			if (this.preferences.indent_statements_compare_to_block) {
-				this.scribe.unIndent();
-			}
-		} else if (this.preferences.insert_new_line_in_empty_block) {
-			this.scribe.printNewLine();
-			if (this.preferences.indent_statements_compare_to_block) {
-				this.scribe.indent();
-			}
-			this.scribe.printComment();
-	
-			if (this.preferences.indent_statements_compare_to_block) {
-				this.scribe.unIndent();
-			}
-		} else {
-			if (this.preferences.indent_statements_compare_to_block) {
-				this.scribe.indent();
-			}
-			this.scribe.printComment();
-	
-			if (this.preferences.indent_statements_compare_to_block) {
-				this.scribe.unIndent();
-			}
-		}
-		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
-		this.scribe.printTrailingComment();
-		if (DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(block_brace_position)) {
-			this.scribe.unIndent();
-		}
-	}
 
 	private void format(FieldDeclaration fieldDeclaration, ASTVisitor visitor, MethodScope scope, boolean isChunkStart, boolean isFirstClassBodyDeclaration) {
 		
@@ -567,7 +550,7 @@
 		Alignment memberAlignment = this.scribe.getMemberAlignment();	//$NON-NLS-1$
 	
         this.scribe.printComment();
-		this.scribe.printModifiers();
+		this.scribe.printModifiers(fieldDeclaration.annotations, this);
 		this.scribe.space();
 		/*
 		 * Field type
@@ -584,7 +567,7 @@
 		/*
 		 * Check for extra dimensions
 		 */
-		int extraDimensions = getExtraDimension();
+		int extraDimensions = getDimensions();
 		if (extraDimensions != 0) {
 			 for (int i = 0; i < extraDimensions; i++) {
 			 	this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
@@ -615,30 +598,6 @@
 			this.scribe.printTrailingComment();
 		}
 	}
-
-	private void format(
-		TypeDeclaration memberTypeDeclaration,
-		ClassScope scope,
-		boolean isChunkStart,
-		boolean isFirstClassBodyDeclaration) {
-
-		if (isFirstClassBodyDeclaration) {
-			int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
-			if (newLinesBeforeFirstClassBodyDeclaration > 0) {
-				this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
-			}
-		} else {
-			int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
-			if (newLineBeforeChunk > 0) {
-				this.scribe.printEmptyLines(newLineBeforeChunk);
-			}
-			final int newLinesBeforeMember = this.preferences.blank_lines_before_member_type;
-			if (newLinesBeforeMember > 0) {
-				this.scribe.printEmptyLines(newLinesBeforeMember);
-			}
-		}
-		memberTypeDeclaration.traverse(this, scope);
-	}
 	
 	private void format(MultiFieldDeclaration multiFieldDeclaration, ASTVisitor visitor, MethodScope scope, boolean isChunkStart, boolean isFirstClassBodyDeclaration) {
 	
@@ -660,7 +619,7 @@
 		Alignment fieldAlignment = this.scribe.getMemberAlignment();	//$NON-NLS-1$
 	
         this.scribe.printComment();
-		this.scribe.printModifiers();
+		this.scribe.printModifiers(multiFieldDeclaration.annotations, this);
 		this.scribe.space();
 	
 		multiFieldDeclaration.declarations[0].type.traverse(this, scope);
@@ -692,7 +651,7 @@
 					/*
 					 * Check for extra dimensions
 					 */
-					int extraDimensions = getExtraDimension();
+					int extraDimensions = getDimensions();
 					if (extraDimensions != 0) {
 						 for (int index = 0; index < extraDimensions; index++) {
 						 	this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
@@ -858,7 +817,7 @@
 
 		this.lastLocalDeclarationSourceStart = -1;
 		try {
-			expression.traverse(this, null);
+			expression.traverse(this, (BlockScope) null);
 			this.scribe.printComment();
 		} catch(AbortFormatting e){
 			return failedToFormat();
@@ -876,17 +835,49 @@
         this.scribe.printComment();
         final int line = this.scribe.line; 
         
-        this.scribe.printModifiers();
+        this.scribe.printModifiers(typeDeclaration.annotations, this);
 		/*
 		 * Type name
 		 */
-		if (typeDeclaration.isInterface()) {
-			this.scribe.printNextToken(TerminalTokens.TokenNameinterface, true); 
-		} else {
-			this.scribe.printNextToken(TerminalTokens.TokenNameclass, true); 
-		}
+        switch(typeDeclaration.kind()) {
+        	case IGenericType.CLASS_DECL :
+				this.scribe.printNextToken(TerminalTokens.TokenNameclass, true); 
+        		break;
+        	case IGenericType.INTERFACE_DECL :
+				this.scribe.printNextToken(TerminalTokens.TokenNameinterface, true); 
+        		break;
+        	case IGenericType.ENUM_DECL :
+				this.scribe.printNextToken(TerminalTokens.TokenNameenum, true); 
+        		break;
+        	case IGenericType.ANNOTATION_TYPE_DECL :
+				this.scribe.printNextToken(TerminalTokens.TokenNameAT, this.preferences.insert_space_before_at_in_annotation_type_declaration);
+				this.scribe.printNextToken(TerminalTokens.TokenNameinterface, this.preferences.insert_space_after_at_in_annotation_type_declaration); 
+        		break;
+        }
 		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true); 
 
+		TypeParameter[] typeParameters = typeDeclaration.typeParameters;
+		if (typeParameters != null) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_parameters); 
+			if (this.preferences.insert_space_after_opening_angle_bracket_in_type_parameters) {
+				this.scribe.space();
+			}
+			int length = typeParameters.length;
+			for (int i = 0; i < length - 1; i++) {
+				typeParameters[i].traverse(this, typeDeclaration.scope);
+				this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_parameters);
+				if (this.preferences.insert_space_after_comma_in_type_parameters) {
+					this.scribe.space();
+				}				
+			}
+			typeParameters[length - 1].traverse(this, typeDeclaration.scope);
+			if (isClosingGenericToken()) {
+				this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_parameters); 
+			}
+			if (this.preferences.insert_space_after_closing_angle_bracket_in_type_parameters) {
+				this.scribe.space();
+			}
+		}
 		/* 
 		 * Superclass 
 		 */
@@ -919,11 +910,19 @@
 		 */
 		final TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
 		if (superInterfaces != null) {
-			
+			int alignment_for_superinterfaces;
+			switch(typeDeclaration.kind()) {
+				case IGenericType.ENUM_DECL :
+					alignment_for_superinterfaces = this.preferences.alignment_for_superinterfaces_in_enum_declaration;
+					break;
+				default:
+					alignment_for_superinterfaces = this.preferences.alignment_for_superinterfaces_in_type_declaration;
+					break;
+			}
 			int superInterfaceLength = superInterfaces.length;
 			Alignment interfaceAlignment =this.scribe.createAlignment(
 					"superInterfaces",//$NON-NLS-1$
-					this.preferences.alignment_for_superinterfaces_in_type_declaration,
+					alignment_for_superinterfaces,
 					superInterfaceLength+1,  // implements token is first fragment
 					this.scribe.scanner.currentPosition);
 			this.scribe.enterAlignment(interfaceAlignment);
@@ -931,7 +930,7 @@
 			do {
 				try {
 					this.scribe.alignFragment(interfaceAlignment, 0);
-					if (typeDeclaration.isInterface()) {
+					if (typeDeclaration.kind() == IGenericType.INTERFACE_DECL) {
 						this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
 					} else  {
 						this.scribe.printNextToken(TerminalTokens.TokenNameimplements, true);
@@ -962,25 +961,101 @@
 		/*
 		 * Type body
 		 */
-		String class_declaration_brace = this.preferences.brace_position_for_type_declaration;
-
+		String class_declaration_brace;
+		boolean space_before_opening_brace;
+		switch(typeDeclaration.kind()) {
+			case IGenericType.ENUM_DECL :
+				class_declaration_brace = this.preferences.brace_position_for_enum_declaration;
+				space_before_opening_brace = this.preferences.insert_space_before_opening_brace_in_enum_declaration;
+				break;
+			case IGenericType.ANNOTATION_TYPE_DECL :
+				class_declaration_brace = this.preferences.brace_position_for_annotation_type_declaration;
+				space_before_opening_brace =  this.preferences.insert_space_before_opening_brace_in_annotation_type_declaration;
+				break;
+			default:
+				class_declaration_brace = this.preferences.brace_position_for_type_declaration;
+				space_before_opening_brace = this.preferences.insert_space_before_opening_brace_in_type_declaration;
+				break;
+		}
         formatLeftCurlyBrace(line, class_declaration_brace);
-		formatTypeOpeningBrace(class_declaration_brace, this.preferences.insert_space_before_opening_brace_in_type_declaration, typeDeclaration);
+		formatTypeOpeningBrace(class_declaration_brace, space_before_opening_brace, typeDeclaration);
 		
-		if (this.preferences.indent_body_declarations_compare_to_type_header) {
+		boolean indent_body_declarations_compare_to_header;
+		switch(typeDeclaration.kind()) {
+			case IGenericType.ENUM_DECL :
+				indent_body_declarations_compare_to_header = this.preferences.indent_body_declarations_compare_to_enum_declaration_header;
+				break;
+			case IGenericType.ANNOTATION_TYPE_DECL :
+				// TODO (olivier) might want to add an option for annotation type
+				indent_body_declarations_compare_to_header = this.preferences.indent_body_declarations_compare_to_type_header;
+				break;
+			default:
+				indent_body_declarations_compare_to_header = this.preferences.indent_body_declarations_compare_to_type_header;
+				break;
+		}		
+		if (indent_body_declarations_compare_to_header) {
 			this.scribe.indent();
 		}
+		
+		if (typeDeclaration.kind() == IGenericType.ENUM_DECL) {
+			FieldDeclaration[] fieldDeclarations = typeDeclaration.fields;
+			boolean hasConstants = false;
+			if (fieldDeclarations != null) {
+				int length = fieldDeclarations.length;
+				loop: for (int i = 0; i < length; i++) {
+					FieldDeclaration fieldDeclaration = fieldDeclarations[i];
+					if (fieldDeclaration.getKind() != AbstractVariableDeclaration.ENUM_CONSTANT) {
+						break loop;
+					}
+					if (i < length) {
+						hasConstants = true;
+						fieldDeclaration.traverse(this, typeDeclaration.initializerScope);
+					}
+					if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
+						this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_enum_declarations);
+						if (this.preferences.insert_space_after_comma_in_enum_declarations) {
+							this.scribe.space();
+						}
+						this.scribe.printTrailingComment();
+						if (fieldDeclaration.initialization instanceof QualifiedAllocationExpression) {
+							this.scribe.printNewLine();
+						}
+					}
+				}			
+			}
+			if (isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+				this.scribe.printTrailingComment();
+			}
+			if (hasConstants) {
+				this.scribe.printNewLine();	
+			}
+		}
 
 		formatTypeMembers(typeDeclaration);
 
 		this.scribe.printComment();
 		
-		if (this.preferences.indent_body_declarations_compare_to_type_header) {
+		if (indent_body_declarations_compare_to_header) {
 			this.scribe.unIndent();
 		}
 		
-		if (this.preferences.insert_new_line_in_empty_type_declaration) {
-			this.scribe.printNewLine();
+		switch(typeDeclaration.kind()) {
+			case IGenericType.ENUM_DECL :
+				if (this.preferences.insert_new_line_in_empty_enum_declaration) {
+					this.scribe.printNewLine();
+				}
+				break;
+			case IGenericType.ANNOTATION_TYPE_DECL :
+				// TODO (olivier) might want an option for annotation type
+				if (this.preferences.insert_new_line_in_empty_type_declaration) {
+					this.scribe.printNewLine();
+				}
+				break;
+			default :
+				if (this.preferences.insert_new_line_in_empty_type_declaration) {
+					this.scribe.printNewLine();
+				}
 		}
 		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
 		this.scribe.printTrailingComment();
@@ -992,6 +1067,30 @@
 		}
 	}
 
+	private void format(
+		TypeDeclaration memberTypeDeclaration,
+		ClassScope scope,
+		boolean isChunkStart,
+		boolean isFirstClassBodyDeclaration) {
+
+		if (isFirstClassBodyDeclaration) {
+			int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
+			if (newLinesBeforeFirstClassBodyDeclaration > 0) {
+				this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
+			}
+		} else {
+			int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
+			if (newLineBeforeChunk > 0) {
+				this.scribe.printEmptyLines(newLineBeforeChunk);
+			}
+			final int newLinesBeforeMember = this.preferences.blank_lines_before_member_type;
+			if (newLinesBeforeMember > 0) {
+				this.scribe.printEmptyLines(newLinesBeforeMember);
+			}
+		}
+		memberTypeDeclaration.traverse(this, scope);
+	}
+	
 	private void formatAnonymousTypeDeclaration(TypeDeclaration typeDeclaration) {
 		/*
 		 * Type body
@@ -1014,6 +1113,52 @@
 			this.scribe.unIndent();
 		}
 	}
+	
+	/**
+	 * @param block
+	 * @param scope
+	 * @param block_brace_position
+	 */
+	private void formatBlock(Block block, BlockScope scope, String block_brace_position, boolean insertSpaceBeforeOpeningBrace) {
+		formatOpeningBrace(block_brace_position, insertSpaceBeforeOpeningBrace);
+		final Statement[] statements = block.statements;
+		if (statements != null) {
+			this.scribe.printNewLine();
+			if (this.preferences.indent_statements_compare_to_block) {
+				this.scribe.indent();
+			}
+			formatStatements(scope, statements, true);
+			this.scribe.printComment();
+	
+			if (this.preferences.indent_statements_compare_to_block) {
+				this.scribe.unIndent();
+			}
+		} else if (this.preferences.insert_new_line_in_empty_block) {
+			this.scribe.printNewLine();
+			if (this.preferences.indent_statements_compare_to_block) {
+				this.scribe.indent();
+			}
+			this.scribe.printComment();
+	
+			if (this.preferences.indent_statements_compare_to_block) {
+				this.scribe.unIndent();
+			}
+		} else {
+			if (this.preferences.indent_statements_compare_to_block) {
+				this.scribe.indent();
+			}
+			this.scribe.printComment();
+	
+			if (this.preferences.indent_statements_compare_to_block) {
+				this.scribe.unIndent();
+			}
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
+		this.scribe.printTrailingComment();
+		if (DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(block_brace_position)) {
+			this.scribe.unIndent();
+		}
+	}
 
 	private void formatCascadingMessageSends(CascadingMethodInvocationFragmentBuilder builder, BlockScope scope) {
 		int size = builder.size();
@@ -1029,6 +1174,28 @@
 				manageOpeningParenthesizedExpression(currentMessageSend, numberOfParens);
 			}
 			ASTNode[] arguments = currentMessageSend.arguments;
+			TypeReference[] typeArguments = currentMessageSend.typeArguments;
+			if (typeArguments != null) {
+					this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments); 
+					if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
+						this.scribe.space();
+					}
+					int length = typeArguments.length;
+					for (int i = 0; i < length - 1; i++) {
+						typeArguments[i].traverse(this, scope);
+						this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
+						if (this.preferences.insert_space_after_comma_in_type_arguments) {
+							this.scribe.space();
+						}				
+					}
+					typeArguments[length - 1].traverse(this, scope);
+					if (isClosingGenericToken()) {
+						this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments); 
+					}
+					if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
+						this.scribe.space();
+					}
+			}
 			this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier); // selector
 			this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
 			if (arguments != null) {
@@ -1190,7 +1357,7 @@
 						isChunkStart = memberAlignment.checkChunkStart(TYPE, i, this.scribe.scanner.currentPosition);
 						format((TypeDeclaration)member, null, isChunkStart, i == 0);
 					}
-					if (isSemiColon()) {
+					if (isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
 						this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
 						this.scribe.printTrailingComment();
 					}
@@ -1210,18 +1377,10 @@
 		}
 		this.scribe.printComment();
 	}
-	
-	private void formatEmptyStatement() {
-		if (this.preferences.put_empty_statement_on_new_line) {
-			this.scribe.printNewLine();
-		}
-		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
-		this.scribe.printTrailingComment();
-	}
 
 	private void formatEmptyTypeDeclaration(boolean isFirst) {
-		boolean hasSemiColon = isSemiColon();
-		while(isSemiColon()) {
+		boolean hasSemiColon = isNextToken(TerminalTokens.TokenNameSEMICOLON);
+		while(isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
 			this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
 			this.scribe.printTrailingComment();
 		}
@@ -1258,7 +1417,7 @@
 		if (!isMultipleLocalDeclaration(localDeclaration)) {
 			if (localDeclaration.modifiers != NO_MODIFIERS) {
 		        this.scribe.printComment();
-				this.scribe.printModifiers();
+				this.scribe.printModifiers(localDeclaration.annotations, this);
 				this.scribe.space();
 			}
 	
@@ -1281,7 +1440,7 @@
 		/*
 		 * Check for extra dimensions
 		 */
-		int extraDimensions = getExtraDimension();
+		int extraDimensions = getDimensions();
 		if (extraDimensions != 0) {
 			 for (int index = 0; index < extraDimensions; index++) {
 			 	this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
@@ -1319,6 +1478,28 @@
 			this.scribe.alignFragment(messageAlignment, 0);
 			this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
 		}
+		TypeReference[] typeArguments = messageSend.typeArguments;
+		if (typeArguments != null) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments); 
+				if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
+					this.scribe.space();
+				}
+				int length = typeArguments.length;
+				for (int i = 0; i < length - 1; i++) {
+					typeArguments[i].traverse(this, scope);
+					this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
+					if (this.preferences.insert_space_after_comma_in_type_arguments) {
+						this.scribe.space();
+					}				
+				}
+				typeArguments[length - 1].traverse(this, scope);
+				if (isClosingGenericToken()) {
+					this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments); 
+				}
+				if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
+					this.scribe.space();
+				}
+		}
 		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier); // selector
 		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
 
@@ -1424,6 +1605,60 @@
 		}	
 	}
 
+	private void formatEnumConstantArguments(
+			FieldDeclaration enumConstant,
+			boolean spaceBeforeOpenParen, 
+			boolean spaceBetweenEmptyParameters,
+			boolean spaceBeforeClosingParen, 
+			boolean spaceBeforeFirstParameter, 
+			boolean spaceBeforeComma, 
+			boolean spaceAfterComma,
+			int methodDeclarationParametersAlignment) {
+				
+		if (!isNextToken(TerminalTokens.TokenNameLPAREN)) {
+			return;
+		}
+		
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, spaceBeforeOpenParen); 
+		final Expression[] arguments = ((AllocationExpression) enumConstant.initialization).arguments;
+		if (arguments != null) {
+			int argumentLength = arguments.length;
+			Alignment argumentsAlignment = this.scribe.createAlignment(
+					"enumConstantArguments",//$NON-NLS-1$
+					methodDeclarationParametersAlignment,
+					argumentLength,
+					this.scribe.scanner.currentPosition);
+			this.scribe.enterAlignment(argumentsAlignment);
+			boolean ok = false;
+			do {
+				try {
+					if (spaceBeforeFirstParameter) {
+						this.scribe.space();
+					}
+					for (int i = 0; i < argumentLength; i++) {
+						if (i > 0) {
+							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, spaceBeforeComma);
+							this.scribe.printTrailingComment();
+						}
+						this.scribe.alignFragment(argumentsAlignment, i);
+						if (i > 0 && spaceAfterComma) {
+							this.scribe.space();
+						}
+						arguments[i].traverse(this, (BlockScope) null);
+					}
+					ok = true;
+				} catch (AlignmentException e) {
+					this.scribe.redoAlignment(e);
+				}
+			} while (!ok);
+			this.scribe.exitAlignment(argumentsAlignment, true);
+		
+			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, spaceBeforeClosingParen); 
+		} else {
+			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, spaceBetweenEmptyParameters); 
+		}	
+	}
+
 	private void formatNecessaryEmptyStatement() {
 		if (this.preferences.put_empty_statement_on_new_line) {
 			this.scribe.printNewLine();
@@ -1449,7 +1684,6 @@
 
 		this.scribe.printTrailingComment();
 	}
-
 	private void formatStatements(BlockScope scope, final Statement[] statements, boolean insertNewLineAfterLastStatement) {
 		int statementsLength = statements.length;
 		for (int i = 0; i < statementsLength; i++) {
@@ -1563,7 +1797,7 @@
 					ASTNode member = members[i];
 					if (member instanceof FieldDeclaration) {
 						isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_FIELD, i, this.scribe.scanner.currentPosition);
-						if (member instanceof MultiFieldDeclaration){
+						if (member instanceof MultiFieldDeclaration) {
 							MultiFieldDeclaration multiField = (MultiFieldDeclaration) member;
 							
 							if (multiField.isStatic()) {
@@ -1598,11 +1832,11 @@
 					} else if (member instanceof AbstractMethodDeclaration) {
 						isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_METHOD, i, this.scribe.scanner.currentPosition);
 						format((AbstractMethodDeclaration) member, typeDeclaration.scope, isChunkStart, i == 0);
-					} else {
+					} else if (member instanceof TypeDeclaration) {
 						isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_TYPE, i, this.scribe.scanner.currentPosition);
 						format((TypeDeclaration)member, typeDeclaration.scope, isChunkStart, i == 0);
 					}
-					if (isSemiColon()) {
+					if (isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
 						this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
 						this.scribe.printTrailingComment();
 					}
@@ -1622,6 +1856,30 @@
 		this.scribe.exitMemberAlignment(memberAlignment);
 	}
 
+	private void formatTypeOpeningBraceForEnumConstant(String bracePosition, boolean insertSpaceBeforeBrace, TypeDeclaration typeDeclaration) {
+		int fieldCount = (typeDeclaration.fields == null) ? 0 : typeDeclaration.fields.length;
+		int methodCount = (typeDeclaration.methods == null) ? 0 : typeDeclaration.methods.length;
+		int typeCount = (typeDeclaration.memberTypes == null) ? 0 : typeDeclaration.memberTypes.length;
+	
+		if (methodCount == 1 && typeDeclaration.methods[0].isDefaultConstructor()) {
+			methodCount = 0;
+		}
+		final int memberLength = fieldCount + methodCount+typeCount;
+
+		boolean insertNewLine = memberLength > 0;
+		
+		if (!insertNewLine) {
+			if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+				insertNewLine = this.preferences.insert_new_line_in_empty_enum_constant;
+			}
+		}
+	
+		formatOpeningBrace(bracePosition, insertSpaceBeforeBrace);
+		
+		if (insertNewLine) {
+			this.scribe.printNewLine();
+		}
+	}
 	private void formatTypeOpeningBrace(String bracePosition, boolean insertSpaceBeforeBrace, TypeDeclaration typeDeclaration) {
 		int fieldCount = (typeDeclaration.fields == null) ? 0 : typeDeclaration.fields.length;
 		int methodCount = (typeDeclaration.methods == null) ? 0 : typeDeclaration.methods.length;
@@ -1630,12 +1888,14 @@
 		if (methodCount == 1 && typeDeclaration.methods[0].isDefaultConstructor()) {
 			methodCount = 0;
 		}
-		final int memberLength = fieldCount+methodCount+typeCount;
+		final int memberLength = fieldCount + methodCount + typeCount;
 
 		boolean insertNewLine = memberLength > 0;
 		
 		if (!insertNewLine) {
-			if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+			if (typeDeclaration.kind() == IGenericType.ENUM_DECL) {
+				insertNewLine = this.preferences.insert_new_line_in_empty_enum_declaration;
+			} else if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
 				insertNewLine = this.preferences.insert_new_line_in_empty_anonymous_type_declaration;
 			} else {
 				insertNewLine = this.preferences.insert_new_line_in_empty_type_declaration;
@@ -1648,8 +1908,7 @@
 			this.scribe.printNewLine();
 		}
 	}
-
-	private int getExtraDimension() {
+	private int getDimensions() {
 
 		this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
 		int dimensions = 0;
@@ -1676,8 +1935,23 @@
 		return dimensions;
 	}
 
-	private boolean isComma() {
+	private boolean hasComments() {
 
+		this.localScanner.resetTo(this.scribe.scanner.startPosition, this.scribe.scannerEndPosition - 1);
+		try {
+			switch(this.localScanner.getNextToken()) {
+				case TerminalTokens.TokenNameCOMMENT_BLOCK :
+				case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+				case TerminalTokens.TokenNameCOMMENT_LINE :
+					return true;
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return false;
+	}
+
+	private boolean isNextToken(int tokenName) {
 		this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
 		try {
 			int token = this.localScanner.getNextToken();
@@ -1692,7 +1966,34 @@
 						break loop;
 				}
 			}
-			return  token == TerminalTokens.TokenNameCOMMA;
+			return  token == tokenName;
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return false;
+	}
+
+	private boolean isClosingGenericToken() {
+		this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
+		try {
+			int token = this.localScanner.getNextToken();
+			loop: while(true) {
+				switch(token) {
+					case TerminalTokens.TokenNameCOMMENT_BLOCK :
+					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+					case TerminalTokens.TokenNameCOMMENT_LINE :
+						token = this.localScanner.getNextToken();
+						continue loop;
+					default:
+						break loop;
+				}
+			}
+			switch(token) {
+				case TerminalTokens.TokenNameGREATER :
+				case TerminalTokens.TokenNameRIGHT_SHIFT :
+				case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT :
+					return true;
+			}
 		} catch(InvalidInputException e) {
 			// ignore
 		}
@@ -1706,29 +2007,6 @@
 				&& (block.statements[0] instanceof ReturnStatement || block.statements[0] instanceof ThrowStatement);
 	}
 
-	private boolean isMinus() {
-
-		this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
-		try {
-			int token = this.localScanner.getNextToken();
-			loop: while(true) {
-				switch(token) {
-					case TerminalTokens.TokenNameCOMMENT_BLOCK :
-					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
-					case TerminalTokens.TokenNameCOMMENT_LINE :
-						token = this.localScanner.getNextToken();
-						continue loop;
-					default:
-						break loop;
-				}
-			}
-			return  token == TerminalTokens.TokenNameMINUS;
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-		return false;
-	}
-
 	private boolean isMultipleLocalDeclaration(LocalDeclaration localDeclaration) {
 
 		if (localDeclaration.declarationSourceStart == this.lastLocalDeclarationSourceStart) return true;
@@ -1758,45 +2036,6 @@
 		return false;
 	}
 
-	private boolean isSemiColon() {
-
-		this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
-		try {
-			int token = this.localScanner.getNextToken();
-			loop: while(true) {
-				switch(token) {
-					case TerminalTokens.TokenNameCOMMENT_BLOCK :
-					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
-					case TerminalTokens.TokenNameCOMMENT_LINE :
-						token = this.localScanner.getNextToken();
-						continue loop;
-					default:
-						break loop;
-				}
-			}
-			return  token == TerminalTokens.TokenNameSEMICOLON;
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-		return false;
-	}
-
-	private boolean hasComments() {
-
-		this.localScanner.resetTo(this.scribe.scanner.startPosition, this.scribe.scannerEndPosition - 1);
-		try {
-			switch(this.localScanner.getNextToken()) {
-				case TerminalTokens.TokenNameCOMMENT_BLOCK :
-				case TerminalTokens.TokenNameCOMMENT_JAVADOC :
-				case TerminalTokens.TokenNameCOMMENT_LINE :
-					return true;
-			}
-		} catch(InvalidInputException e) {
-			// ignore
-		}
-		return false;
-	}
-
 	private void manageClosingParenthesizedExpression(Expression expression, int numberOfParens) {
 		for (int i = 0; i < numberOfParens; i++) {
 			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_parenthesized_expression);
@@ -1825,6 +2064,29 @@
 			manageOpeningParenthesizedExpression(allocationExpression, numberOfParens);
 		}
 		this.scribe.printNextToken(TerminalTokens.TokenNamenew);
+		TypeReference[] typeArguments = allocationExpression.typeArguments;
+		if (typeArguments != null) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments); 
+				if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
+					this.scribe.space();
+				}
+				int length = typeArguments.length;
+				for (int i = 0; i < length - 1; i++) {
+					typeArguments[i].traverse(this, scope);
+					this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
+					if (this.preferences.insert_space_after_comma_in_type_arguments) {
+						this.scribe.space();
+					}				
+				}
+				typeArguments[length - 1].traverse(this, scope);
+				if (isClosingGenericToken()) {
+					this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments); 
+				}
+				if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
+					this.scribe.space();
+				}
+		}
+
 		this.scribe.space();
 		allocationExpression.type.traverse(this, scope);
 		
@@ -1882,6 +2144,52 @@
 			
 		return dumpBinaryExpression(and_and_Expression, TerminalTokens.TokenNameAND_AND, scope);
 	}
+	public boolean visit(
+			AnnotationMethodDeclaration annotationTypeMemberDeclaration,
+			ClassScope scope) {        
+        /*
+         * Print comments to get proper line number
+         */
+        this.scribe.printComment();        
+        this.scribe.printModifiers(annotationTypeMemberDeclaration.annotations, this);
+		this.scribe.space();
+		/*
+		 * Print the method return type
+		 */	
+		final TypeReference returnType = annotationTypeMemberDeclaration.returnType;
+		final MethodScope annotationTypeMemberDeclarationScope = annotationTypeMemberDeclaration.scope;
+		
+		if (returnType != null) {
+			returnType.traverse(this, annotationTypeMemberDeclarationScope);
+		}
+		/*
+		 * Print the method name
+		 */
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true); 
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation_type_member_declaration); 
+		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_annotation_type_member_declaration); 
+
+		/*
+		 * Check for extra dimensions
+		 */
+		int extraDimensions = annotationTypeMemberDeclaration.extendedDimensions;
+		if (extraDimensions != 0) {
+			 for (int i = 0; i < extraDimensions; i++) {
+			 	this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
+			 	this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
+			 }
+		}
+
+		Expression defaultValue = annotationTypeMemberDeclaration.defaultValue;
+		if (defaultValue != null) {
+			this.scribe.printNextToken(TerminalTokens.TokenNamedefault, true);
+			this.scribe.space();
+			defaultValue.traverse(this, (BlockScope) null);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+		this.scribe.printTrailingComment();
+		return false;
+	}
 
 	/**
 	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.Argument, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
@@ -1890,7 +2198,7 @@
 
 		if (argument.modifiers != NO_MODIFIERS) {
 	        this.scribe.printComment();
-			this.scribe.printModifiers();
+			this.scribe.printModifiers(argument.annotations, this);
 			this.scribe.space();
 		}
 
@@ -1901,16 +2209,24 @@
 			argument.type.traverse(this, scope);
 		}
 		
-		/*
-		 * Print the argument name
-		 */	
-		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
+		if (argument.isVarArgs()) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameELLIPSIS, this.preferences.insert_space_before_ellipsis);
+			if (this.preferences.insert_space_after_ellipsis) {
+				this.scribe.space();
+			}
+			this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false);
+		} else {
+			/*
+			 * Print the argument name
+			 */	
+			this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
+		}
 
 
 		/*
 		 * Check for extra dimensions
 		 */
-		int extraDimensions = getExtraDimension();
+		int extraDimensions = getDimensions();
 		if (extraDimensions != 0) {
 			 for (int i = 0; i < extraDimensions; i++) {
 			 	this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
@@ -2014,7 +2330,7 @@
 							}
 							expressions[i].traverse(this, scope);
 							if (i == expressionsLength - 1) {
-								if (isComma()) {
+								if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
 									this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
 									this.scribe.printTrailingComment();
 								}
@@ -2036,7 +2352,7 @@
 					this.scribe.space();
 				}
 				expressions[0].traverse(this, scope);
-				if (isComma()) {
+				if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
 					this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
 					this.scribe.printTrailingComment();
 				}
@@ -2088,7 +2404,7 @@
 				manageOpeningParenthesizedExpression(arrayQualifiedTypeReference, numberOfParens);
 			}
 			this.scribe.printQualifiedReference(arrayQualifiedTypeReference.sourceEnd);
-			int dimensions = getExtraDimension();
+			int dimensions = getDimensions();
 			if (dimensions != 0) {
 				for (int i = 0; i < dimensions; i++) {
 					this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
@@ -2113,7 +2429,7 @@
 				manageOpeningParenthesizedExpression(arrayQualifiedTypeReference, numberOfParens);
 			}
 			this.scribe.printQualifiedReference(arrayQualifiedTypeReference.sourceEnd);
-			int dimensions = getExtraDimension();
+			int dimensions = getDimensions();
 			if (dimensions != 0) {
 				for (int i = 0; i < dimensions; i++) {
 					this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
@@ -2163,7 +2479,7 @@
 		}
 		this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS);
 		
-		int dimensions = getExtraDimension();
+		int dimensions = getDimensions();
 		if (dimensions != 0) {
 			if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
 				this.scribe.space();
@@ -2194,7 +2510,7 @@
 			manageOpeningParenthesizedExpression(arrayTypeReference, numberOfParens);
 		}
 		this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS);
-		int dimensions = getExtraDimension();
+		int dimensions = getDimensions();
 		if (dimensions != 0) {
 			if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
 				this.scribe.space();
@@ -2430,6 +2746,8 @@
 				this.scribe.printEmptyLines(blankLinesBeforePackage);
 			}
 
+			this.scribe.printModifiers(compilationUnitDeclaration.currentPackage.annotations, this);
+			this.scribe.space();
 			// dump the package keyword
 			this.scribe.printNextToken(TerminalTokens.TokenNamepackage);
 			this.scribe.space();
@@ -2485,10 +2803,9 @@
 					this.scribe.printNewLine();
 				}
 			}
-			format(types[typesLength - 1]);
+			types[typesLength - 1].traverse(this, scope);
 		}
-		this.scribe.printComment();
-		formatEmptyTypeDeclaration(false);
+		this.scribe.printEndOfCompilationUnit();
 		return false;
 	}
 
@@ -2627,8 +2944,32 @@
          */
         this.scribe.printComment();
         final int line = this.scribe.line;
-		this.scribe.printModifiers();
+		this.scribe.printModifiers(constructorDeclaration.annotations, this);
 		this.scribe.space();
+
+		TypeParameter[] typeParameters = constructorDeclaration.typeParameters;
+		if (typeParameters != null) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_parameters); 
+			if (this.preferences.insert_space_after_opening_angle_bracket_in_type_parameters) {
+				this.scribe.space();
+			}
+			int length = typeParameters.length;
+			for (int i = 0; i < length - 1; i++) {
+				typeParameters[i].traverse(this, constructorDeclaration.scope);
+				this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_parameters);
+				if (this.preferences.insert_space_after_comma_in_type_parameters) {
+					this.scribe.space();
+				}				
+			}
+			typeParameters[length - 1].traverse(this, constructorDeclaration.scope);
+			if (isClosingGenericToken()) {
+				this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_parameters); 
+			}
+			if (this.preferences.insert_space_after_closing_angle_bracket_in_type_parameters) {
+				this.scribe.space();
+			}
+		}
+
 		/*
 		 * Print the method name
 		 */	
@@ -2799,11 +3140,76 @@
 	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.EmptyStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
 	 */
 	public boolean visit(EmptyStatement statement, BlockScope scope) {
-
-		formatEmptyStatement();
+		if (this.preferences.put_empty_statement_on_new_line) {
+			this.scribe.printNewLine();
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+		this.scribe.printTrailingComment();
 		return false;	
 	}
-
+	// field is an enum constant
+	public boolean visit(FieldDeclaration enumConstant, MethodScope scope) {
+        /*
+         * Print comments to get proper line number
+         */
+        this.scribe.printComment();
+        final int line = this.scribe.line; 
+        
+        this.scribe.printModifiers(enumConstant.annotations, this);
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true); 
+		formatEnumConstantArguments(
+			enumConstant,
+			this.preferences.insert_space_before_opening_paren_in_enum_constant,
+			this.preferences.insert_space_between_empty_parens_in_enum_constant,
+			this.preferences.insert_space_before_closing_paren_in_enum_constant,
+			this.preferences.insert_space_after_opening_paren_in_enum_constant,
+			this.preferences.insert_space_before_comma_in_enum_constant_arguments,
+			this.preferences.insert_space_after_comma_in_enum_constant_arguments,
+			this.preferences.alignment_for_arguments_in_enum_constant);			
+		
+		Expression initialization = enumConstant.initialization;
+		if (initialization instanceof QualifiedAllocationExpression) {
+			TypeDeclaration typeDeclaration = ((QualifiedAllocationExpression) initialization).anonymousType;
+			int fieldsCount = typeDeclaration.fields == null ? 0 : typeDeclaration.fields.length;
+			int methodsCount = typeDeclaration.methods == null ? 0 : typeDeclaration.methods.length;
+			int membersCount = typeDeclaration.memberTypes == null ? 0 : typeDeclaration.memberTypes.length;
+			
+			/*
+			 * Type body
+			 */
+			String enum_constant_brace = this.preferences.brace_position_for_enum_constant;
+	
+	        formatLeftCurlyBrace(line, enum_constant_brace);
+			formatTypeOpeningBraceForEnumConstant(enum_constant_brace, this.preferences.insert_space_before_opening_brace_in_enum_constant, typeDeclaration);
+			
+			if (this.preferences.indent_body_declarations_compare_to_enum_constant_header) {
+				this.scribe.indent();
+			}
+	
+			if (fieldsCount != 0 || methodsCount != 0 || membersCount != 0) {
+				formatTypeMembers(typeDeclaration);
+			}
+	
+			this.scribe.printComment();
+			
+			if (this.preferences.indent_body_declarations_compare_to_enum_constant_header) {
+				this.scribe.unIndent();
+			}
+			
+			if (this.preferences.insert_new_line_in_empty_enum_constant) {
+				this.scribe.printNewLine();
+			}
+			this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
+			this.scribe.printTrailingComment();
+			if (enum_constant_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
+				this.scribe.unIndent();
+			}
+			if (hasComments()) {
+				this.scribe.printNewLine();
+			}
+		}
+		return false;
+	}
 	/**
 	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.EqualExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
 	 */
@@ -2832,6 +3238,29 @@
 			this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
 		}
 
+		TypeReference[] typeArguments = explicitConstructor.typeArguments;
+		if (typeArguments != null) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments); 
+				if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
+					this.scribe.space();
+				}
+				int length = typeArguments.length;
+				for (int i = 0; i < length - 1; i++) {
+					typeArguments[i].traverse(this, scope);
+					this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
+					if (this.preferences.insert_space_after_comma_in_type_arguments) {
+						this.scribe.space();
+					}				
+				}
+				typeArguments[length - 1].traverse(this, scope);
+				if (isClosingGenericToken()) {
+					this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments); 
+				}
+				if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
+					this.scribe.space();
+				}
+		}
+		
 		if (explicitConstructor.isSuperAccess()) {
 			this.scribe.printNextToken(TerminalTokens.TokenNamesuper);
 		} else {
@@ -2879,7 +3308,6 @@
 		this.scribe.printTrailingComment();
 		return false;
 	}
-
 	/**
 	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.FalseLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
 	 */
@@ -2896,7 +3324,6 @@
 		}
 		return false;
 	}
-
 	/**
 	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.FieldReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
 	 */
@@ -2936,6 +3363,52 @@
 		}
 		return false;
 	}
+	public boolean visit(ForeachStatement forStatement, BlockScope scope) {
+		this.scribe.printNextToken(TerminalTokens.TokenNamefor);
+	    final int line = this.scribe.line;
+	    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_for);
+		
+		if (this.preferences.insert_space_after_opening_paren_in_for) {
+			this.scribe.space();
+		}
+		formatLocalDeclaration(forStatement.elementVariable, scope, false, false);
+
+		this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_for);
+		if (this.preferences.insert_space_after_colon_in_for) {
+			this.scribe.space();
+		}
+		forStatement.collection.traverse(this, scope);
+
+		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_for);
+		
+		final Statement action = forStatement.action;
+		if (action != null) {
+			if (action instanceof Block) {
+	            formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
+				action.traverse(this, scope);
+			} else if (action instanceof EmptyStatement) {
+				/*
+				 * This is an empty statement
+				 */
+				formatNecessaryEmptyStatement();
+			} else {
+				this.scribe.indent();
+				this.scribe.printNewLine();
+				action.traverse(this, scope);
+				this.scribe.unIndent();
+			}
+			if (action instanceof Expression) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+				this.scribe.printTrailingComment();
+			}
+		} else {
+			/*
+			 * This is an empty statement
+			 */
+			formatNecessaryEmptyStatement(); 
+		}
+		return false;
+	}
 
 	/**
 	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ForStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
@@ -3061,11 +3534,13 @@
 				}
 			} else if (elseStatement == null && this.preferences.keep_simple_if_on_one_line) {
 				Alignment compactIfAlignment = this.scribe.createAlignment(
-					"compactIf", //$NON-NLS-1$
-					this.preferences.alignment_for_compact_if,
-					Alignment.R_OUTERMOST,
-					1, 
-					this.scribe.scanner.currentPosition);
+						"compactIf", //$NON-NLS-1$
+						this.preferences.alignment_for_compact_if,
+						Alignment.R_OUTERMOST,
+						1,
+						this.scribe.scanner.currentPosition,
+						1,
+						false);
 				this.scribe.enterAlignment(compactIfAlignment);
 				boolean ok = false;
 				do {
@@ -3157,6 +3632,10 @@
 		
 		this.scribe.printNextToken(TerminalTokens.TokenNameimport);
 		this.scribe.space();
+		if (importRef.isStatic()) {
+			this.scribe.printNextToken(TerminalTokens.TokenNamestatic);
+			this.scribe.space();
+		}
 		if (importRef.onDemand) {
 			this.scribe.printQualifiedReference(importRef.sourceEnd);
 			this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
@@ -3269,12 +3748,47 @@
 		}
 		return false;
 	}
-
-	/**
-	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
-	 */
-	public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
-		format(memberTypeDeclaration);	
+	public boolean visit(MarkerAnnotation annotation, BlockScope scope) {
+		this.scribe.printNextToken(TerminalTokens.TokenNameAT);
+		if (this.preferences.insert_space_after_at_in_annotation) {
+			this.scribe.space();
+		}
+		this.scribe.printQualifiedReference(annotation.sourceEnd);
+		return false;
+	}
+	public boolean visit(MarkerAnnotation annotation, CompilationUnitScope scope) {
+		this.scribe.printNextToken(TerminalTokens.TokenNameAT);
+		if (this.preferences.insert_space_after_at_in_annotation) {
+			this.scribe.space();
+		}
+		this.scribe.printQualifiedReference(annotation.sourceEnd);
+		return false;
+	}
+	public boolean visit(MemberValuePair pair, BlockScope scope) {
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
+		this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
+		if (this.preferences.insert_space_after_assignment_operator) {
+			this.scribe.space();
+		}
+		pair.value.traverse(this, scope);	
+		return false;
+	}
+	public boolean visit(MemberValuePair pair, ClassScope scope) {
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
+		this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
+		if (this.preferences.insert_space_after_assignment_operator) {
+			this.scribe.space();
+		}
+		pair.value.traverse(this, scope);	
+		return false;
+	}
+	public boolean visit(MemberValuePair pair, CompilationUnitScope scope) {
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
+		this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
+		if (this.preferences.insert_space_after_assignment_operator) {
+			this.scribe.space();
+		}
+		pair.value.traverse(this, scope);	
 		return false;
 	}
 
@@ -3341,9 +3855,32 @@
         this.scribe.printComment();
         final int line = this.scribe.line;
         
-        this.scribe.printModifiers();
+        this.scribe.printModifiers(methodDeclaration.annotations, this);
 		this.scribe.space();
 		
+		TypeParameter[] typeParameters = methodDeclaration.typeParameters;
+		if (typeParameters != null) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_parameters); 
+			if (this.preferences.insert_space_after_opening_angle_bracket_in_type_parameters) {
+				this.scribe.space();
+			}
+			int length = typeParameters.length;
+			for (int i = 0; i < length - 1; i++) {
+				typeParameters[i].traverse(this, methodDeclaration.scope);
+				this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_parameters);
+				if (this.preferences.insert_space_after_comma_in_type_parameters) {
+					this.scribe.space();
+				}				
+			}
+			typeParameters[length - 1].traverse(this, methodDeclaration.scope);
+			if (isClosingGenericToken()) {
+				this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_parameters); 
+			}
+			if (this.preferences.insert_space_after_closing_angle_bracket_in_type_parameters) {
+				this.scribe.space();
+			}
+		}
+		
 		/*
 		 * Print the method return type
 		 */	
@@ -3371,7 +3908,7 @@
 		/*
 		 * Check for extra dimensions
 		 */
-		int extraDimensions = getExtraDimension();
+		int extraDimensions = getDimensions();
 		if (extraDimensions != 0) {
 			 for (int i = 0; i < extraDimensions; i++) {
 			 	this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
@@ -3429,50 +3966,54 @@
 		}
 		return false;
 	}
-
-	/**
-	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.NullLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
-	 */
-	public boolean visit(StringLiteralConcatenation stringLiteral, BlockScope scope) {
-		final int numberOfParens = (stringLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
-		if (numberOfParens > 0) {
-			manageOpeningParenthesizedExpression(stringLiteral, numberOfParens);
+	public boolean visit(NormalAnnotation annotation, BlockScope scope) {
+		this.scribe.printNextToken(TerminalTokens.TokenNameAT);
+		if (this.preferences.insert_space_after_at_in_annotation) {
+			this.scribe.space();
 		}
-
-		this.scribe.printComment();
-		ASTNode[] fragments = stringLiteral.literals;
-		int fragmentsSize = stringLiteral.counter;
-		Alignment binaryExpressionAlignment = this.scribe.createAlignment("binaryExpressionAlignment", this.preferences.alignment_for_binary_expression, Alignment.R_OUTERMOST, fragmentsSize, this.scribe.scanner.currentPosition); //$NON-NLS-1$
-		this.scribe.enterAlignment(binaryExpressionAlignment);
-		boolean ok = false;
-		do {
-			try {
-				for (int i = 0; i < fragmentsSize - 1; i++) {
-					ASTNode fragment = fragments[i];
-					fragment.traverse(this, scope);
-					this.scribe.printTrailingComment();
-					if (this.scribe.lastNumberOfNewLines == 1) {
-						// a new line has been inserted by printTrailingComment()
-						this.scribe.indentationLevel = binaryExpressionAlignment.breakIndentationLevel;
-					}
-					this.scribe.alignFragment(binaryExpressionAlignment, i);
-					this.scribe.printNextToken(TerminalTokens.TokenNamePLUS, this.preferences.insert_space_before_binary_operator);
-					if (this.preferences.insert_space_after_binary_operator) {
-						this.scribe.space();
-					}
+		this.scribe.printQualifiedReference(annotation.sourceEnd);
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation);
+		if (this.preferences.insert_space_after_opening_paren_in_annotation) {
+			this.scribe.space();
+		}
+		MemberValuePair[] memberValuePairs = annotation.memberValuePairs;
+		if (memberValuePairs != null) {
+			int length = memberValuePairs.length;
+			for (int i = 0; i < length - 1; i++) {
+				memberValuePairs[i].traverse(this, scope);
+				this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_annotation);
+				if (this.preferences.insert_space_after_comma_in_annotation) {
+					this.scribe.space();
 				}
-				fragments[fragmentsSize - 1].traverse(this, scope);
-				this.scribe.printTrailingComment();
-				ok = true;
-			} catch(AlignmentException e){
-				this.scribe.redoAlignment(e);
 			}
-		} while (!ok);		
-		this.scribe.exitAlignment(binaryExpressionAlignment, true);
-	
-		if (numberOfParens > 0) {
-			manageClosingParenthesizedExpression(stringLiteral, numberOfParens);
+			memberValuePairs[length - 1].traverse(this, scope);
 		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_annotation);
+		return false;
+	}
+	public boolean visit(NormalAnnotation annotation, CompilationUnitScope scope) {
+		this.scribe.printNextToken(TerminalTokens.TokenNameAT);
+		if (this.preferences.insert_space_after_at_in_annotation) {
+			this.scribe.space();
+		}
+		this.scribe.printQualifiedReference(annotation.sourceEnd);
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation);
+		if (this.preferences.insert_space_after_opening_paren_in_annotation) {
+			this.scribe.space();
+		}
+		MemberValuePair[] memberValuePairs = annotation.memberValuePairs;
+		if (memberValuePairs != null) {
+			int length = memberValuePairs.length;
+			for (int i = 0; i < length - 1; i++) {
+				memberValuePairs[i].traverse(this, scope);
+				this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_annotation);
+				if (this.preferences.insert_space_after_comma_in_annotation) {
+					this.scribe.space();
+				}
+			}
+			memberValuePairs[length - 1].traverse(this, scope);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_annotation);
 		return false;
 	}
 
@@ -3498,9 +4039,198 @@
 	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
 	 */
 	public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) {
-
 		return dumpBinaryExpression(or_or_Expression, TerminalTokens.TokenNameOR_OR, scope);
 	}
+	public boolean visit(
+			ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference,
+			BlockScope scope) {
+		final int numberOfParens = (parameterizedQualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(parameterizedQualifiedTypeReference, numberOfParens);
+		}
+		TypeReference[][] typeArguments = parameterizedQualifiedTypeReference.typeArguments;
+		int length = typeArguments.length;
+		for (int i = 0; i < length; i++) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
+			TypeReference[] typeArgument = typeArguments[i];			
+			if (typeArgument != null) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_parameterized_type_reference);
+				if (this.preferences.insert_space_after_opening_angle_bracket_in_parameterized_type_reference) {
+					this.scribe.space();
+				}
+				int typeArgumentLength = typeArgument.length;
+				for (int j = 0; j < typeArgumentLength - 1; j++) {
+					typeArgument[j].traverse(this, scope);
+					this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_parameterized_type_reference);
+					if (this.preferences.insert_space_after_comma_in_parameterized_type_reference) {
+						this.scribe.space();
+					}			
+				}
+				typeArgument[typeArgumentLength - 1].traverse(this, scope);
+				if (isClosingGenericToken()) {
+					this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_parameterized_type_reference);
+				}
+			}
+			if (i < length - 1) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
+			}
+		}
+		int dimensions = parameterizedQualifiedTypeReference.dimensions();
+		if (dimensions != 0) {
+			if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
+				this.scribe.space();
+			}
+			for (int i = 0; i < dimensions; i++) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
+				if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
+					this.scribe.space();
+				}
+				this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
+			}
+		}		
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(parameterizedQualifiedTypeReference, numberOfParens);
+		}
+		return false;
+	}
+	public boolean visit(
+			ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference,
+			ClassScope scope) {
+		final int numberOfParens = (parameterizedQualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(parameterizedQualifiedTypeReference, numberOfParens);
+		}
+		TypeReference[][] typeArguments = parameterizedQualifiedTypeReference.typeArguments;
+		int length = typeArguments.length;
+		for (int i = 0; i < length - 1; i++) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
+			TypeReference[] typeArgument = typeArguments[i];			
+			if (typeArgument != null) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_parameterized_type_reference);
+				if (this.preferences.insert_space_after_opening_angle_bracket_in_parameterized_type_reference) {
+					this.scribe.space();
+				}
+				int typeArgumentLength = typeArgument.length;
+				for (int j = 0; j < typeArgumentLength - 1; j++) {
+					typeArgument[j].traverse(this, scope);
+					this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_parameterized_type_reference);
+					if (this.preferences.insert_space_after_comma_in_parameterized_type_reference) {
+						this.scribe.space();
+					}			
+				}
+				typeArgument[typeArgumentLength - 1].traverse(this, scope);
+				if (isClosingGenericToken()) {
+					this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_parameterized_type_reference);
+				}
+			}			
+			this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
+		}
+		int dimensions = parameterizedQualifiedTypeReference.dimensions();
+		if (dimensions != 0) {
+			if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
+				this.scribe.space();
+			}
+			for (int i = 0; i < dimensions; i++) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
+				if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
+					this.scribe.space();
+				}
+				this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
+			}
+		}		
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(parameterizedQualifiedTypeReference, numberOfParens);
+		}
+		return false;
+	}
+	public boolean visit(
+			ParameterizedSingleTypeReference parameterizedSingleTypeReference,
+			BlockScope scope) {
+		final int numberOfParens = (parameterizedSingleTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(parameterizedSingleTypeReference, numberOfParens);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
+
+		this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_parameterized_type_reference);
+		if (this.preferences.insert_space_after_opening_angle_bracket_in_parameterized_type_reference) {
+			this.scribe.space();
+		}
+		TypeReference[] typeArguments = parameterizedSingleTypeReference.typeArguments;
+		int typeArgumentsLength = typeArguments.length;
+		for (int i = 0; i < typeArgumentsLength - 1; i++) {
+			typeArguments[i].traverse(this, scope);
+			this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_parameterized_type_reference);
+			if (this.preferences.insert_space_after_comma_in_parameterized_type_reference) {
+				this.scribe.space();
+			}			
+		}
+		typeArguments[typeArgumentsLength - 1].traverse(this, scope);
+		if (isClosingGenericToken()) {
+			this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_parameterized_type_reference);
+		}
+		int dimensions = parameterizedSingleTypeReference.dimensions;
+		if (dimensions != 0) {
+			if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
+				this.scribe.space();
+			}
+			for (int i = 0; i < dimensions; i++) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
+				if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
+					this.scribe.space();
+				}
+				this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
+			}
+		}		
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(parameterizedSingleTypeReference, numberOfParens);
+		}
+		return false;
+	}
+	public boolean visit(
+			ParameterizedSingleTypeReference parameterizedSingleTypeReference,
+			ClassScope scope) {
+		final int numberOfParens = (parameterizedSingleTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(parameterizedSingleTypeReference, numberOfParens);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
+
+		this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_parameterized_type_reference);
+		if (this.preferences.insert_space_after_opening_angle_bracket_in_parameterized_type_reference) {
+			this.scribe.space();
+		}
+		TypeReference[] typeArguments = parameterizedSingleTypeReference.typeArguments;
+		int typeArgumentsLength = typeArguments.length;
+		for (int i = 0; i < typeArgumentsLength - 1; i++) {
+			typeArguments[i].traverse(this, scope);
+			this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_parameterized_type_reference);
+			if (this.preferences.insert_space_after_comma_in_parameterized_type_reference) {
+				this.scribe.space();
+			}			
+		}
+		typeArguments[typeArgumentsLength - 1].traverse(this, scope);
+		if (isClosingGenericToken()) {
+			this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_parameterized_type_reference);
+		}
+		int dimensions = parameterizedSingleTypeReference.dimensions;
+		if (dimensions != 0) {
+			if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
+				this.scribe.space();
+			}
+			for (int i = 0; i < dimensions; i++) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
+				if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
+					this.scribe.space();
+				}
+				this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
+			}
+		}		
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(parameterizedSingleTypeReference, numberOfParens);
+		}
+		return false;
+	}
 	
 	/**
 	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.PostfixExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
@@ -3567,8 +4297,30 @@
 		
 		this.scribe.printNextToken(TerminalTokens.TokenNamenew);
 		// used for the new line on wrap style of formatting
+		TypeReference[] typeArguments = qualifiedAllocationExpression.typeArguments;
+		if (typeArguments != null) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments); 
+				if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
+					this.scribe.space();
+				}
+				int length = typeArguments.length;
+				for (int i = 0; i < length - 1; i++) {
+					typeArguments[i].traverse(this, scope);
+					this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
+					if (this.preferences.insert_space_after_comma_in_type_arguments) {
+						this.scribe.space();
+					}				
+				}
+				typeArguments[length - 1].traverse(this, scope);
+				if (isClosingGenericToken()) {
+					this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments); 
+				}
+				if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
+					this.scribe.space();
+				}
+		}
+
 		final int line = this.scribe.line;
-		
 		this.scribe.space();
 		qualifiedAllocationExpression.type.traverse(this, scope);
 		
@@ -3738,6 +4490,35 @@
 		this.scribe.printTrailingComment();
 		return false;
 	}
+	public boolean visit(SingleMemberAnnotation annotation, BlockScope scope) {
+		this.scribe.printNextToken(TerminalTokens.TokenNameAT);
+		if (this.preferences.insert_space_after_at_in_annotation) {
+			this.scribe.space();
+		}
+		this.scribe.printQualifiedReference(annotation.sourceEnd);
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation);
+		if (this.preferences.insert_space_after_opening_paren_in_annotation) {
+			this.scribe.space();
+		}
+		annotation.memberValue.traverse(this, scope);
+		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_annotation);
+		return false;
+	}
+	public boolean visit(SingleMemberAnnotation annotation,
+			CompilationUnitScope scope) {
+		this.scribe.printNextToken(TerminalTokens.TokenNameAT);
+		if (this.preferences.insert_space_after_at_in_annotation) {
+			this.scribe.space();
+		}
+		this.scribe.printQualifiedReference(annotation.sourceEnd);
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation);
+		if (this.preferences.insert_space_after_opening_paren_in_annotation) {
+			this.scribe.space();
+		}
+		annotation.memberValue.traverse(this, scope);
+		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_annotation);
+		return false;
+	}
 
 	/**
 	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.SingleNameReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
@@ -3812,6 +4593,52 @@
 	}
 
 	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.NullLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(StringLiteralConcatenation stringLiteral, BlockScope scope) {
+		final int numberOfParens = (stringLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(stringLiteral, numberOfParens);
+		}
+
+		this.scribe.printComment();
+		ASTNode[] fragments = stringLiteral.literals;
+		int fragmentsSize = stringLiteral.counter;
+		Alignment binaryExpressionAlignment = this.scribe.createAlignment("binaryExpressionAlignment", this.preferences.alignment_for_binary_expression, Alignment.R_OUTERMOST, fragmentsSize, this.scribe.scanner.currentPosition); //$NON-NLS-1$
+		this.scribe.enterAlignment(binaryExpressionAlignment);
+		boolean ok = false;
+		do {
+			try {
+				for (int i = 0; i < fragmentsSize - 1; i++) {
+					ASTNode fragment = fragments[i];
+					fragment.traverse(this, scope);
+					this.scribe.printTrailingComment();
+					if (this.scribe.lastNumberOfNewLines == 1) {
+						// a new line has been inserted by printTrailingComment()
+						this.scribe.indentationLevel = binaryExpressionAlignment.breakIndentationLevel;
+					}
+					this.scribe.alignFragment(binaryExpressionAlignment, i);
+					this.scribe.printNextToken(TerminalTokens.TokenNamePLUS, this.preferences.insert_space_before_binary_operator);
+					if (this.preferences.insert_space_after_binary_operator) {
+						this.scribe.space();
+					}
+				}
+				fragments[fragmentsSize - 1].traverse(this, scope);
+				this.scribe.printTrailingComment();
+				ok = true;
+			} catch(AlignmentException e){
+				this.scribe.redoAlignment(e);
+			}
+		} while (!ok);		
+		this.scribe.exitAlignment(binaryExpressionAlignment, true);
+	
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(stringLiteral, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
 	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.SuperReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
 	 */
 	public boolean visit(SuperReference superReference, BlockScope scope) {
@@ -4104,6 +4931,14 @@
 			format(localTypeDeclaration);
 			return false;
 	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
+	 */
+	public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
+		format(memberTypeDeclaration);	
+		return false;
+	}
 	
 	/**
 	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration, org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope)
@@ -4115,6 +4950,58 @@
 		format(typeDeclaration);
 		return false;
 	}
+	public boolean visit(TypeParameter typeParameter, BlockScope scope) {
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
+		if (typeParameter.type != null) {
+			this.scribe.space();
+			this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
+			this.scribe.space();
+			typeParameter.type.traverse(this, scope);
+		}
+		final TypeReference[] bounds = typeParameter.bounds;
+		if (bounds != null) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameAND, this.preferences.insert_space_before_and_in_type_parameter);
+			if (this.preferences.insert_space_after_and_in_type_parameter) {
+				this.scribe.space();
+			}
+			int boundsLength = bounds.length;
+			for (int i = 0; i < boundsLength - 1; i++) {
+				bounds[i].traverse(this, scope);
+				this.scribe.printNextToken(TerminalTokens.TokenNameAND, this.preferences.insert_space_before_and_in_type_parameter);
+				if (this.preferences.insert_space_after_and_in_type_parameter) {
+					this.scribe.space();
+				}
+			}
+			bounds[boundsLength - 1].traverse(this, scope);
+		}
+		return false;
+	}
+	public boolean visit(TypeParameter typeParameter, ClassScope scope) {
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
+		if (typeParameter.type != null) {
+			this.scribe.space();
+			this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
+			this.scribe.space();
+			typeParameter.type.traverse(this, scope);
+		}
+		final TypeReference[] bounds = typeParameter.bounds;
+		if (bounds != null) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameAND, this.preferences.insert_space_before_and_in_type_parameter);
+			if (this.preferences.insert_space_after_and_in_type_parameter) {
+				this.scribe.space();
+			}
+			int boundsLength = bounds.length;
+			for (int i = 0; i < boundsLength - 1; i++) {
+				bounds[i].traverse(this, scope);
+				this.scribe.printNextToken(TerminalTokens.TokenNameAND, this.preferences.insert_space_before_and_in_type_parameter);
+				if (this.preferences.insert_space_after_and_in_type_parameter) {
+					this.scribe.space();
+				}
+			}
+			bounds[boundsLength - 1].traverse(this, scope);
+		}
+		return false;
+	}
 
 	/**
 	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.UnaryExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
@@ -4200,4 +5087,44 @@
 		}
 		return false;
 	}
+	public boolean visit(Wildcard wildcard, BlockScope scope) {
+		this.scribe.printNextToken(TerminalTokens.TokenNameQUESTION, this.preferences.insert_space_before_question_in_wilcard);
+		switch(wildcard.kind) {
+			case Wildcard.SUPER :
+				this.scribe.printNextToken(TerminalTokens.TokenNamesuper, true);				
+				this.scribe.space();
+				wildcard.bound.traverse(this, scope);
+				break;
+			case Wildcard.EXTENDS :
+				this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);				
+				this.scribe.space();
+				wildcard.bound.traverse(this, scope);
+				break;
+			case Wildcard.UNBOUND :
+				if (this.preferences.insert_space_after_question_in_wilcard) {
+					this.scribe.space();
+				}
+		}
+		return false;
+	}
+	public boolean visit(Wildcard wildcard, ClassScope scope) {
+		this.scribe.printNextToken(TerminalTokens.TokenNameQUESTION, this.preferences.insert_space_before_question_in_wilcard);
+		switch(wildcard.kind) {
+			case Wildcard.SUPER :
+				this.scribe.printNextToken(TerminalTokens.TokenNamesuper, true);				
+				this.scribe.space();
+				wildcard.bound.traverse(this, scope);
+				break;
+			case Wildcard.EXTENDS :
+				this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);				
+				this.scribe.space();
+				wildcard.bound.traverse(this, scope);
+				break;
+			case Wildcard.UNBOUND :
+				if (this.preferences.insert_space_after_question_in_wilcard) {
+					this.scribe.space();
+				}
+		}
+		return false;
+	}
 }
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
index bd4668a..ab8b7e4 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
@@ -170,11 +170,14 @@
 			optionsMap.put(CompilerOptions.OPTION_ReportPossibleAccidentalBooleanAssignment, CompilerOptions.IGNORE);
 			optionsMap.put(CompilerOptions.OPTION_ReportEmptyStatement, CompilerOptions.IGNORE);
 			optionsMap.put(CompilerOptions.OPTION_ReportAssertIdentifier, CompilerOptions.IGNORE);
+			optionsMap.put(CompilerOptions.OPTION_ReportEnumIdentifier, CompilerOptions.IGNORE);
 			optionsMap.put(CompilerOptions.OPTION_ReportUndocumentedEmptyBlock, CompilerOptions.IGNORE);
 			optionsMap.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.IGNORE);
 			optionsMap.put(CompilerOptions.OPTION_ReportInvalidJavadoc, CompilerOptions.IGNORE);
 			optionsMap.put(CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility, CompilerOptions.PUBLIC);
 			optionsMap.put(CompilerOptions.OPTION_ReportInvalidJavadocTags, CompilerOptions.DISABLED);
+			optionsMap.put(CompilerOptions.OPTION_ReportInvalidJavadocTagsDeprecatedRef, CompilerOptions.DISABLED);
+			optionsMap.put(CompilerOptions.OPTION_ReportInvalidJavadocTagsNotVisibleRef, CompilerOptions.DISABLED);
 			optionsMap.put(CompilerOptions.OPTION_ReportMissingJavadocTags, CompilerOptions.IGNORE);
 			optionsMap.put(CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility, CompilerOptions.PUBLIC);
 			optionsMap.put(CompilerOptions.OPTION_ReportMissingJavadocTagsOverriding, CompilerOptions.DISABLED);
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
index 5943709..c01a6d6 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
@@ -36,6 +36,7 @@
 	}
 
 	public int alignment_for_arguments_in_allocation_expression;
+	public int alignment_for_arguments_in_enum_constant;
 	public int alignment_for_arguments_in_explicit_constructor_call;
 	public int alignment_for_arguments_in_method_invocation;
 	public int alignment_for_arguments_in_qualified_allocation_expression;
@@ -48,17 +49,21 @@
 	public int alignment_for_parameters_in_method_declaration;
 	public int alignment_for_selector_in_method_invocation;
 	public int alignment_for_superclass_in_type_declaration;
+	public int alignment_for_superinterfaces_in_enum_declaration;
 	public int alignment_for_superinterfaces_in_type_declaration;
 	public int alignment_for_throws_clause_in_constructor_declaration;
 	public int alignment_for_throws_clause_in_method_declaration;
 	
 	public boolean align_type_members_on_columns;
 	
+	public String brace_position_for_annotation_type_declaration;
 	public String brace_position_for_anonymous_type_declaration;
 	public String brace_position_for_array_initializer;
 	public String brace_position_for_block;
 	public String brace_position_for_block_in_case;
 	public String brace_position_for_constructor_declaration;
+	public String brace_position_for_enum_constant;
+	public String brace_position_for_enum_declaration;
 	public String brace_position_for_method_declaration;
 	public String brace_position_for_type_declaration;
 	public String brace_position_for_switch;
@@ -80,12 +85,15 @@
 	
 	public boolean indent_statements_compare_to_block;
 	public boolean indent_statements_compare_to_body;
+	public boolean indent_body_declarations_compare_to_enum_constant_header;
+	public boolean indent_body_declarations_compare_to_enum_declaration_header;
 	public boolean indent_body_declarations_compare_to_type_header;
 	public boolean indent_breaks_compare_to_cases;
 	public boolean indent_switchstatements_compare_to_cases;
 	public boolean indent_switchstatements_compare_to_switch;
 	
 	public boolean insert_new_line_after_opening_brace_in_array_initializer;
+	public boolean insert_new_line_at_end_of_file_if_missing;
 	public boolean insert_new_line_before_catch_in_try_statement;
 	public boolean insert_new_line_before_closing_brace_in_array_initializer;
 	public boolean insert_new_line_before_else_in_if_statement;
@@ -93,20 +101,31 @@
 	public boolean insert_new_line_before_while_in_do_statement;
 	public boolean insert_new_line_in_empty_anonymous_type_declaration;
 	public boolean insert_new_line_in_empty_block;
+	public boolean insert_new_line_in_empty_enum_constant;
+	public boolean insert_new_line_in_empty_enum_declaration;
 	public boolean insert_new_line_in_empty_method_body;
 	public boolean insert_new_line_in_empty_type_declaration;
+	public boolean insert_space_after_and_in_type_parameter;
 	public boolean insert_space_after_assignment_operator;
+	public boolean insert_space_after_at_in_annotation;
+	public boolean insert_space_after_at_in_annotation_type_declaration;
 	public boolean insert_space_after_binary_operator;
+	public boolean insert_space_after_closing_angle_bracket_in_type_arguments;
+	public boolean insert_space_after_closing_angle_bracket_in_type_parameters;
 	public boolean insert_space_after_closing_paren_in_cast;
 	public boolean insert_space_after_closing_brace_in_block;
 	public boolean insert_space_after_colon_in_assert;
 	public boolean insert_space_after_colon_in_case;
 	public boolean insert_space_after_colon_in_conditional;
+	public boolean insert_space_after_colon_in_for;
 	public boolean insert_space_after_colon_in_labeled_statement;
 	public boolean insert_space_after_comma_in_allocation_expression;
+	public boolean insert_space_after_comma_in_annotation;
 	public boolean insert_space_after_comma_in_array_initializer;
 	public boolean insert_space_after_comma_in_constructor_declaration_parameters;
 	public boolean insert_space_after_comma_in_constructor_declaration_throws;
+	public boolean insert_space_after_comma_in_enum_constant_arguments;
+	public boolean insert_space_after_comma_in_enum_declarations;
 	public boolean insert_space_after_comma_in_explicit_constructor_call_arguments;
 	public boolean insert_space_after_comma_in_for_increments;
 	public boolean insert_space_after_comma_in_for_inits;
@@ -115,13 +134,22 @@
 	public boolean insert_space_after_comma_in_method_declaration_throws;
 	public boolean insert_space_after_comma_in_multiple_field_declarations;
 	public boolean insert_space_after_comma_in_multiple_local_declarations;
+	public boolean insert_space_after_comma_in_parameterized_type_reference;
 	public boolean insert_space_after_comma_in_superinterfaces;
+	public boolean insert_space_after_comma_in_type_arguments;
+	public boolean insert_space_after_comma_in_type_parameters;
+	public boolean insert_space_after_ellipsis;
+	public boolean insert_space_after_opening_angle_bracket_in_parameterized_type_reference;
+	public boolean insert_space_after_opening_angle_bracket_in_type_arguments;
+	public boolean insert_space_after_opening_angle_bracket_in_type_parameters;
 	public boolean insert_space_after_opening_bracket_in_array_allocation_expression;
 	public boolean insert_space_after_opening_bracket_in_array_reference;
 	public boolean insert_space_after_opening_brace_in_array_initializer;
+	public boolean insert_space_after_opening_paren_in_annotation;
 	public boolean insert_space_after_opening_paren_in_cast;
 	public boolean insert_space_after_opening_paren_in_catch;
 	public boolean insert_space_after_opening_paren_in_constructor_declaration;
+	public boolean insert_space_after_opening_paren_in_enum_constant;
 	public boolean insert_space_after_opening_paren_in_for;
 	public boolean insert_space_after_opening_paren_in_if;
 	public boolean insert_space_after_opening_paren_in_method_declaration;
@@ -133,16 +161,24 @@
 	public boolean insert_space_after_postfix_operator;
 	public boolean insert_space_after_prefix_operator;
 	public boolean insert_space_after_question_in_conditional;
+	public boolean insert_space_after_question_in_wilcard;
 	public boolean insert_space_after_semicolon_in_for;
 	public boolean insert_space_after_unary_operator;
+	public boolean insert_space_before_and_in_type_parameter;
+	public boolean insert_space_before_at_in_annotation_type_declaration;
 	public boolean insert_space_before_assignment_operator;
 	public boolean insert_space_before_binary_operator;
+	public boolean insert_space_before_closing_angle_bracket_in_parameterized_type_reference;
+	public boolean insert_space_before_closing_angle_bracket_in_type_arguments;
+	public boolean insert_space_before_closing_angle_bracket_in_type_parameters;
 	public boolean insert_space_before_closing_brace_in_array_initializer;
 	public boolean insert_space_before_closing_bracket_in_array_allocation_expression;
 	public boolean insert_space_before_closing_bracket_in_array_reference;
+	public boolean insert_space_before_closing_paren_in_annotation;
 	public boolean insert_space_before_closing_paren_in_cast;
 	public boolean insert_space_before_closing_paren_in_catch;
 	public boolean insert_space_before_closing_paren_in_constructor_declaration;
+	public boolean insert_space_before_closing_paren_in_enum_constant;
 	public boolean insert_space_before_closing_paren_in_for;
 	public boolean insert_space_before_closing_paren_in_if;
 	public boolean insert_space_before_closing_paren_in_method_declaration;
@@ -155,11 +191,15 @@
 	public boolean insert_space_before_colon_in_case;
 	public boolean insert_space_before_colon_in_conditional;
 	public boolean insert_space_before_colon_in_default;
+	public boolean insert_space_before_colon_in_for;
 	public boolean insert_space_before_colon_in_labeled_statement;
 	public boolean insert_space_before_comma_in_allocation_expression;
+	public boolean insert_space_before_comma_in_annotation;
 	public boolean insert_space_before_comma_in_array_initializer;
 	public boolean insert_space_before_comma_in_constructor_declaration_parameters;
 	public boolean insert_space_before_comma_in_constructor_declaration_throws;
+	public boolean insert_space_before_comma_in_enum_constant_arguments;
+	public boolean insert_space_before_comma_in_enum_declarations;
 	public boolean insert_space_before_comma_in_explicit_constructor_call_arguments;
 	public boolean insert_space_before_comma_in_for_increments;
 	public boolean insert_space_before_comma_in_for_inits;
@@ -168,18 +208,32 @@
 	public boolean insert_space_before_comma_in_method_declaration_throws;
 	public boolean insert_space_before_comma_in_multiple_field_declarations;
 	public boolean insert_space_before_comma_in_multiple_local_declarations;
+	public boolean insert_space_before_comma_in_parameterized_type_reference;
 	public boolean insert_space_before_comma_in_superinterfaces;
+	public boolean insert_space_before_comma_in_type_arguments;
+	public boolean insert_space_before_comma_in_type_parameters;
+	public boolean insert_space_before_ellipsis;
+	public boolean insert_space_before_question_in_wilcard;
+	public boolean insert_space_before_opening_angle_bracket_in_parameterized_type_reference;
+	public boolean insert_space_before_opening_angle_bracket_in_type_arguments;
+	public boolean insert_space_before_opening_angle_bracket_in_type_parameters;
+	public boolean insert_space_before_opening_brace_in_annotation_type_declaration;
 	public boolean insert_space_before_opening_brace_in_anonymous_type_declaration;
 	public boolean insert_space_before_opening_brace_in_array_initializer;
 	public boolean insert_space_before_opening_brace_in_block;
 	public boolean insert_space_before_opening_brace_in_constructor_declaration;
+	public boolean insert_space_before_opening_brace_in_enum_constant;
+	public boolean insert_space_before_opening_brace_in_enum_declaration;
 	public boolean insert_space_before_opening_brace_in_method_declaration;
 	public boolean insert_space_before_opening_brace_in_type_declaration;
 	public boolean insert_space_before_opening_bracket_in_array_allocation_expression;
 	public boolean insert_space_before_opening_bracket_in_array_reference;
 	public boolean insert_space_before_opening_bracket_in_array_type_reference;
+	public boolean insert_space_before_opening_paren_in_annotation;
+	public boolean insert_space_before_opening_paren_in_annotation_type_member_declaration;
 	public boolean insert_space_before_opening_paren_in_catch;
 	public boolean insert_space_before_opening_paren_in_constructor_declaration;
+	public boolean insert_space_before_opening_paren_in_enum_constant;
 	public boolean insert_space_before_opening_paren_in_for;
 	public boolean insert_space_before_opening_paren_in_if;
 	public boolean insert_space_before_opening_paren_in_method_invocation;
@@ -198,7 +252,9 @@
 	public boolean insert_space_between_brackets_in_array_type_reference;
 	public boolean insert_space_between_empty_braces_in_array_initializer;
 	public boolean insert_space_between_empty_brackets_in_array_allocation_expression;
+	public boolean insert_space_between_empty_parens_in_annotation_type_member_declaration;
 	public boolean insert_space_between_empty_parens_in_constructor_declaration;
+	public boolean insert_space_between_empty_parens_in_enum_constant;
 	public boolean insert_space_between_empty_parens_in_method_declaration;
 	public boolean insert_space_between_empty_parens_in_method_invocation;
 	public boolean compact_else_if;
@@ -234,6 +290,7 @@
 	public Map getMap() {
 		Map options = new HashMap();
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_ALLOCATION_EXPRESSION, getAlignment(this.alignment_for_arguments_in_allocation_expression));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_ENUM_CONSTANT, getAlignment(this.alignment_for_arguments_in_enum_constant));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_EXPLICIT_CONSTRUCTOR_CALL, getAlignment(this.alignment_for_arguments_in_explicit_constructor_call));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_METHOD_INVOCATION, getAlignment(this.alignment_for_arguments_in_method_invocation));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_QUALIFIED_ALLOCATION_EXPRESSION, getAlignment(this.alignment_for_arguments_in_qualified_allocation_expression));
@@ -246,15 +303,19 @@
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERS_IN_METHOD_DECLARATION, getAlignment(this.alignment_for_parameters_in_method_declaration));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_SELECTOR_IN_METHOD_INVOCATION, getAlignment(this.alignment_for_selector_in_method_invocation));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_SUPERCLASS_IN_TYPE_DECLARATION, getAlignment(this.alignment_for_superclass_in_type_declaration));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_SUPERINTERFACES_IN_ENUM_DECLARATION, getAlignment(this.alignment_for_superinterfaces_in_enum_declaration));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_SUPERINTERFACES_IN_TYPE_DECLARATION, getAlignment(this.alignment_for_superinterfaces_in_type_declaration));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_THROWS_CLAUSE_IN_CONSTRUCTOR_DECLARATION, getAlignment(this.alignment_for_throws_clause_in_constructor_declaration));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_THROWS_CLAUSE_IN_METHOD_DECLARATION, getAlignment(this.alignment_for_throws_clause_in_method_declaration));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGN_TYPE_MEMBERS_ON_COLUMNS, this.align_type_members_on_columns ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_ANNOTATION_TYPE_DECLARATION, this.brace_position_for_annotation_type_declaration);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_ANONYMOUS_TYPE_DECLARATION, this.brace_position_for_anonymous_type_declaration);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_ARRAY_INITIALIZER, this.brace_position_for_array_initializer);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_BLOCK, this.brace_position_for_block);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_BLOCK_IN_CASE, this.brace_position_for_block_in_case);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_CONSTRUCTOR_DECLARATION, this.brace_position_for_constructor_declaration);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_ENUM_CONSTANT, this.brace_position_for_enum_constant);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_ENUM_DECLARATION, this.brace_position_for_enum_declaration);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_METHOD_DECLARATION, this.brace_position_for_method_declaration);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_TYPE_DECLARATION, this.brace_position_for_type_declaration);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_SWITCH, this.brace_position_for_switch);
@@ -273,11 +334,14 @@
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_AT_BEGINNING_OF_METHOD_BODY, Integer.toString(this.blank_lines_at_beginning_of_method_body));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INDENT_STATEMENTS_COMPARE_TO_BLOCK, this.indent_statements_compare_to_block ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INDENT_STATEMENTS_COMPARE_TO_BODY, this.indent_statements_compare_to_body ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_ENUM_CONSTANT_HEADER, this.indent_body_declarations_compare_to_enum_constant_header ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_ENUM_DECLARATION_HEADER, this.indent_body_declarations_compare_to_enum_declaration_header ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_TYPE_HEADER, this.indent_body_declarations_compare_to_type_header ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INDENT_BREAKS_COMPARE_TO_CASES, this.indent_breaks_compare_to_cases ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_CASES, this.indent_switchstatements_compare_to_cases ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_SWITCH, this.indent_switchstatements_compare_to_switch ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_OPENING_BRACE_IN_ARRAY_INITIALIZER, this.insert_new_line_after_opening_brace_in_array_initializer? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AT_END_OF_FILE_IF_MISSING, this.insert_new_line_at_end_of_file_if_missing ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_BEFORE_CATCH_IN_TRY_STATEMENT, this.insert_new_line_before_catch_in_try_statement? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_BEFORE_CLOSING_BRACE_IN_ARRAY_INITIALIZER, this.insert_new_line_before_closing_brace_in_array_initializer? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_BEFORE_ELSE_IN_IF_STATEMENT, this.insert_new_line_before_else_in_if_statement? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
@@ -285,20 +349,31 @@
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_BEFORE_WHILE_IN_DO_STATEMENT, this.insert_new_line_before_while_in_do_statement? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ANONYMOUS_TYPE_DECLARATION, this.insert_new_line_in_empty_anonymous_type_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_BLOCK, this.insert_new_line_in_empty_block? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ENUM_CONSTANT, this.insert_new_line_in_empty_enum_constant? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ENUM_DECLARATION, this.insert_new_line_in_empty_enum_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_METHOD_BODY, this.insert_new_line_in_empty_method_body? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_TYPE_DECLARATION, this.insert_new_line_in_empty_type_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_AND_IN_TYPE_PARAMETER, this.insert_space_after_and_in_type_parameter? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATOR, this.insert_space_after_assignment_operator? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_AT_IN_ANNOTATION, this.insert_space_after_at_in_annotation? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_AT_IN_ANNOTATION_TYPE_DECLARATION, this.insert_space_after_at_in_annotation_type_declaration ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, this.insert_space_after_binary_operator? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS, this.insert_space_after_closing_angle_bracket_in_type_arguments ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_PARAMETERS, this.insert_space_after_closing_angle_bracket_in_type_parameters ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_CLOSING_PAREN_IN_CAST, this.insert_space_after_closing_paren_in_cast? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_CLOSING_BRACE_IN_BLOCK, this.insert_space_after_closing_brace_in_block? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
-		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COLON_IN_ASSERT, this.insert_space_after_colon_in_assert? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
-		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COLON_IN_CASE, this.insert_space_after_colon_in_case? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
-		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COLON_IN_CONDITIONAL, this.insert_space_after_colon_in_conditional? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COLON_IN_ASSERT, this.insert_space_after_colon_in_assert ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COLON_IN_CASE, this.insert_space_after_colon_in_case ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COLON_IN_CONDITIONAL, this.insert_space_after_colon_in_conditional ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COLON_IN_FOR, this.insert_space_after_colon_in_for ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COLON_IN_LABELED_STATEMENT, this.insert_space_after_colon_in_labeled_statement? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ALLOCATION_EXPRESSION, this.insert_space_after_comma_in_allocation_expression? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ANNOTATION, this.insert_space_after_comma_in_annotation? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ARRAY_INITIALIZER, this.insert_space_after_comma_in_array_initializer? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_CONSTRUCTOR_DECLARATION_PARAMETERS, this.insert_space_after_comma_in_constructor_declaration_parameters? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_CONSTRUCTOR_DECLARATION_THROWS, this.insert_space_after_comma_in_constructor_declaration_throws? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ENUM_CONSTANT_ARGUMENTS, this.insert_space_after_comma_in_enum_constant_arguments ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ENUM_DECLARATIONS, this.insert_space_after_comma_in_enum_declarations ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_EXPLICIT_CONSTRUCTOR_CALL_ARGUMENTS, this.insert_space_after_comma_in_explicit_constructor_call_arguments? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_FOR_INCREMENTS, this.insert_space_after_comma_in_for_increments? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_FOR_INITS, this.insert_space_after_comma_in_for_inits? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
@@ -307,13 +382,22 @@
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_METHOD_DECLARATION_THROWS, this.insert_space_after_comma_in_method_declaration_throws? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_MULTIPLE_FIELD_DECLARATIONS, this.insert_space_after_comma_in_multiple_field_declarations? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_MULTIPLE_LOCAL_DECLARATIONS, this.insert_space_after_comma_in_multiple_local_declarations? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_PARAMETERIZED_TYPE_REFERENCE, this.insert_space_after_comma_in_parameterized_type_reference? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_SUPERINTERFACES, this.insert_space_after_comma_in_superinterfaces? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS, this.insert_space_after_comma_in_type_arguments ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_TYPE_PARAMETERS, this.insert_space_after_comma_in_type_parameters ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_BRACKET_IN_ARRAY_ALLOCATION_EXPRESSION, this.insert_space_after_opening_bracket_in_array_allocation_expression? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ELLIPSIS, this.insert_space_after_ellipsis ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_ANGLE_BRACKET_IN_PARAMETERIZED_TYPE_REFERENCE, this.insert_space_after_opening_angle_bracket_in_parameterized_type_reference? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS, this.insert_space_after_opening_angle_bracket_in_type_arguments? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETERS, this.insert_space_after_opening_angle_bracket_in_type_parameters? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_BRACKET_IN_ARRAY_REFERENCE, this.insert_space_after_opening_bracket_in_array_reference? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_BRACE_IN_ARRAY_INITIALIZER, this.insert_space_after_opening_brace_in_array_initializer? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_ANNOTATION, this.insert_space_after_opening_paren_in_annotation? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_CAST, this.insert_space_after_opening_paren_in_cast? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_CATCH, this.insert_space_after_opening_paren_in_catch? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_CONSTRUCTOR_DECLARATION, this.insert_space_after_opening_paren_in_constructor_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_ENUM_CONSTANT, this.insert_space_after_opening_paren_in_enum_constant? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_FOR, this.insert_space_after_opening_paren_in_for? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_IF, this.insert_space_after_opening_paren_in_if? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_METHOD_DECLARATION, this.insert_space_after_opening_paren_in_method_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
@@ -325,16 +409,24 @@
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_POSTFIX_OPERATOR, this.insert_space_after_postfix_operator? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_PREFIX_OPERATOR, this.insert_space_after_prefix_operator? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_QUESTION_IN_CONDITIONAL, this.insert_space_after_question_in_conditional? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_QUESTION_IN_WILDCARD, this.insert_space_after_question_in_wilcard? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_SEMICOLON_IN_FOR, this.insert_space_after_semicolon_in_for? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_UNARY_OPERATOR, this.insert_space_after_unary_operator? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_AND_IN_TYPE_PARAMETER, this.insert_space_before_and_in_type_parameter ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_AT_IN_ANNOTATION_TYPE_DECLARATION, this.insert_space_before_at_in_annotation_type_declaration ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATOR, this.insert_space_before_assignment_operator? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, this.insert_space_before_binary_operator? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_ANGLE_BRACKET_IN_PARAMETERIZED_TYPE_REFERENCE, this.insert_space_before_closing_angle_bracket_in_parameterized_type_reference? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS, this.insert_space_before_closing_angle_bracket_in_type_arguments? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_ANGLE_BRACKET_IN_TYPE_PARAMETERS, this.insert_space_before_closing_angle_bracket_in_type_parameters? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_BRACE_IN_ARRAY_INITIALIZER, this.insert_space_before_closing_brace_in_array_initializer? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_BRACKET_IN_ARRAY_ALLOCATION_EXPRESSION, this.insert_space_before_closing_bracket_in_array_allocation_expression? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_BRACKET_IN_ARRAY_REFERENCE, this.insert_space_before_closing_bracket_in_array_reference? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_ANNOTATION, this.insert_space_before_closing_paren_in_annotation? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_CAST, this.insert_space_before_closing_paren_in_cast? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_CATCH, this.insert_space_before_closing_paren_in_catch? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_CONSTRUCTOR_DECLARATION, this.insert_space_before_closing_paren_in_constructor_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_ENUM_CONSTANT, this.insert_space_before_closing_paren_in_enum_constant? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_FOR, this.insert_space_before_closing_paren_in_for? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_IF, this.insert_space_before_closing_paren_in_if? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_METHOD_DECLARATION, this.insert_space_before_closing_paren_in_method_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
@@ -347,11 +439,15 @@
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_CASE, this.insert_space_before_colon_in_case? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_CONDITIONAL, this.insert_space_before_colon_in_conditional? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_DEFAULT, this.insert_space_before_colon_in_default? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_FOR, this.insert_space_before_colon_in_for ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_LABELED_STATEMENT, this.insert_space_before_colon_in_labeled_statement? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ALLOCATION_EXPRESSION, this.insert_space_before_comma_in_allocation_expression? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ANNOTATION, this.insert_space_before_comma_in_annotation? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ARRAY_INITIALIZER, this.insert_space_before_comma_in_array_initializer? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_CONSTRUCTOR_DECLARATION_PARAMETERS, this.insert_space_before_comma_in_constructor_declaration_parameters? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_CONSTRUCTOR_DECLARATION_THROWS, this.insert_space_before_comma_in_constructor_declaration_throws? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ENUM_CONSTANT_ARGUMENTS, this.insert_space_before_comma_in_enum_constant_arguments? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ENUM_DECLARATIONS, this.insert_space_before_comma_in_enum_declarations? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_EXPLICIT_CONSTRUCTOR_CALL_ARGUMENTS, this.insert_space_before_comma_in_explicit_constructor_call_arguments? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_FOR_INCREMENTS, this.insert_space_before_comma_in_for_increments? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_FOR_INITS, this.insert_space_before_comma_in_for_inits? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
@@ -361,17 +457,30 @@
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_MULTIPLE_FIELD_DECLARATIONS, this.insert_space_before_comma_in_multiple_field_declarations? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_MULTIPLE_LOCAL_DECLARATIONS, this.insert_space_before_comma_in_multiple_local_declarations? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_SUPERINTERFACES, this.insert_space_before_comma_in_superinterfaces? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_TYPE_ARGUMENTS, this.insert_space_before_comma_in_type_arguments ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_TYPE_PARAMETERS, this.insert_space_before_comma_in_type_parameters? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_PARAMETERIZED_TYPE_REFERENCE, this.insert_space_before_comma_in_parameterized_type_reference? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ELLIPSIS, this.insert_space_before_ellipsis ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_PARAMETERIZED_TYPE_REFERENCE, this.insert_space_before_opening_angle_bracket_in_parameterized_type_reference? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS, this.insert_space_before_opening_angle_bracket_in_type_arguments? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETERS, this.insert_space_before_opening_angle_bracket_in_type_parameters? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ANNOTATION_TYPE_DECLARATION, this.insert_space_before_opening_brace_in_annotation_type_declaration ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ANONYMOUS_TYPE_DECLARATION, this.insert_space_before_opening_brace_in_anonymous_type_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ARRAY_INITIALIZER, this.insert_space_before_opening_brace_in_array_initializer? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_BLOCK, this.insert_space_before_opening_brace_in_block? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_CONSTRUCTOR_DECLARATION, this.insert_space_before_opening_brace_in_constructor_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ENUM_CONSTANT, this.insert_space_before_opening_brace_in_enum_constant? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ENUM_DECLARATION, this.insert_space_before_opening_brace_in_enum_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_METHOD_DECLARATION, this.insert_space_before_opening_brace_in_method_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_TYPE_DECLARATION, this.insert_space_before_opening_brace_in_type_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACKET_IN_ARRAY_ALLOCATION_EXPRESSION, this.insert_space_before_opening_bracket_in_array_allocation_expression ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACKET_IN_ARRAY_REFERENCE, this.insert_space_before_opening_bracket_in_array_reference? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACKET_IN_ARRAY_TYPE_REFERENCE, this.insert_space_before_opening_bracket_in_array_type_reference? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_ANNOTATION, this.insert_space_before_opening_paren_in_annotation? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_ANNOTATION_TYPE_MEMBER_DECLARATION, this.insert_space_before_opening_paren_in_annotation_type_member_declaration ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_CATCH, this.insert_space_before_opening_paren_in_catch? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_CONSTRUCTOR_DECLARATION, this.insert_space_before_opening_paren_in_constructor_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_ENUM_CONSTANT, this.insert_space_before_opening_paren_in_enum_constant? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_FOR, this.insert_space_before_opening_paren_in_for? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_IF, this.insert_space_before_opening_paren_in_if? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_METHOD_INVOCATION, this.insert_space_before_opening_paren_in_method_invocation? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
@@ -384,13 +493,16 @@
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_POSTFIX_OPERATOR, this.insert_space_before_postfix_operator? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_PREFIX_OPERATOR, this.insert_space_before_prefix_operator? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_QUESTION_IN_CONDITIONAL, this.insert_space_before_question_in_conditional? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_QUESTION_IN_WILDCARD, this.insert_space_before_question_in_wilcard? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_SEMICOLON, this.insert_space_before_semicolon? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_SEMICOLON_IN_FOR, this.insert_space_before_semicolon_in_for? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_UNARY_OPERATOR, this.insert_space_before_unary_operator? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_BRACKETS_IN_ARRAY_TYPE_REFERENCE, this.insert_space_between_brackets_in_array_type_reference? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_BRACES_IN_ARRAY_INITIALIZER, this.insert_space_between_empty_braces_in_array_initializer? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_BRACKETS_IN_ARRAY_ALLOCATION_EXPRESSION, this.insert_space_between_empty_brackets_in_array_allocation_expression? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_PARENS_IN_ANNOTATION_TYPE_MEMBER_DECLARATION, this.insert_space_between_empty_parens_in_annotation_type_member_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_PARENS_IN_CONSTRUCTOR_DECLARATION, this.insert_space_between_empty_parens_in_constructor_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_PARENS_IN_ENUM_CONSTANT, this.insert_space_between_empty_parens_in_enum_constant? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_PARENS_IN_METHOD_DECLARATION, this.insert_space_between_empty_parens_in_method_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_PARENS_IN_METHOD_INVOCATION, this.insert_space_between_empty_parens_in_method_invocation? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_COMPACT_ELSE_IF, this.compact_else_if ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
@@ -418,6 +530,16 @@
 				this.alignment_for_arguments_in_allocation_expression = Alignment.M_COMPACT_SPLIT;
 			}
 		}
+		final Object alignmentForArgumentsInEnumConstantOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_ENUM_CONSTANT);
+		if (alignmentForArgumentsInEnumConstantOption != null) {
+			try {
+				this.alignment_for_arguments_in_enum_constant = Integer.parseInt((String) alignmentForArgumentsInEnumConstantOption);
+			} catch (NumberFormatException e) {
+				this.alignment_for_arguments_in_enum_constant = Alignment.M_COMPACT_SPLIT;
+			} catch (ClassCastException e) {
+				this.alignment_for_arguments_in_enum_constant = Alignment.M_COMPACT_SPLIT;
+			}
+		}
 		final Object alignmentForArgumentsInExplicitConstructorCallOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_EXPLICIT_CONSTRUCTOR_CALL);
 		if (alignmentForArgumentsInExplicitConstructorCallOption != null) {
 			try {
@@ -538,6 +660,16 @@
 				this.alignment_for_superclass_in_type_declaration = Alignment.M_NEXT_SHIFTED_SPLIT;
 			}
 		}
+		final Object alignmentForSuperinterfacesInEnumDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_SUPERINTERFACES_IN_ENUM_DECLARATION);
+		if (alignmentForSuperinterfacesInEnumDeclarationOption != null) {
+			try {
+				this.alignment_for_superinterfaces_in_enum_declaration = Integer.parseInt((String) alignmentForSuperinterfacesInEnumDeclarationOption);
+			} catch (NumberFormatException e) {
+				this.alignment_for_superinterfaces_in_enum_declaration = Alignment.M_NEXT_SHIFTED_SPLIT;
+			} catch(ClassCastException e) {
+				this.alignment_for_superinterfaces_in_enum_declaration = Alignment.M_NEXT_SHIFTED_SPLIT;
+			}
+		}
 		final Object alignmentForSuperinterfacesInTypeDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_SUPERINTERFACES_IN_TYPE_DECLARATION);
 		if (alignmentForSuperinterfacesInTypeDeclarationOption != null) {
 			try {
@@ -572,6 +704,14 @@
 		if (alignTypeMembersOnColumnsOption != null) {
 			this.align_type_members_on_columns = DefaultCodeFormatterConstants.TRUE.equals(alignTypeMembersOnColumnsOption);
 		}
+		final Object bracePositionForAnnotationTypeDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_ANNOTATION_TYPE_DECLARATION);
+		if (bracePositionForAnnotationTypeDeclarationOption != null) {
+			try {
+				this.brace_position_for_annotation_type_declaration = (String) bracePositionForAnnotationTypeDeclarationOption;
+			} catch(ClassCastException e) {
+				this.brace_position_for_annotation_type_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
+			}
+		}
 		final Object bracePositionForAnonymousTypeDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_ANONYMOUS_TYPE_DECLARATION);
 		if (bracePositionForAnonymousTypeDeclarationOption != null) {
 			try {
@@ -612,6 +752,22 @@
 				this.brace_position_for_constructor_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
 			}
 		}
+		final Object bracePositionForEnumConstantOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_ENUM_CONSTANT);
+		if (bracePositionForEnumConstantOption != null) {
+			try {
+				this.brace_position_for_enum_constant = (String) bracePositionForEnumConstantOption;
+			} catch(ClassCastException e) {
+				this.brace_position_for_enum_constant = DefaultCodeFormatterConstants.END_OF_LINE;
+			}
+		}
+		final Object bracePositionForEnumDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_ENUM_DECLARATION);
+		if (bracePositionForEnumDeclarationOption != null) {
+			try {
+				this.brace_position_for_enum_declaration = (String) bracePositionForEnumDeclarationOption;
+			} catch(ClassCastException e) {
+				this.brace_position_for_enum_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
+			}
+		}
 		final Object bracePositionForMethodDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_METHOD_DECLARATION);
 		if (bracePositionForMethodDeclarationOption != null) {
 			try {
@@ -774,6 +930,14 @@
 		if (indentStatementsCompareToBodyOption != null) {
 			this.indent_statements_compare_to_body = DefaultCodeFormatterConstants.TRUE.equals(indentStatementsCompareToBodyOption);
 		}
+		final Object indentBodyDeclarationsCompareToEnumConstantHeaderOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_ENUM_CONSTANT_HEADER);
+		if (indentBodyDeclarationsCompareToEnumConstantHeaderOption != null) {
+			this.indent_body_declarations_compare_to_enum_constant_header = DefaultCodeFormatterConstants.TRUE.equals(indentBodyDeclarationsCompareToEnumConstantHeaderOption);
+		}
+		final Object indentBodyDeclarationsCompareToEnumDeclarationHeaderOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_ENUM_DECLARATION_HEADER);
+		if (indentBodyDeclarationsCompareToEnumDeclarationHeaderOption != null) {
+			this.indent_body_declarations_compare_to_enum_declaration_header = DefaultCodeFormatterConstants.TRUE.equals(indentBodyDeclarationsCompareToEnumDeclarationHeaderOption);
+		}
 		final Object indentBodyDeclarationsCompareToTypeHeaderOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_TYPE_HEADER);
 		if (indentBodyDeclarationsCompareToTypeHeaderOption != null) {
 			this.indent_body_declarations_compare_to_type_header = DefaultCodeFormatterConstants.TRUE.equals(indentBodyDeclarationsCompareToTypeHeaderOption);
@@ -794,6 +958,10 @@
 		if (insertNewLineAfterOpeningBraceInArrayInitializerOption != null) {
 			this.insert_new_line_after_opening_brace_in_array_initializer = JavaCore.INSERT.equals(insertNewLineAfterOpeningBraceInArrayInitializerOption);
 		}
+		final Object insertNewLineAtEndOfFileIfMissingOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AT_END_OF_FILE_IF_MISSING);
+		if (insertNewLineAtEndOfFileIfMissingOption != null) {
+			this.insert_new_line_at_end_of_file_if_missing = JavaCore.INSERT.equals(insertNewLineAtEndOfFileIfMissingOption);
+		}
 		final Object insertNewLineBeforeCatchInTryStatementOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_BEFORE_CATCH_IN_TRY_STATEMENT);
 		if (insertNewLineBeforeCatchInTryStatementOption != null) {
 			this.insert_new_line_before_catch_in_try_statement = JavaCore.INSERT.equals(insertNewLineBeforeCatchInTryStatementOption);
@@ -822,6 +990,14 @@
 		if (insertNewLineInEmptyBlockOption != null) {
 			this.insert_new_line_in_empty_block = JavaCore.INSERT.equals(insertNewLineInEmptyBlockOption);
 		}
+		final Object insertNewLineInEmptyEnumConstantOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ENUM_CONSTANT);
+		if (insertNewLineInEmptyEnumConstantOption != null) {
+			this.insert_new_line_in_empty_enum_constant = JavaCore.INSERT.equals(insertNewLineInEmptyEnumConstantOption);
+		}
+		final Object insertNewLineInEmptyEnumDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ENUM_DECLARATION);
+		if (insertNewLineInEmptyEnumDeclarationOption != null) {
+			this.insert_new_line_in_empty_enum_declaration = JavaCore.INSERT.equals(insertNewLineInEmptyEnumDeclarationOption);
+		}
 		final Object insertNewLineInEmptyMethodBodyOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_METHOD_BODY);
 		if (insertNewLineInEmptyMethodBodyOption != null) {
 			this.insert_new_line_in_empty_method_body = JavaCore.INSERT.equals(insertNewLineInEmptyMethodBodyOption);
@@ -830,14 +1006,34 @@
 		if (insertNewLineInEmptyTypeDeclarationOption != null) {
 			this.insert_new_line_in_empty_type_declaration = JavaCore.INSERT.equals(insertNewLineInEmptyTypeDeclarationOption);
 		}
+		final Object insertSpaceAfterAndInWildcardOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_AND_IN_TYPE_PARAMETER);
+		if (insertSpaceAfterAndInWildcardOption != null) {
+			this.insert_space_after_and_in_type_parameter = JavaCore.INSERT.equals(insertSpaceAfterAndInWildcardOption);
+		}
 		final Object insertSpaceAfterAssignmentOperatorOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATOR);
 		if (insertSpaceAfterAssignmentOperatorOption != null) {
 			this.insert_space_after_assignment_operator = JavaCore.INSERT.equals(insertSpaceAfterAssignmentOperatorOption);
 		}
+		final Object insertSpaceAfterAtInAnnotationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_AT_IN_ANNOTATION);
+		if (insertSpaceAfterAtInAnnotationOption != null) {
+			this.insert_space_after_at_in_annotation = JavaCore.INSERT.equals(insertSpaceAfterAtInAnnotationOption);
+		}
+		final Object insertSpaceAfterAtInAnnotationTypeDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_AT_IN_ANNOTATION_TYPE_DECLARATION);
+		if (insertSpaceAfterAtInAnnotationTypeDeclarationOption != null) {
+			this.insert_space_after_at_in_annotation_type_declaration = JavaCore.INSERT.equals(insertSpaceAfterAtInAnnotationTypeDeclarationOption);
+		}
 		final Object insertSpaceAfterBinaryOperatorOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR);
 		if (insertSpaceAfterBinaryOperatorOption != null) {
 			this.insert_space_after_binary_operator = JavaCore.INSERT.equals(insertSpaceAfterBinaryOperatorOption);
 		}
+		final Object insertSpaceAfterClosingAngleBracketInTypeArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS);
+		if (insertSpaceAfterClosingAngleBracketInTypeArgumentsOption != null) {
+			this.insert_space_after_closing_angle_bracket_in_type_arguments = JavaCore.INSERT.equals(insertSpaceAfterClosingAngleBracketInTypeArgumentsOption);
+		}
+		final Object insertSpaceAfterClosingAngleBracketInTypeParametersOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_PARAMETERS);
+		if (insertSpaceAfterClosingAngleBracketInTypeParametersOption != null) {
+			this.insert_space_after_closing_angle_bracket_in_type_parameters = JavaCore.INSERT.equals(insertSpaceAfterClosingAngleBracketInTypeParametersOption);
+		}
 		final Object insertSpaceAfterClosingParenInCastOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_CLOSING_PAREN_IN_CAST);
 		if (insertSpaceAfterClosingParenInCastOption != null) {
 			this.insert_space_after_closing_paren_in_cast = JavaCore.INSERT.equals(insertSpaceAfterClosingParenInCastOption);
@@ -858,6 +1054,10 @@
 		if (insertSpaceAfterColonInConditionalOption != null) {
 			this.insert_space_after_colon_in_conditional = JavaCore.INSERT.equals(insertSpaceAfterColonInConditionalOption);
 		}
+		final Object insertSpaceAfterColonInForOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COLON_IN_FOR);
+		if (insertSpaceAfterColonInForOption != null) {
+			this.insert_space_after_colon_in_for = JavaCore.INSERT.equals(insertSpaceAfterColonInForOption);
+		}
 		final Object insertSpaceAfterColonInLabeledStatementOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COLON_IN_LABELED_STATEMENT);
 		if (insertSpaceAfterColonInLabeledStatementOption != null) {
 			this.insert_space_after_colon_in_labeled_statement = JavaCore.INSERT.equals(insertSpaceAfterColonInLabeledStatementOption);
@@ -866,6 +1066,10 @@
 		if (insertSpaceAfterCommaInAllocationExpressionOption != null) {
 			this.insert_space_after_comma_in_allocation_expression = JavaCore.INSERT.equals(insertSpaceAfterCommaInAllocationExpressionOption);
 		}
+		final Object insertSpaceAfterCommaInAnnotationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ANNOTATION);
+		if (insertSpaceAfterCommaInAnnotationOption != null) {
+			this.insert_space_after_comma_in_annotation = JavaCore.INSERT.equals(insertSpaceAfterCommaInAnnotationOption);
+		}
 		final Object insertSpaceAfterCommaInArrayInitializerOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ARRAY_INITIALIZER);
 		if (insertSpaceAfterCommaInArrayInitializerOption != null) {
 			this.insert_space_after_comma_in_array_initializer = JavaCore.INSERT.equals(insertSpaceAfterCommaInArrayInitializerOption);
@@ -878,6 +1082,14 @@
 		if (insertSpaceAfterCommaInConstructorDeclarationThrowsOption != null) {
 			this.insert_space_after_comma_in_constructor_declaration_throws = JavaCore.INSERT.equals(insertSpaceAfterCommaInConstructorDeclarationThrowsOption);
 		}
+		final Object insertSpaceAfterCommaInEnumConstantArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ENUM_CONSTANT_ARGUMENTS);
+		if (insertSpaceAfterCommaInEnumConstantArgumentsOption != null) {
+			this.insert_space_after_comma_in_enum_constant_arguments = JavaCore.INSERT.equals(insertSpaceAfterCommaInEnumConstantArgumentsOption);
+		}
+		final Object insertSpaceAfterCommaInEnumDeclarationsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ENUM_DECLARATIONS);
+		if (insertSpaceAfterCommaInEnumDeclarationsOption != null) {
+			this.insert_space_after_comma_in_enum_declarations = JavaCore.INSERT.equals(insertSpaceAfterCommaInEnumDeclarationsOption);
+		}
 		final Object insertSpaceAfterCommaInExplicitConstructorCallArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_EXPLICIT_CONSTRUCTOR_CALL_ARGUMENTS);
 		if (insertSpaceAfterCommaInExplicitConstructorCallArgumentsOption != null) {
 			this.insert_space_after_comma_in_explicit_constructor_call_arguments = JavaCore.INSERT.equals(insertSpaceAfterCommaInExplicitConstructorCallArgumentsOption);
@@ -910,10 +1122,38 @@
 		if (insertSpaceAfterCommaInMultipleLocalDeclarationsOption != null) {
 			this.insert_space_after_comma_in_multiple_local_declarations = JavaCore.INSERT.equals(insertSpaceAfterCommaInMultipleLocalDeclarationsOption);
 		}
+		final Object insertSpaceAfterCommaInParameterizedTypeReferenceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_PARAMETERIZED_TYPE_REFERENCE);
+		if (insertSpaceAfterCommaInParameterizedTypeReferenceOption != null) {
+			this.insert_space_after_comma_in_parameterized_type_reference = JavaCore.INSERT.equals(insertSpaceAfterCommaInParameterizedTypeReferenceOption);
+		}
 		final Object insertSpaceAfterCommaInSuperinterfacesOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_SUPERINTERFACES);
 		if (insertSpaceAfterCommaInSuperinterfacesOption != null) {
 			this.insert_space_after_comma_in_superinterfaces = JavaCore.INSERT.equals(insertSpaceAfterCommaInSuperinterfacesOption);
 		}
+		final Object insertSpaceAfterCommaInTypeArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS);
+		if (insertSpaceAfterCommaInTypeArgumentsOption != null) {
+			this.insert_space_after_comma_in_type_arguments = JavaCore.INSERT.equals(insertSpaceAfterCommaInTypeArgumentsOption);
+		}
+		final Object insertSpaceAfterCommaInTypeParametersOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_TYPE_PARAMETERS);
+		if (insertSpaceAfterCommaInTypeParametersOption != null) {
+			this.insert_space_after_comma_in_type_parameters = JavaCore.INSERT.equals(insertSpaceAfterCommaInTypeParametersOption);
+		}
+		final Object insertSpaceAfterEllipsisOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ELLIPSIS);
+		if (insertSpaceAfterEllipsisOption != null) {
+			this.insert_space_after_ellipsis = JavaCore.INSERT.equals(insertSpaceAfterEllipsisOption);
+		}
+		final Object insertSpaceAfterOpeningAngleBracketInParameterizedTypeReferenceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_ANGLE_BRACKET_IN_PARAMETERIZED_TYPE_REFERENCE);
+		if (insertSpaceAfterOpeningAngleBracketInParameterizedTypeReferenceOption != null) {
+			this.insert_space_after_opening_angle_bracket_in_parameterized_type_reference = JavaCore.INSERT.equals(insertSpaceAfterOpeningAngleBracketInParameterizedTypeReferenceOption);
+		}
+		final Object insertSpaceAfterOpeningAngleBracketInTypeArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS);
+		if (insertSpaceAfterOpeningAngleBracketInTypeArgumentsOption != null) {
+			this.insert_space_after_opening_angle_bracket_in_type_arguments = JavaCore.INSERT.equals(insertSpaceAfterOpeningAngleBracketInTypeArgumentsOption);
+		}
+		final Object insertSpaceAfterOpeningAngleBracketInTypeParametersOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETERS);
+		if (insertSpaceAfterOpeningAngleBracketInTypeParametersOption != null) {
+			this.insert_space_after_opening_angle_bracket_in_type_parameters = JavaCore.INSERT.equals(insertSpaceAfterOpeningAngleBracketInTypeParametersOption);
+		}
 		final Object insertSpaceAfterOpeningBracketInArrayAllocationExpressionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_BRACKET_IN_ARRAY_ALLOCATION_EXPRESSION);
 		if (insertSpaceAfterOpeningBracketInArrayAllocationExpressionOption != null) {
 			this.insert_space_after_opening_bracket_in_array_allocation_expression = JavaCore.INSERT.equals(insertSpaceAfterOpeningBracketInArrayAllocationExpressionOption);
@@ -926,6 +1166,10 @@
 		if (insertSpaceAfterOpeningBraceInArrayInitializerOption != null) {
 			this.insert_space_after_opening_brace_in_array_initializer = JavaCore.INSERT.equals(insertSpaceAfterOpeningBraceInArrayInitializerOption);
 		}
+		final Object insertSpaceAfterOpeningParenInAnnotationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_ANNOTATION);
+		if (insertSpaceAfterOpeningParenInAnnotationOption != null) {
+			this.insert_space_after_opening_paren_in_annotation = JavaCore.INSERT.equals(insertSpaceAfterOpeningParenInAnnotationOption);
+		}
 		final Object insertSpaceAfterOpeningParenInCastOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_CAST);
 		if (insertSpaceAfterOpeningParenInCastOption != null) {
 			this.insert_space_after_opening_paren_in_cast = JavaCore.INSERT.equals(insertSpaceAfterOpeningParenInCastOption);
@@ -938,6 +1182,10 @@
 		if (insertSpaceAfterOpeningParenInConstructorDeclarationOption != null) {
 			this.insert_space_after_opening_paren_in_constructor_declaration = JavaCore.INSERT.equals(insertSpaceAfterOpeningParenInConstructorDeclarationOption);
 		}
+		final Object insertSpaceAfterOpeningParenInEnumConstantOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_ENUM_CONSTANT);
+		if (insertSpaceAfterOpeningParenInEnumConstantOption != null) {
+			this.insert_space_after_opening_paren_in_enum_constant = JavaCore.INSERT.equals(insertSpaceAfterOpeningParenInEnumConstantOption);
+		}
 		final Object insertSpaceAfterOpeningParenInForOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_FOR);
 		if (insertSpaceAfterOpeningParenInForOption != null) {
 			this.insert_space_after_opening_paren_in_for = JavaCore.INSERT.equals(insertSpaceAfterOpeningParenInForOption);
@@ -982,6 +1230,10 @@
 		if (insertSpaceAfterQuestionInConditionalOption != null) {
 			this.insert_space_after_question_in_conditional = JavaCore.INSERT.equals(insertSpaceAfterQuestionInConditionalOption);
 		}
+		final Object insertSpaceAfterQuestionInWildcardOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_QUESTION_IN_WILDCARD);
+		if (insertSpaceAfterQuestionInWildcardOption != null) {
+			this.insert_space_after_question_in_wilcard = JavaCore.INSERT.equals(insertSpaceAfterQuestionInWildcardOption);
+		}
 		final Object insertSpaceAfterSemicolonInForOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_SEMICOLON_IN_FOR);
 		if (insertSpaceAfterSemicolonInForOption != null) {
 			this.insert_space_after_semicolon_in_for = JavaCore.INSERT.equals(insertSpaceAfterSemicolonInForOption);
@@ -990,6 +1242,14 @@
 		if (insertSpaceAfterUnaryOperatorOption != null) {
 			this.insert_space_after_unary_operator = JavaCore.INSERT.equals(insertSpaceAfterUnaryOperatorOption);
 		}
+		final Object insertSpaceBeforeAndInWildcardOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_AND_IN_TYPE_PARAMETER);
+		if (insertSpaceBeforeAndInWildcardOption != null) {
+			this.insert_space_before_and_in_type_parameter = JavaCore.INSERT.equals(insertSpaceBeforeAndInWildcardOption);
+		}
+		final Object insertSpaceBeforeAtInAnnotationTypeDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_AT_IN_ANNOTATION_TYPE_DECLARATION);
+		if (insertSpaceBeforeAtInAnnotationTypeDeclarationOption != null) {
+			this.insert_space_before_at_in_annotation_type_declaration = JavaCore.INSERT.equals(insertSpaceBeforeAtInAnnotationTypeDeclarationOption);
+		}
 		final Object insertSpaceBeforeAssignmentOperatorOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATOR);
 		if (insertSpaceBeforeAssignmentOperatorOption != null) {
 			this.insert_space_before_assignment_operator = JavaCore.INSERT.equals(insertSpaceBeforeAssignmentOperatorOption);
@@ -998,6 +1258,18 @@
 		if (insertSpaceBeforeBinaryOperatorOption != null) {
 			this.insert_space_before_binary_operator = JavaCore.INSERT.equals(insertSpaceBeforeBinaryOperatorOption);
 		}
+		final Object insertSpaceBeforeClosingAngleBracketInParameterizedTypeReferenceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_ANGLE_BRACKET_IN_PARAMETERIZED_TYPE_REFERENCE);
+		if (insertSpaceBeforeClosingAngleBracketInParameterizedTypeReferenceOption != null) {
+			this.insert_space_before_closing_angle_bracket_in_parameterized_type_reference = JavaCore.INSERT.equals(insertSpaceBeforeClosingAngleBracketInParameterizedTypeReferenceOption);
+		}
+		final Object insertSpaceBeforeClosingAngleBracketInTypeArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS);
+		if (insertSpaceBeforeClosingAngleBracketInTypeArgumentsOption != null) {
+			this.insert_space_before_closing_angle_bracket_in_type_arguments = JavaCore.INSERT.equals(insertSpaceBeforeClosingAngleBracketInTypeArgumentsOption);
+		}
+		final Object insertSpaceBeforeClosingAngleBracketInTypeParametersOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_ANGLE_BRACKET_IN_TYPE_PARAMETERS);
+		if (insertSpaceBeforeClosingAngleBracketInTypeParametersOption != null) {
+			this.insert_space_before_closing_angle_bracket_in_type_parameters = JavaCore.INSERT.equals(insertSpaceBeforeClosingAngleBracketInTypeParametersOption);
+		}
 		final Object insertSpaceBeforeClosingBraceInArrayInitializerOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_BRACE_IN_ARRAY_INITIALIZER);
 		if (insertSpaceBeforeClosingBraceInArrayInitializerOption != null) {
 			this.insert_space_before_closing_brace_in_array_initializer = JavaCore.INSERT.equals(insertSpaceBeforeClosingBraceInArrayInitializerOption);
@@ -1010,6 +1282,10 @@
 		if (insertSpaceBeforeClosingBracketInArrayReferenceOption != null) {
 			this.insert_space_before_closing_bracket_in_array_reference = JavaCore.INSERT.equals(insertSpaceBeforeClosingBracketInArrayReferenceOption);
 		}
+		final Object insertSpaceBeforeClosingParenInAnnotationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_ANNOTATION);
+		if (insertSpaceBeforeClosingParenInAnnotationOption != null) {
+			this.insert_space_before_closing_paren_in_annotation = JavaCore.INSERT.equals(insertSpaceBeforeClosingParenInAnnotationOption);
+		}
 		final Object insertSpaceBeforeClosingParenInCastOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_CAST);
 		if (insertSpaceBeforeClosingParenInCastOption != null) {
 			this.insert_space_before_closing_paren_in_cast = JavaCore.INSERT.equals(insertSpaceBeforeClosingParenInCastOption);
@@ -1022,6 +1298,10 @@
 		if (insertSpaceBeforeClosingParenInConstructorDeclarationOption != null) {
 			this.insert_space_before_closing_paren_in_constructor_declaration = JavaCore.INSERT.equals(insertSpaceBeforeClosingParenInConstructorDeclarationOption);
 		}
+		final Object insertSpaceBeforeClosingParenInEnumConstantOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_ENUM_CONSTANT);
+		if (insertSpaceBeforeClosingParenInEnumConstantOption != null) {
+			this.insert_space_before_closing_paren_in_enum_constant = JavaCore.INSERT.equals(insertSpaceBeforeClosingParenInEnumConstantOption);
+		}
 		final Object insertSpaceBeforeClosingParenInForOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_FOR);
 		if (insertSpaceBeforeClosingParenInForOption != null) {
 			this.insert_space_before_closing_paren_in_for = JavaCore.INSERT.equals(insertSpaceBeforeClosingParenInForOption);
@@ -1070,6 +1350,10 @@
 		if (insertSpaceBeforeColonInDefaultOption != null) {
 			this.insert_space_before_colon_in_default = JavaCore.INSERT.equals(insertSpaceBeforeColonInDefaultOption);
 		}
+		final Object insertSpaceBeforeColonInForOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_FOR);
+		if (insertSpaceBeforeColonInForOption != null) {
+			this.insert_space_before_colon_in_for = JavaCore.INSERT.equals(insertSpaceBeforeColonInForOption);
+		}
 		final Object insertSpaceBeforeColonInLabeledStatementOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_LABELED_STATEMENT);
 		if (insertSpaceBeforeColonInLabeledStatementOption != null) {
 			this.insert_space_before_colon_in_labeled_statement = JavaCore.INSERT.equals(insertSpaceBeforeColonInLabeledStatementOption);
@@ -1078,6 +1362,10 @@
 		if (insertSpaceBeforeCommaInAllocationExpressionOption != null) {
 			this.insert_space_before_comma_in_allocation_expression = JavaCore.INSERT.equals(insertSpaceBeforeCommaInAllocationExpressionOption);
 		}
+		final Object insertSpaceBeforeCommaInAnnotationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ANNOTATION);
+		if (insertSpaceBeforeCommaInAnnotationOption != null) {
+			this.insert_space_before_comma_in_annotation = JavaCore.INSERT.equals(insertSpaceBeforeCommaInAnnotationOption);
+		}
 		final Object insertSpaceBeforeCommaInArrayInitializerOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ARRAY_INITIALIZER);
 		if (insertSpaceBeforeCommaInArrayInitializerOption != null) {
 			this.insert_space_before_comma_in_array_initializer = JavaCore.INSERT.equals(insertSpaceBeforeCommaInArrayInitializerOption);
@@ -1090,6 +1378,14 @@
 		if (insertSpaceBeforeCommaInConstructorDeclarationThrowsOption != null) {
 			this.insert_space_before_comma_in_constructor_declaration_throws = JavaCore.INSERT.equals(insertSpaceBeforeCommaInConstructorDeclarationThrowsOption);
 		}
+		final Object insertSpaceBeforeCommaInEnumConstantArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ENUM_CONSTANT_ARGUMENTS);
+		if (insertSpaceBeforeCommaInEnumConstantArgumentsOption != null) {
+			this.insert_space_before_comma_in_enum_constant_arguments = JavaCore.INSERT.equals(insertSpaceBeforeCommaInEnumConstantArgumentsOption);
+		}
+		final Object insertSpaceBeforeCommaInEnumDeclarationsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ENUM_DECLARATIONS);
+		if (insertSpaceBeforeCommaInEnumDeclarationsOption != null) {
+			this.insert_space_before_comma_in_enum_declarations = JavaCore.INSERT.equals(insertSpaceBeforeCommaInEnumDeclarationsOption);
+		}
 		final Object insertSpaceBeforeCommaInExplicitConstructorCallArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_EXPLICIT_CONSTRUCTOR_CALL_ARGUMENTS);
 		if (insertSpaceBeforeCommaInExplicitConstructorCallArgumentsOption != null) {
 			this.insert_space_before_comma_in_explicit_constructor_call_arguments = JavaCore.INSERT.equals(insertSpaceBeforeCommaInExplicitConstructorCallArgumentsOption);
@@ -1122,10 +1418,42 @@
 		if (insertSpaceBeforeCommaInMultipleLocalDeclarationsOption != null) {
 			this.insert_space_before_comma_in_multiple_local_declarations = JavaCore.INSERT.equals(insertSpaceBeforeCommaInMultipleLocalDeclarationsOption);
 		}
+		final Object insertSpaceBeforeCommaInParameterizedTypeReferenceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_PARAMETERIZED_TYPE_REFERENCE);
+		if (insertSpaceBeforeCommaInParameterizedTypeReferenceOption != null) {
+			this.insert_space_before_comma_in_parameterized_type_reference = JavaCore.INSERT.equals(insertSpaceBeforeCommaInParameterizedTypeReferenceOption);
+		}
 		final Object insertSpaceBeforeCommaInSuperinterfacesOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_SUPERINTERFACES);
 		if (insertSpaceBeforeCommaInSuperinterfacesOption != null) {
 			this.insert_space_before_comma_in_superinterfaces = JavaCore.INSERT.equals(insertSpaceBeforeCommaInSuperinterfacesOption);
 		}
+		final Object insertSpaceBeforeCommaInTypeArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_TYPE_ARGUMENTS);
+		if (insertSpaceBeforeCommaInTypeArgumentsOption != null) {
+			this.insert_space_before_comma_in_type_arguments = JavaCore.INSERT.equals(insertSpaceBeforeCommaInTypeArgumentsOption);
+		}
+		final Object insertSpaceBeforeCommaInTypeParametersOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_TYPE_PARAMETERS);
+		if (insertSpaceBeforeCommaInTypeParametersOption != null) {
+			this.insert_space_before_comma_in_type_parameters = JavaCore.INSERT.equals(insertSpaceBeforeCommaInTypeParametersOption);
+		}
+		final Object insertSpaceBeforeEllipsisOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ELLIPSIS);
+		if (insertSpaceBeforeEllipsisOption != null) {
+			this.insert_space_before_ellipsis = JavaCore.INSERT.equals(insertSpaceBeforeEllipsisOption);
+		}
+		final Object insertSpaceBeforeOpeningAngleBrackerInParameterizedTypeReferenceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_PARAMETERIZED_TYPE_REFERENCE);
+		if (insertSpaceBeforeOpeningAngleBrackerInParameterizedTypeReferenceOption != null) {
+			this.insert_space_before_opening_angle_bracket_in_parameterized_type_reference = JavaCore.INSERT.equals(insertSpaceBeforeOpeningAngleBrackerInParameterizedTypeReferenceOption);
+		}
+		final Object insertSpaceBeforeOpeningAngleBrackerInTypeArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS);
+		if (insertSpaceBeforeOpeningAngleBrackerInTypeArgumentsOption != null) {
+			this.insert_space_before_opening_angle_bracket_in_type_arguments = JavaCore.INSERT.equals(insertSpaceBeforeOpeningAngleBrackerInTypeArgumentsOption);
+		}
+		final Object insertSpaceBeforeOpeningAngleBrackerInTypeParametersOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETERS);
+		if (insertSpaceBeforeOpeningAngleBrackerInTypeParametersOption != null) {
+			this.insert_space_before_opening_angle_bracket_in_type_parameters = JavaCore.INSERT.equals(insertSpaceBeforeOpeningAngleBrackerInTypeParametersOption);
+		}
+		final Object insertSpaceBeforeOpeningBraceInAnnotationTypeDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ANNOTATION_TYPE_DECLARATION);
+		if (insertSpaceBeforeOpeningBraceInAnnotationTypeDeclarationOption != null) {
+			this.insert_space_before_opening_brace_in_annotation_type_declaration = JavaCore.INSERT.equals(insertSpaceBeforeOpeningBraceInAnnotationTypeDeclarationOption);
+		}
 		final Object insertSpaceBeforeOpeningBraceInAnonymousTypeDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ANONYMOUS_TYPE_DECLARATION);
 		if (insertSpaceBeforeOpeningBraceInAnonymousTypeDeclarationOption != null) {
 			this.insert_space_before_opening_brace_in_anonymous_type_declaration = JavaCore.INSERT.equals(insertSpaceBeforeOpeningBraceInAnonymousTypeDeclarationOption);
@@ -1142,6 +1470,14 @@
 		if (insertSpaceBeforeOpeningBraceInConstructorDeclarationOption != null) {
 			this.insert_space_before_opening_brace_in_constructor_declaration = JavaCore.INSERT.equals(insertSpaceBeforeOpeningBraceInConstructorDeclarationOption);
 		}
+		final Object insertSpaceBeforeOpeningBraceInEnumDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ENUM_DECLARATION);
+		if (insertSpaceBeforeOpeningBraceInEnumDeclarationOption != null) {
+			this.insert_space_before_opening_brace_in_enum_declaration = JavaCore.INSERT.equals(insertSpaceBeforeOpeningBraceInEnumDeclarationOption);
+		}
+		final Object insertSpaceBeforeOpeningBraceInEnumConstantOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ENUM_CONSTANT);
+		if (insertSpaceBeforeOpeningBraceInEnumConstantOption != null) {
+			this.insert_space_before_opening_brace_in_enum_constant = JavaCore.INSERT.equals(insertSpaceBeforeOpeningBraceInEnumConstantOption);
+		}
 		final Object insertSpaceBeforeOpeningBraceInMethodDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_METHOD_DECLARATION);
 		if (insertSpaceBeforeOpeningBraceInMethodDeclarationOption != null) {
 			this.insert_space_before_opening_brace_in_method_declaration = JavaCore.INSERT.equals(insertSpaceBeforeOpeningBraceInMethodDeclarationOption);
@@ -1162,6 +1498,14 @@
 		if (insertSpaceBeforeOpeningBracketInArrayTypeReferenceOption != null) {
 			this.insert_space_before_opening_bracket_in_array_type_reference = JavaCore.INSERT.equals(insertSpaceBeforeOpeningBracketInArrayTypeReferenceOption);
 		}
+		final Object insertSpaceBeforeOpeningParenInAnnotationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_ANNOTATION);
+		if (insertSpaceBeforeOpeningParenInAnnotationOption != null) {
+			this.insert_space_before_opening_paren_in_annotation = JavaCore.INSERT.equals(insertSpaceBeforeOpeningParenInAnnotationOption);
+		}
+		final Object insertSpaceBeforeOpeningParenInAnnotationTypeMemberDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_ANNOTATION_TYPE_MEMBER_DECLARATION);
+		if (insertSpaceBeforeOpeningParenInAnnotationTypeMemberDeclarationOption != null) {
+			this.insert_space_before_opening_paren_in_annotation_type_member_declaration = JavaCore.INSERT.equals(insertSpaceBeforeOpeningParenInAnnotationTypeMemberDeclarationOption);
+		}
 		final Object insertSpaceBeforeOpeningParenInCatchOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_CATCH);
 		if (insertSpaceBeforeOpeningParenInCatchOption != null) {
 			this.insert_space_before_opening_paren_in_catch = JavaCore.INSERT.equals(insertSpaceBeforeOpeningParenInCatchOption);
@@ -1170,6 +1514,10 @@
 		if (insertSpaceBeforeOpeningParenInConstructorDeclarationOption != null) {
 			this.insert_space_before_opening_paren_in_constructor_declaration = JavaCore.INSERT.equals(insertSpaceBeforeOpeningParenInConstructorDeclarationOption);
 		}
+		final Object insertSpaceBeforeOpeningParenInEnumConstantOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_ENUM_CONSTANT);
+		if (insertSpaceBeforeOpeningParenInEnumConstantOption != null) {
+			this.insert_space_before_opening_paren_in_enum_constant = JavaCore.INSERT.equals(insertSpaceBeforeOpeningParenInEnumConstantOption);
+		}
 		final Object insertSpaceBeforeOpeningParenInForOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_FOR);
 		if (insertSpaceBeforeOpeningParenInForOption != null) {
 			this.insert_space_before_opening_paren_in_for = JavaCore.INSERT.equals(insertSpaceBeforeOpeningParenInForOption);
@@ -1218,6 +1566,10 @@
 		if (insertSpaceBeforeQuestionInConditionalOption != null) {
 			this.insert_space_before_question_in_conditional = JavaCore.INSERT.equals(insertSpaceBeforeQuestionInConditionalOption);
 		}
+		final Object insertSpaceBeforeQuestionInWildcardOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_QUESTION_IN_WILDCARD);
+		if (insertSpaceBeforeQuestionInWildcardOption != null) {
+			this.insert_space_before_question_in_wilcard = JavaCore.INSERT.equals(insertSpaceBeforeQuestionInWildcardOption);
+		}
 		final Object insertSpaceBeforeSemicolonOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_SEMICOLON);
 		if (insertSpaceBeforeSemicolonOption != null) {
 			this.insert_space_before_semicolon = JavaCore.INSERT.equals(insertSpaceBeforeSemicolonOption);
@@ -1246,6 +1598,14 @@
 		if (insertSpaceBetweenEmptyParensInConstructorDeclarationOption != null) {
 			this.insert_space_between_empty_parens_in_constructor_declaration = JavaCore.INSERT.equals(insertSpaceBetweenEmptyParensInConstructorDeclarationOption);
 		}
+		final Object insertSpaceBetweenEmptyParensInAnnotationTypeMemberDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_PARENS_IN_ANNOTATION_TYPE_MEMBER_DECLARATION);
+		if (insertSpaceBetweenEmptyParensInAnnotationTypeMemberDeclarationOption != null) {
+			this.insert_space_between_empty_parens_in_annotation_type_member_declaration = JavaCore.INSERT.equals(insertSpaceBetweenEmptyParensInAnnotationTypeMemberDeclarationOption);
+		}
+		final Object insertSpaceBetweenEmptyParensInEnumConstantOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_PARENS_IN_ENUM_CONSTANT);
+		if (insertSpaceBetweenEmptyParensInEnumConstantOption != null) {
+			this.insert_space_between_empty_parens_in_enum_constant = JavaCore.INSERT.equals(insertSpaceBetweenEmptyParensInEnumConstantOption);
+		}
 		final Object insertSpaceBetweenEmptyParensInMethodDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_PARENS_IN_METHOD_DECLARATION);
 		if (insertSpaceBetweenEmptyParensInMethodDeclarationOption != null) {
 			this.insert_space_between_empty_parens_in_method_declaration = JavaCore.INSERT.equals(insertSpaceBetweenEmptyParensInMethodDeclarationOption);
@@ -1320,6 +1680,7 @@
 
 	public void setDefaultSettings() {
 		this.alignment_for_arguments_in_allocation_expression = Alignment.M_COMPACT_SPLIT;
+		this.alignment_for_arguments_in_enum_constant = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_arguments_in_explicit_constructor_call = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_arguments_in_method_invocation = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_arguments_in_qualified_allocation_expression = Alignment.M_COMPACT_SPLIT;
@@ -1332,15 +1693,19 @@
 		this.alignment_for_parameters_in_method_declaration = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_selector_in_method_invocation = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_superclass_in_type_declaration = Alignment.M_NEXT_SHIFTED_SPLIT;
+		this.alignment_for_superinterfaces_in_enum_declaration = Alignment.M_NEXT_SHIFTED_SPLIT;
 		this.alignment_for_superinterfaces_in_type_declaration = Alignment.M_NEXT_SHIFTED_SPLIT;
 		this.alignment_for_throws_clause_in_constructor_declaration = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_throws_clause_in_method_declaration = Alignment.M_COMPACT_SPLIT;
 		this.align_type_members_on_columns = false;
+		this.brace_position_for_annotation_type_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_anonymous_type_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_array_initializer = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_block = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_block_in_case = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_constructor_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
+		this.brace_position_for_enum_constant = DefaultCodeFormatterConstants.END_OF_LINE;
+		this.brace_position_for_enum_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_method_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_type_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_switch = DefaultCodeFormatterConstants.END_OF_LINE;
@@ -1359,11 +1724,14 @@
 		this.blank_lines_at_beginning_of_method_body = 0;
 		this.indent_statements_compare_to_block = true;
 		this.indent_statements_compare_to_body = true;
+		this.indent_body_declarations_compare_to_enum_constant_header = true;
+		this.indent_body_declarations_compare_to_enum_declaration_header = true;
 		this.indent_body_declarations_compare_to_type_header = true;
 		this.indent_breaks_compare_to_cases = true;
 		this.indent_switchstatements_compare_to_cases = true;
 		this.indent_switchstatements_compare_to_switch = true;
 		this.insert_new_line_after_opening_brace_in_array_initializer = false;
+		this.insert_new_line_at_end_of_file_if_missing = false;
 		this.insert_new_line_before_catch_in_try_statement = false;
 		this.insert_new_line_before_closing_brace_in_array_initializer = false;
 		this.insert_new_line_before_else_in_if_statement = false;
@@ -1371,20 +1739,31 @@
 		this.insert_new_line_before_while_in_do_statement = false;
 		this.insert_new_line_in_empty_anonymous_type_declaration = true;
 		this.insert_new_line_in_empty_block = true;
+		this.insert_new_line_in_empty_enum_constant = true;
+		this.insert_new_line_in_empty_enum_declaration = true;
 		this.insert_new_line_in_empty_method_body = true;
 		this.insert_new_line_in_empty_type_declaration = true;
+		this.insert_space_after_and_in_type_parameter = true;
 		this.insert_space_after_assignment_operator = true;
+		this.insert_space_after_at_in_annotation = false;
+		this.insert_space_after_at_in_annotation_type_declaration = false;
 		this.insert_space_after_binary_operator = true;
+		this.insert_space_after_closing_angle_bracket_in_type_arguments = true;
+		this.insert_space_after_closing_angle_bracket_in_type_parameters = true;
 		this.insert_space_after_closing_paren_in_cast = true;
 		this.insert_space_after_closing_brace_in_block = true;
 		this.insert_space_after_colon_in_assert = true;
 		this.insert_space_after_colon_in_case = true;
 		this.insert_space_after_colon_in_conditional = true;
+		this.insert_space_after_colon_in_for = true;
 		this.insert_space_after_colon_in_labeled_statement = true;
 		this.insert_space_after_comma_in_allocation_expression = true;
+		this.insert_space_after_comma_in_annotation = true;
 		this.insert_space_after_comma_in_array_initializer = true;
 		this.insert_space_after_comma_in_constructor_declaration_parameters = true;
 		this.insert_space_after_comma_in_constructor_declaration_throws = true;
+		this.insert_space_after_comma_in_enum_constant_arguments = true;
+		this.insert_space_after_comma_in_enum_declarations = true;
 		this.insert_space_after_comma_in_explicit_constructor_call_arguments = true;
 		this.insert_space_after_comma_in_for_increments = true;
 		this.insert_space_after_comma_in_for_inits = true;
@@ -1393,13 +1772,22 @@
 		this.insert_space_after_comma_in_method_declaration_throws = true;
 		this.insert_space_after_comma_in_multiple_field_declarations = true;
 		this.insert_space_after_comma_in_multiple_local_declarations = true;
+		this.insert_space_after_comma_in_parameterized_type_reference = true;
 		this.insert_space_after_comma_in_superinterfaces = true;
+		this.insert_space_after_comma_in_type_arguments = true;
+		this.insert_space_after_comma_in_type_parameters = true;
+		this.insert_space_after_ellipsis = true;
+		this.insert_space_after_opening_angle_bracket_in_parameterized_type_reference = false;
+		this.insert_space_after_opening_angle_bracket_in_type_arguments = false;
+		this.insert_space_after_opening_angle_bracket_in_type_parameters = false;
 		this.insert_space_after_opening_bracket_in_array_allocation_expression = false;
 		this.insert_space_after_opening_bracket_in_array_reference = false;
 		this.insert_space_after_opening_brace_in_array_initializer = false;
+		this.insert_space_after_opening_paren_in_annotation = false;
 		this.insert_space_after_opening_paren_in_cast = false;
 		this.insert_space_after_opening_paren_in_catch = false;
 		this.insert_space_after_opening_paren_in_constructor_declaration = false;
+		this.insert_space_after_opening_paren_in_enum_constant = false;
 		this.insert_space_after_opening_paren_in_for = false;
 		this.insert_space_after_opening_paren_in_if = false;
 		this.insert_space_after_opening_paren_in_method_declaration = false;
@@ -1411,16 +1799,24 @@
 		this.insert_space_after_postfix_operator = false;
 		this.insert_space_after_prefix_operator = false;
 		this.insert_space_after_question_in_conditional = true;
+		this.insert_space_after_question_in_wilcard = false;
 		this.insert_space_after_semicolon_in_for = true;
 		this.insert_space_after_unary_operator = false;
+		this.insert_space_before_and_in_type_parameter = true;
+		this.insert_space_before_at_in_annotation_type_declaration = true;
 		this.insert_space_before_assignment_operator = true;
 		this.insert_space_before_binary_operator = true;
+		this.insert_space_before_closing_angle_bracket_in_parameterized_type_reference = false;
+		this.insert_space_before_closing_angle_bracket_in_type_arguments = false;
+		this.insert_space_before_closing_angle_bracket_in_type_parameters = false;
 		this.insert_space_before_closing_brace_in_array_initializer = false;
 		this.insert_space_before_closing_bracket_in_array_allocation_expression = false;
 		this.insert_space_before_closing_bracket_in_array_reference = false;
+		this.insert_space_before_closing_paren_in_annotation = false;
 		this.insert_space_before_closing_paren_in_cast = false;
 		this.insert_space_before_closing_paren_in_catch = false;
 		this.insert_space_before_closing_paren_in_constructor_declaration = false;
+		this.insert_space_before_closing_paren_in_enum_constant = false;
 		this.insert_space_before_closing_paren_in_for = false;
 		this.insert_space_before_closing_paren_in_if = false;
 		this.insert_space_before_closing_paren_in_method_declaration = false;
@@ -1433,11 +1829,14 @@
 		this.insert_space_before_colon_in_case = true;
 		this.insert_space_before_colon_in_conditional = true;
 		this.insert_space_before_colon_in_default = true;
+		this.insert_space_before_colon_in_for = true;
 		this.insert_space_before_colon_in_labeled_statement = true;
 		this.insert_space_before_comma_in_allocation_expression = false;
 		this.insert_space_before_comma_in_array_initializer = false;
 		this.insert_space_before_comma_in_constructor_declaration_parameters = false;
 		this.insert_space_before_comma_in_constructor_declaration_throws = false;
+		this.insert_space_before_comma_in_enum_constant_arguments = false;
+		this.insert_space_before_comma_in_enum_declarations = false;
 		this.insert_space_before_comma_in_explicit_constructor_call_arguments = false;
 		this.insert_space_before_comma_in_for_increments = false;
 		this.insert_space_before_comma_in_for_inits = false;
@@ -1446,19 +1845,32 @@
 		this.insert_space_before_comma_in_method_declaration_throws = false;
 		this.insert_space_before_comma_in_multiple_field_declarations = false;
 		this.insert_space_before_comma_in_multiple_local_declarations = false;
+		this.insert_space_before_comma_in_parameterized_type_reference = false;
 		this.insert_space_before_comma_in_superinterfaces = false;
+		this.insert_space_before_comma_in_type_arguments = false;
+		this.insert_space_before_comma_in_type_parameters = false;
+		this.insert_space_before_ellipsis = false;
+		this.insert_space_before_opening_angle_bracket_in_parameterized_type_reference = false;
+		this.insert_space_before_opening_angle_bracket_in_type_arguments = false;
+		this.insert_space_before_opening_angle_bracket_in_type_parameters = false;
+		this.insert_space_before_opening_brace_in_annotation_type_declaration = true;
 		this.insert_space_before_opening_brace_in_anonymous_type_declaration = true;
 		this.insert_space_before_opening_brace_in_array_initializer = false;
 		this.insert_space_before_opening_brace_in_block = true;
 		this.insert_space_before_opening_brace_in_constructor_declaration = true;
+		this.insert_space_before_opening_brace_in_enum_constant = true;
+		this.insert_space_before_opening_brace_in_enum_declaration = true;
 		this.insert_space_before_opening_brace_in_method_declaration = true;
 		this.insert_space_before_opening_brace_in_switch = true;
 		this.insert_space_before_opening_brace_in_type_declaration = true;
 		this.insert_space_before_opening_bracket_in_array_allocation_expression = false;
 		this.insert_space_before_opening_bracket_in_array_reference = false;
 		this.insert_space_before_opening_bracket_in_array_type_reference = false;
+		this.insert_space_before_opening_paren_in_annotation = false;
+		this.insert_space_before_opening_paren_in_annotation_type_member_declaration = false;
 		this.insert_space_before_opening_paren_in_catch = true;
 		this.insert_space_before_opening_paren_in_constructor_declaration = false;
+		this.insert_space_before_opening_paren_in_enum_constant = false;
 		this.insert_space_before_opening_paren_in_for = true;
 		this.insert_space_before_opening_paren_in_if = true;
 		this.insert_space_before_opening_paren_in_method_invocation = false;
@@ -1470,13 +1882,16 @@
 		this.insert_space_before_postfix_operator = false;
 		this.insert_space_before_prefix_operator = false;
 		this.insert_space_before_question_in_conditional = true;
+		this.insert_space_before_question_in_wilcard = false;
 		this.insert_space_before_semicolon = false;
 		this.insert_space_before_semicolon_in_for = false;
 		this.insert_space_before_unary_operator = false;
 		this.insert_space_between_brackets_in_array_type_reference = false;
 		this.insert_space_between_empty_braces_in_array_initializer = false;
 		this.insert_space_between_empty_brackets_in_array_allocation_expression = false;
+		this.insert_space_between_empty_parens_in_annotation_type_member_declaration = false;
 		this.insert_space_between_empty_parens_in_constructor_declaration = false;
+		this.insert_space_between_empty_parens_in_enum_constant = false;
 		this.insert_space_between_empty_parens_in_method_declaration = false;
 		this.insert_space_between_empty_parens_in_method_invocation = false;
 		this.compact_else_if = true;
@@ -1494,6 +1909,7 @@
 	
 	public void setJavaConventionsSettings() {
 		this.alignment_for_arguments_in_allocation_expression = Alignment.M_COMPACT_SPLIT;
+		this.alignment_for_arguments_in_enum_constant = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_arguments_in_explicit_constructor_call = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_arguments_in_method_invocation = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_arguments_in_qualified_allocation_expression = Alignment.M_COMPACT_SPLIT;
@@ -1506,15 +1922,19 @@
 		this.alignment_for_parameters_in_method_declaration = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_selector_in_method_invocation = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_superclass_in_type_declaration = Alignment.M_COMPACT_SPLIT;
+		this.alignment_for_superinterfaces_in_enum_declaration = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_superinterfaces_in_type_declaration = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_throws_clause_in_constructor_declaration = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_throws_clause_in_method_declaration = Alignment.M_COMPACT_SPLIT;
 		this.align_type_members_on_columns = false;
+		this.brace_position_for_annotation_type_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_anonymous_type_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_array_initializer = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_block = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_block_in_case = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_constructor_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
+		this.brace_position_for_enum_constant = DefaultCodeFormatterConstants.END_OF_LINE;
+		this.brace_position_for_enum_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_method_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_type_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_switch = DefaultCodeFormatterConstants.END_OF_LINE;
@@ -1533,11 +1953,14 @@
 		this.blank_lines_at_beginning_of_method_body = 0;
 		this.indent_statements_compare_to_block = true;
 		this.indent_statements_compare_to_body = true;
+		this.indent_body_declarations_compare_to_enum_constant_header = true;
+		this.indent_body_declarations_compare_to_enum_declaration_header = true;
 		this.indent_body_declarations_compare_to_type_header = true;
 		this.indent_breaks_compare_to_cases = true;
 		this.indent_switchstatements_compare_to_cases = true;
 		this.indent_switchstatements_compare_to_switch = false;
 		this.insert_new_line_after_opening_brace_in_array_initializer = false;
+		this.insert_new_line_at_end_of_file_if_missing = false;
 		this.insert_new_line_before_catch_in_try_statement = false;
 		this.insert_new_line_before_closing_brace_in_array_initializer = false;
 		this.insert_new_line_before_else_in_if_statement = false;
@@ -1545,20 +1968,31 @@
 		this.insert_new_line_before_while_in_do_statement = false;
 		this.insert_new_line_in_empty_anonymous_type_declaration = true;
 		this.insert_new_line_in_empty_block = true;
+		this.insert_new_line_in_empty_enum_constant = true;
+		this.insert_new_line_in_empty_enum_declaration = true;
 		this.insert_new_line_in_empty_method_body = true;
 		this.insert_new_line_in_empty_type_declaration = true;
+		this.insert_space_after_and_in_type_parameter = true;
 		this.insert_space_after_assignment_operator = true;
+		this.insert_space_after_at_in_annotation = false;
+		this.insert_space_after_at_in_annotation_type_declaration = false;
 		this.insert_space_after_binary_operator = true;
+		this.insert_space_after_closing_angle_bracket_in_type_arguments = true;
+		this.insert_space_after_closing_angle_bracket_in_type_parameters = true;
 		this.insert_space_after_closing_paren_in_cast = true;
 		this.insert_space_after_closing_brace_in_block = true;
 		this.insert_space_after_colon_in_assert = true;
 		this.insert_space_after_colon_in_case = true;
 		this.insert_space_after_colon_in_conditional = true;
+		this.insert_space_after_colon_in_for = true;
 		this.insert_space_after_colon_in_labeled_statement = true;
 		this.insert_space_after_comma_in_allocation_expression = true;
+		this.insert_space_after_comma_in_annotation = true;
 		this.insert_space_after_comma_in_array_initializer = true;
 		this.insert_space_after_comma_in_constructor_declaration_parameters = true;
 		this.insert_space_after_comma_in_constructor_declaration_throws = true;
+		this.insert_space_after_comma_in_enum_constant_arguments = true;
+		this.insert_space_after_comma_in_enum_declarations = true;
 		this.insert_space_after_comma_in_explicit_constructor_call_arguments = true;
 		this.insert_space_after_comma_in_for_increments = true;
 		this.insert_space_after_comma_in_for_inits = true;
@@ -1567,13 +2001,22 @@
 		this.insert_space_after_comma_in_method_declaration_throws = true;
 		this.insert_space_after_comma_in_multiple_field_declarations = true;
 		this.insert_space_after_comma_in_multiple_local_declarations = true;
+		this.insert_space_after_comma_in_parameterized_type_reference = true;
 		this.insert_space_after_comma_in_superinterfaces = true;
+		this.insert_space_after_comma_in_type_arguments = true;
+		this.insert_space_after_comma_in_type_parameters = true;
+		this.insert_space_after_ellipsis = true;
+		this.insert_space_after_opening_angle_bracket_in_parameterized_type_reference = false;
+		this.insert_space_after_opening_angle_bracket_in_type_arguments = false;
+		this.insert_space_after_opening_angle_bracket_in_type_parameters = false;
 		this.insert_space_after_opening_bracket_in_array_allocation_expression = false;
 		this.insert_space_after_opening_bracket_in_array_reference = false;
 		this.insert_space_after_opening_brace_in_array_initializer = true;
+		this.insert_space_after_opening_paren_in_annotation = false;
 		this.insert_space_after_opening_paren_in_cast = false;
 		this.insert_space_after_opening_paren_in_catch = false;
 		this.insert_space_after_opening_paren_in_constructor_declaration = false;
+		this.insert_space_after_opening_paren_in_enum_constant = false;
 		this.insert_space_after_opening_paren_in_for = false;
 		this.insert_space_after_opening_paren_in_if = false;
 		this.insert_space_after_opening_paren_in_method_declaration = false;
@@ -1585,16 +2028,24 @@
 		this.insert_space_after_postfix_operator = false;
 		this.insert_space_after_prefix_operator = false;
 		this.insert_space_after_question_in_conditional = true;
+		this.insert_space_after_question_in_wilcard = false;
 		this.insert_space_after_semicolon_in_for = true;
 		this.insert_space_after_unary_operator = false;
+		this.insert_space_before_and_in_type_parameter = true;
+		this.insert_space_before_at_in_annotation_type_declaration = true;
 		this.insert_space_before_assignment_operator = true;
 		this.insert_space_before_binary_operator = true;
+		this.insert_space_before_closing_angle_bracket_in_parameterized_type_reference = false;
+		this.insert_space_before_closing_angle_bracket_in_type_arguments = false;
+		this.insert_space_before_closing_angle_bracket_in_type_parameters = false;
 		this.insert_space_before_closing_brace_in_array_initializer = true;
 		this.insert_space_before_closing_bracket_in_array_allocation_expression = false;
 		this.insert_space_before_closing_bracket_in_array_reference = false;
+		this.insert_space_before_closing_paren_in_annotation = false;
 		this.insert_space_before_closing_paren_in_cast = false;
 		this.insert_space_before_closing_paren_in_catch = false;
 		this.insert_space_before_closing_paren_in_constructor_declaration = false;
+		this.insert_space_before_closing_paren_in_enum_constant = false;
 		this.insert_space_before_closing_paren_in_for = false;
 		this.insert_space_before_closing_paren_in_if = false;
 		this.insert_space_before_closing_paren_in_method_declaration = false;
@@ -1607,11 +2058,14 @@
 		this.insert_space_before_colon_in_case = false;
 		this.insert_space_before_colon_in_conditional = true;
 		this.insert_space_before_colon_in_default = false;
+		this.insert_space_before_colon_in_for = true;
 		this.insert_space_before_colon_in_labeled_statement = false;
 		this.insert_space_before_comma_in_allocation_expression = false;
 		this.insert_space_before_comma_in_array_initializer = false;
 		this.insert_space_before_comma_in_constructor_declaration_parameters = false;
 		this.insert_space_before_comma_in_constructor_declaration_throws = false;
+		this.insert_space_before_comma_in_enum_constant_arguments = false;
+		this.insert_space_before_comma_in_enum_declarations = false;
 		this.insert_space_before_comma_in_explicit_constructor_call_arguments = false;
 		this.insert_space_before_comma_in_for_increments = false;
 		this.insert_space_before_comma_in_for_inits = false;
@@ -1620,19 +2074,32 @@
 		this.insert_space_before_comma_in_method_declaration_throws = false;
 		this.insert_space_before_comma_in_multiple_field_declarations = false;
 		this.insert_space_before_comma_in_multiple_local_declarations = false;
+		this.insert_space_before_comma_in_parameterized_type_reference = false;
 		this.insert_space_before_comma_in_superinterfaces = false;
+		this.insert_space_before_comma_in_type_arguments = false;
+		this.insert_space_before_comma_in_type_parameters = false;
+		this.insert_space_before_ellipsis = false;
+		this.insert_space_before_opening_angle_bracket_in_parameterized_type_reference = false;
+		this.insert_space_before_opening_angle_bracket_in_type_arguments = false;
+		this.insert_space_before_opening_angle_bracket_in_type_parameters = false;
+		this.insert_space_before_opening_brace_in_annotation_type_declaration = true;
 		this.insert_space_before_opening_brace_in_anonymous_type_declaration = true;
 		this.insert_space_before_opening_brace_in_array_initializer = true;
 		this.insert_space_before_opening_brace_in_block = true;
 		this.insert_space_before_opening_brace_in_constructor_declaration = true;
+		this.insert_space_before_opening_brace_in_enum_constant = true;
+		this.insert_space_before_opening_brace_in_enum_declaration = true;
 		this.insert_space_before_opening_brace_in_method_declaration = true;
 		this.insert_space_before_opening_brace_in_switch = true;
 		this.insert_space_before_opening_brace_in_type_declaration = true;
 		this.insert_space_before_opening_bracket_in_array_allocation_expression = false;
 		this.insert_space_before_opening_bracket_in_array_reference = false;
 		this.insert_space_before_opening_bracket_in_array_type_reference = false;
+		this.insert_space_before_opening_paren_in_annotation = false;
+		this.insert_space_before_opening_paren_in_annotation_type_member_declaration = false;
 		this.insert_space_before_opening_paren_in_catch = true;
 		this.insert_space_before_opening_paren_in_constructor_declaration = false;
+		this.insert_space_before_opening_paren_in_enum_constant = false;
 		this.insert_space_before_opening_paren_in_for = true;
 		this.insert_space_before_opening_paren_in_if = true;
 		this.insert_space_before_opening_paren_in_method_invocation = false;
@@ -1644,13 +2111,16 @@
 		this.insert_space_before_postfix_operator = false;
 		this.insert_space_before_prefix_operator = false;
 		this.insert_space_before_question_in_conditional = true;
+		this.insert_space_before_question_in_wilcard = false;
 		this.insert_space_before_semicolon = false;
 		this.insert_space_before_semicolon_in_for = false;
 		this.insert_space_before_unary_operator = false;
 		this.insert_space_between_brackets_in_array_type_reference = false;
 		this.insert_space_between_empty_braces_in_array_initializer = false;
 		this.insert_space_between_empty_brackets_in_array_allocation_expression = false;
+		this.insert_space_between_empty_parens_in_annotation_type_member_declaration = false;
 		this.insert_space_between_empty_parens_in_constructor_declaration = false;
+		this.insert_space_between_empty_parens_in_enum_constant = false;
 		this.insert_space_between_empty_parens_in_method_declaration = false;
 		this.insert_space_between_empty_parens_in_method_invocation = false;
 		this.compact_else_if = true;
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Scribe.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Scribe.java
index b951deb..8fc3e41 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Scribe.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Scribe.java
@@ -15,7 +15,10 @@
 
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
 import org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil;
@@ -72,12 +75,14 @@
 
 	Scribe(CodeFormatterVisitor formatter, Map settings, int offset, int length, CodeSnippetParsingUtil codeSnippetParsingUtil) {
 		if (settings != null) {
-			Object assertModeSetting = settings.get(JavaCore.COMPILER_SOURCE);
-			if (assertModeSetting != null) {
-				this.scanner = new Scanner(true, true, false/*nls*/, JavaCore.VERSION_1_4.equals(assertModeSetting) ? ClassFileConstants.JDK1_4 : ClassFileConstants.JDK1_3/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
-			} else {
-				this.scanner = new Scanner(true, true, false/*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
+			Object sourceLevelOption = settings.get(JavaCore.COMPILER_SOURCE);
+			long sourceLevel = ClassFileConstants.JDK1_3;
+			if (JavaCore.VERSION_1_4.equals(sourceLevelOption)) {
+				sourceLevel = ClassFileConstants.JDK1_4;
+			} else if (JavaCore.VERSION_1_5.equals(sourceLevelOption)) {
+				sourceLevel = ClassFileConstants.JDK1_5;
 			}
+			this.scanner = new Scanner(true, true, false/*nls*/, sourceLevel/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
 		} else {
 			this.scanner = new Scanner(true, true, false/*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
 		}
@@ -644,6 +649,8 @@
 			}
 		} else if (this.textRegionStart <= editOffset && editOffset <= this.textRegionEnd) {
 			return true;
+		} else if (editOffset == this.scannerEndPosition && editOffset == this.textRegionEnd + 1) {
+			return true;
 		}
 		return false;
 	}
@@ -748,6 +755,123 @@
 			printNewLine();
 		}
 	}
+	
+	public void printEndOfCompilationUnit() {
+		try {
+			// if we have a space between two tokens we ensure it will be dumped in the formatted string
+			int currentTokenStartPosition = this.scanner.currentPosition;
+			boolean hasComment = false;
+			boolean hasLineComment = false;
+			boolean hasWhitespace = false;
+			int count = 0;
+			while (true) {
+				this.currentToken = this.scanner.getNextToken();
+				switch(this.currentToken) {
+					case TerminalTokens.TokenNameWHITESPACE :
+						char[] whiteSpaces = this.scanner.getCurrentTokenSource();
+						count = 0;
+						for (int i = 0, max = whiteSpaces.length; i < max; i++) {
+							switch(whiteSpaces[i]) {
+								case '\r' :
+									if ((i + 1) < max) {
+										if (whiteSpaces[i + 1] == '\n') {
+											i++;
+										}
+									}
+									count++;
+									break;
+								case '\n' :
+									count++;
+							}
+						}
+						if (count == 0) {
+							hasWhitespace = true;
+							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
+						} else if (hasComment) {
+							if (count == 1) {
+								this.printNewLine(this.scanner.getCurrentTokenStartPosition());
+							} else {
+								preserveEmptyLines(count - 1, this.scanner.getCurrentTokenStartPosition());
+							}
+							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
+						} else if (hasLineComment) {
+							this.preserveEmptyLines(count, this.scanner.getCurrentTokenStartPosition());
+							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
+						} else {
+							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
+						}
+						currentTokenStartPosition = this.scanner.currentPosition;						
+						break;
+					case TerminalTokens.TokenNameCOMMENT_LINE :
+						if (count >= 1) {
+							if (count > 1) {
+								preserveEmptyLines(count - 1, this.scanner.getCurrentTokenStartPosition());
+							} else if (count == 1) {
+								printNewLine(this.scanner.getCurrentTokenStartPosition());
+							}
+						} else if (hasWhitespace) {
+							space();
+						} 
+						hasWhitespace = false;
+						this.printCommentLine(this.scanner.getRawTokenSource());
+						currentTokenStartPosition = this.scanner.currentPosition;
+						hasLineComment = true;		
+						count = 0;
+						break;
+					case TerminalTokens.TokenNameCOMMENT_BLOCK :
+						if (count >= 1) {
+							if (count > 1) {
+								preserveEmptyLines(count - 1, this.scanner.getCurrentTokenStartPosition());
+							} else if (count == 1) {
+								printNewLine(this.scanner.getCurrentTokenStartPosition());
+							}
+						} else if (hasWhitespace) {
+							space();
+						} 
+						hasWhitespace = false;
+						this.printBlockComment(this.scanner.getRawTokenSource(), false);
+						currentTokenStartPosition = this.scanner.currentPosition;
+						hasLineComment = false;
+						hasComment = true;
+						count = 0;
+						break;
+					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+						if (count >= 1) {
+							if (count > 1) {
+								preserveEmptyLines(count - 1, this.scanner.getCurrentTokenStartPosition());
+							} else if (count == 1) {
+								printNewLine(this.scanner.getCurrentTokenStartPosition());
+							}
+						} else if (hasWhitespace) {
+							space();
+						} 
+						hasWhitespace = false;
+						this.printBlockComment(this.scanner.getRawTokenSource(), true);
+						currentTokenStartPosition = this.scanner.currentPosition;
+						hasLineComment = false;
+						hasComment = true;
+						count = 0;
+						break;
+					case TerminalTokens.TokenNameSEMICOLON :
+						char[] currentTokenSource = this.scanner.getRawTokenSource();
+						this.print(currentTokenSource, this.formatter.preferences.insert_space_before_semicolon);
+						break;
+					case TerminalTokens.TokenNameEOF :
+						if (count >= 1 || this.formatter.preferences.insert_new_line_at_end_of_file_if_missing) {
+							this.printNewLine(this.scannerEndPosition);
+						}
+						return;
+					default :
+						// step back one token
+						this.scanner.resetTo(currentTokenStartPosition, this.scannerEndPosition - 1);
+						return;
+				}
+			}
+		} catch (InvalidInputException e) {
+			throw new AbortFormatting(e);
+		}
+	}
+
 	public void printComment() {
 		try {
 			// if we have a space between two tokens we ensure it will be dumped in the formatted string
@@ -986,8 +1110,10 @@
 		}
 	}
 
-	public void printModifiers() {
+	public void printModifiers(Annotation[] annotations, ASTVisitor visitor) {
 		try {
+			int annotationsLength = annotations != null ? annotations.length : 0;
+			int annotationsIndex = 0;
 			boolean isFirstModifier = true;
 			int currentTokenStartPosition = this.scanner.currentPosition;
 			boolean hasComment = false;
@@ -1003,10 +1129,24 @@
 					case TerminalTokens.TokenNamesynchronized :
 					case TerminalTokens.TokenNametransient :
 					case TerminalTokens.TokenNamevolatile :
+					case TerminalTokens.TokenNamestrictfp :
 						this.print(this.scanner.getRawTokenSource(), !isFirstModifier);
 						isFirstModifier = false;
 						currentTokenStartPosition = this.scanner.getCurrentTokenStartPosition();
 						break;
+					case TerminalTokens.TokenNameAT :
+						if (!isFirstModifier) {
+							this.space();
+						}
+						this.scanner.resetTo(this.scanner.getCurrentTokenStartPosition(), this.scannerEndPosition - 1);
+						if (annotationsIndex < annotationsLength) {
+							annotations[annotationsIndex++].traverse(visitor, (BlockScope) null);
+						} else {
+							return;
+						}
+						isFirstModifier = false;
+						currentTokenStartPosition = this.scanner.currentPosition;
+						break;
 					case TerminalTokens.TokenNameCOMMENT_BLOCK :
 						this.printBlockComment(this.scanner.getRawTokenSource(), false);
 						currentTokenStartPosition = this.scanner.currentPosition;
@@ -1104,7 +1244,11 @@
 		}
 	}
 
-	public void printNextToken(int[] expectedTokenTypes){
+	public void printNextToken(int[] expectedTokenTypes) {
+		printNextToken(expectedTokenTypes, false);
+	}
+
+	public void printNextToken(int[] expectedTokenTypes, boolean considerSpaceIfAny){
 		printComment();
 		try {
 			this.currentToken = this.scanner.getNextToken();
@@ -1119,7 +1263,7 @@
 				}				
 				throw new AbortFormatting("unexpected token type, expecting:["+expectations.toString()+"], actual:"+this.currentToken);//$NON-NLS-1$//$NON-NLS-2$
 			}
-			this.print(currentTokenSource, false);
+			this.print(currentTokenSource, considerSpaceIfAny);
 		} catch (InvalidInputException e) {
 			throw new AbortFormatting(e);
 		}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/align/Alignment.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/align/Alignment.java
index fc6eb3e..a43ceb9 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/align/Alignment.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/align/Alignment.java
@@ -129,7 +129,7 @@
 	public static final int CHUNK_FIELD = 1;
 	public static final int CHUNK_METHOD = 2;
 	public static final int CHUNK_TYPE = 3;
-
+	public static final int CHUNK_ENUM = 4;
 
 	// location to align and break on.
 	public Alignment(String name, int mode, int tieBreakRule, Scribe scribe, int fragmentCount, int sourceRestart, int continuationIndent){
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/align/AlignmentException.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/align/AlignmentException.java
index bd62945..27759b5 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/align/AlignmentException.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/align/AlignmentException.java
@@ -20,6 +20,7 @@
 	
 	public static final int LINE_TOO_LONG = 1;
 	public static final int ALIGN_TOO_SMALL = 2;
+	private static final long serialVersionUID = -3324134986466253314L; // backward compatible
 	
 	int reason;
 	int value;
diff --git a/org.eclipse.jdt.core/grammar/java_1_5.g b/org.eclipse.jdt.core/grammar/java_1_5.g
index 89c165b..a0f100c 100644
--- a/org.eclipse.jdt.core/grammar/java_1_5.g
+++ b/org.eclipse.jdt.core/grammar/java_1_5.g
@@ -28,8 +28,11 @@
 

 

 $readableName 

-/.$rule_number=./

-

+/.1#$rule_number=./

+$compliance

+/.2#$rule_number=./

+$recovery

+/.2#$rule_number= recovery./

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

 $Terminals

 

@@ -171,7 +174,8 @@
 Goal ::= '>>' Initializer

 -- error recovery

 -- Modifiersopt is used to properly consume a header and exit the rule reduction at the end of the parse() method

-Goal ::= '>>>' Header Modifiersopt

+Goal ::= '>>>' Header1 Modifiersopt

+Goal ::= '!' Header2 Modifiersopt

 Goal ::= '*' BlockStatements

 Goal ::= '*' CatchHeader

 -- JDOM

@@ -185,6 +189,10 @@
 Goal ::= '%' Expression

 -- completion parser

 Goal ::= '~' BlockStatementsopt

+-- source type converter

+Goal ::= '||' MemberValue

+-- syntax diagnosis

+Goal ::= '?' AnnotationTypeMemberDeclaration

 /:$readableName Goal:/

 

 Literal -> IntegerLiteral

@@ -232,15 +240,19 @@
 -- 1.5 feature

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

 ClassOrInterfaceType -> ClassOrInterface

-ClassOrInterfaceType -> ClassOrInterface TypeArguments

+ClassOrInterfaceType -> GenericType

 /:$readableName Type:/

 

 ClassOrInterface ::= Name

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

-ClassOrInterface ::= ClassOrInterface TypeArguments '.' Name

+ClassOrInterface ::= GenericType '.' Name

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

 /:$readableName Type:/

 

+GenericType ::= ClassOrInterface TypeArguments

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

+/:$readableName GenericType:/

+

 --

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

 -- by adding the 1.1 features

@@ -250,7 +262,7 @@
 -- ArrayType ::= ArrayType '[' ']'

 --

 

-ArrayTypeWithTypeArgumentsName ::= ClassOrInterface TypeArguments '.' Name

+ArrayTypeWithTypeArgumentsName ::= GenericType '.' Name

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

 /:$readableName ArrayTypeWithTypeArgumentsName:/

 

@@ -260,7 +272,7 @@
 /.$putCase consumeNameArrayType();  $break ./

 ArrayType ::= ArrayTypeWithTypeArgumentsName Dims

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

-ArrayType ::= ClassOrInterface TypeArguments Dims

+ArrayType ::= GenericType Dims

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

 /:$readableName ArrayType:/

 

@@ -281,10 +293,32 @@
 /.$putCase consumeQualifiedName(); $break ./

 /:$readableName QualifiedName:/

 

-CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt TypeDeclarationsopt

+CompilationUnit ::= EnterCompilationUnit InternalCompilationUnit

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

 /:$readableName CompilationUnit:/

 

+InternalCompilationUnit ::= PackageDeclaration

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

+InternalCompilationUnit ::= PackageDeclaration ImportDeclarations ReduceImports

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

+InternalCompilationUnit ::= PackageDeclaration ImportDeclarations ReduceImports TypeDeclarations

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

+InternalCompilationUnit ::= PackageDeclaration TypeDeclarations

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

+InternalCompilationUnit ::= ImportDeclarations ReduceImports

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

+InternalCompilationUnit ::= TypeDeclarations

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

+InternalCompilationUnit ::= ImportDeclarations ReduceImports TypeDeclarations

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

+InternalCompilationUnit ::= $empty

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

+/:$readableName CompilationUnit:/

+

+ReduceImports ::= $empty

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

+/:$readableName ReduceImports:/

+

 EnterCompilationUnit ::= $empty

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

 /:$readableName EnterCompilationUnit:/

@@ -293,14 +327,23 @@
 Header -> PackageDeclaration

 Header -> ClassHeader

 Header -> InterfaceHeader

+Header -> EnumHeader

+Header -> AnnotationTypeDeclarationHeader

 Header -> StaticInitializer

-Header -> MethodHeader

-Header -> ConstructorHeader

+Header -> RecoveryMethodHeader

 Header -> FieldDeclaration

 Header -> AllocationHeader

 Header -> ArrayCreationHeader

 /:$readableName Header:/

 

+Header1 -> Header

+Header1 -> ConstructorHeader

+/:$readableName Header1:/

+

+Header2 -> Header

+Header2 -> EnumConstantHeader

+/:$readableName Header2:/

+

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

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

 /:$readableName CatchHeader:/

@@ -319,6 +362,11 @@
 /.$putCase  consumePackageDeclaration(); $break ./

 /:$readableName PackageDeclaration:/

 

+PackageDeclarationName ::= Modifiers 'package' PushRealModifiers Name

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

+/:$readableName PackageDeclarationName:/

+/:$compliance 1.5:/

+

 PackageDeclarationName ::= 'package' Name

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

 /:$readableName PackageDeclarationName:/

@@ -364,8 +412,9 @@
 

 --18.7 Only in the LALR(1) Grammar

 

-Modifiers ::= Modifier

+Modifiers -> Modifier

 Modifiers ::= Modifiers Modifier

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

 /:$readableName Modifiers:/

 

 Modifier -> 'public' 

@@ -379,7 +428,8 @@
 Modifier -> 'transient'

 Modifier -> 'volatile'

 Modifier -> 'strictfp'

-Modifier -> Annotation

+Modifier ::= Annotation

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

 /:$readableName Modifier:/

 

 --18.8 Productions from 8: Class Declarations

@@ -400,10 +450,14 @@
 -----------------------------------------------

 -- 1.5 features : generics

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

-ClassHeaderName ::= Modifiersopt 'class' 'Identifier' TypeParameters

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

-ClassHeaderName ::= Modifiersopt 'class' 'Identifier'

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

+ClassHeaderName ::= ClassHeaderName1 TypeParameters

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

+

+ClassHeaderName -> ClassHeaderName1

+/:$readableName ClassHeaderName:/

+

+ClassHeaderName1 ::= Modifiersopt 'class' 'Identifier'

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

 /:$readableName ClassHeaderName:/

 

 ClassHeaderExtends ::= 'extends' ClassType

@@ -455,19 +509,20 @@
 ClassMemberDeclaration -> InterfaceDeclaration

 -- 1.5 feature

 ClassMemberDeclaration -> EnumDeclaration

+ClassMemberDeclaration -> AnnotationTypeDeclaration

 /:$readableName ClassMemberDeclaration:/

 

 -- Empty declarations are not valid Java ClassMemberDeclarations.

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

 -- (in fact, some of the official tests contain this erroneous

 -- syntax)

+ClassMemberDeclaration ::= ';'

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

+

 GenericMethodDeclaration -> MethodDeclaration

 GenericMethodDeclaration -> ConstructorDeclaration

 /:$readableName GenericMethodDeclaration:/

 

-ClassMemberDeclaration ::= ';'

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

-

 --18.8.2 Productions from 8.3: Field Declarations

 --VariableModifier ::=

 --      'public'

@@ -538,16 +593,16 @@
 AbstractMethodDeclaration ::= MethodHeader ';'

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

   consumeMethodDeclaration(false); $break ./

-/:$readableName AbstractMethodDeclaration:/

+/:$readableName MethodDeclaration:/

 

 MethodHeader ::= MethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims MethodHeaderThrowsClauseopt

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

 /:$readableName MethodDeclaration:/

 

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

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

+/.$putCase consumeMethodHeaderNameWithTypeParameters(false); $break ./

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

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

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

 /:$readableName MethodHeaderName:/

 

 MethodHeaderRightParen ::= ')'

@@ -583,6 +638,7 @@
 FormalParameter ::= Modifiersopt Type '...' VariableDeclaratorId

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

 /:$readableName FormalParameter:/

+/:$compliance 1.5:/

 

 ClassTypeList -> ClassTypeElt

 ClassTypeList ::= ClassTypeList ',' ClassTypeElt

@@ -629,46 +685,44 @@
 -- in the rule below in order to make the grammar lalr(1).

 

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

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

+/.$putCase consumeExplicitConstructorInvocation(0, THIS_CALL); $break ./

 

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

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

+/.$putCase consumeExplicitConstructorInvocationWithTypeArguments(0,THIS_CALL); $break ./

 

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

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

+/.$putCase consumeExplicitConstructorInvocation(0,SUPER_CALL); $break ./

 

 ExplicitConstructorInvocation ::= OnlyTypeArguments 'super' '(' ArgumentListopt ')' ';'

-/.$putCase consumeExplicitConstructorInvocationWithTypeArguments(0,ExplicitConstructorCall.Super); $break ./

+/.$putCase consumeExplicitConstructorInvocationWithTypeArguments(0,SUPER_CALL); $break ./

 

 --1.1 feature

 ExplicitConstructorInvocation ::= Primary '.' 'super' '(' ArgumentListopt ')' ';'

-/.$putCase consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.Super); $break ./

+/.$putCase consumeExplicitConstructorInvocation(1, SUPER_CALL); $break ./

 

 ExplicitConstructorInvocation ::= Primary '.' OnlyTypeArguments 'super' '(' ArgumentListopt ')' ';'

-/.$putCase consumeExplicitConstructorInvocationWithTypeArguments(1, ExplicitConstructorCall.Super); $break ./

+/.$putCase consumeExplicitConstructorInvocationWithTypeArguments(1, SUPER_CALL); $break ./

 

 --1.1 feature

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

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

+/.$putCase consumeExplicitConstructorInvocation(2, SUPER_CALL); $break ./

 

 ExplicitConstructorInvocation ::= Name '.' OnlyTypeArguments 'super' '(' ArgumentListopt ')' ';'

-/.$putCase consumeExplicitConstructorInvocationWithTypeArguments(2, ExplicitConstructorCall.Super); $break ./

+/.$putCase consumeExplicitConstructorInvocationWithTypeArguments(2, SUPER_CALL); $break ./

 

 --1.1 feature

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

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

+/.$putCase consumeExplicitConstructorInvocation(1, THIS_CALL); $break ./

 

 ExplicitConstructorInvocation ::= Primary '.' OnlyTypeArguments 'this' '(' ArgumentListopt ')' ';'

-/.$putCase consumeExplicitConstructorInvocationWithTypeArguments(1, ExplicitConstructorCall.This); $break ./

+/.$putCase consumeExplicitConstructorInvocationWithTypeArguments(1, THIS_CALL); $break ./

 

 --1.1 feature

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

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

+/.$putCase consumeExplicitConstructorInvocation(2, THIS_CALL); $break ./

 

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

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

-/:$readableName ExplicitConstructorInvocation:/

-

+/.$putCase consumeExplicitConstructorInvocationWithTypeArguments(2, THIS_CALL); $break ./

 /:$readableName ExplicitConstructorInvocation:/

 

 --18.9 Productions from 9: Interface Declarations

@@ -689,10 +743,14 @@
 -----------------------------------------------

 -- 1.5 features : generics

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

-InterfaceHeaderName ::= Modifiersopt interface Identifier TypeParameters

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

-InterfaceHeaderName ::= Modifiersopt interface Identifier

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

+InterfaceHeaderName ::= InterfaceHeaderName1 TypeParameters

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

+

+InterfaceHeaderName -> InterfaceHeaderName1

+/:$readableName InterfaceHeaderName:/

+

+InterfaceHeaderName1 ::= Modifiersopt interface Identifier

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

 /:$readableName InterfaceHeaderName:/

 

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

@@ -738,16 +796,22 @@
 InterfaceMemberDeclaration -> ClassDeclaration

 --1.1 feature

 InterfaceMemberDeclaration -> InterfaceDeclaration

+InterfaceMemberDeclaration -> EnumDeclaration

+InterfaceMemberDeclaration -> AnnotationTypeDeclaration

 /:$readableName InterfaceMemberDeclaration:/

 

 ConstantDeclaration -> FieldDeclaration

 /:$readableName ConstantDeclaration:/

 

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

+PushLeftBrace ::= $empty

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

+/:$readableName PushLeftBrace:/

+

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

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

-ArrayInitializer ::= '{' VariableInitializers '}'

+ArrayInitializer ::= '{' PushLeftBrace VariableInitializers '}'

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

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

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

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

 /:$readableName ArrayInitializer:/

 

@@ -787,7 +851,7 @@
 -- The modifiers part of this rule makes the grammar more permissive. 

 -- The only modifier here is final. We put Modifiers to allow multiple modifiers

 -- This will require to check the validity of the modifier

-LocalVariableDeclaration ::= Modifiers Type PushModifiers VariableDeclarators

+LocalVariableDeclaration ::= Modifiers Type PushRealModifiers VariableDeclarators

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

 /:$readableName LocalVariableDeclaration:/

 

@@ -795,6 +859,14 @@
 /.$putCase consumePushModifiers(); $break ./

 /:$readableName PushModifiers:/

 

+PushModifiersForHeader ::= $empty

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

+/:$readableName PushModifiersForHeader:/

+

+PushRealModifiers ::= $empty

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

+/:$readableName PushRealModifiers:/

+

 Statement -> StatementWithoutTrailingSubstatement

 Statement -> LabeledStatement

 Statement -> IfThenStatement

@@ -941,10 +1013,12 @@
 -- 1.4 feature

 AssertStatement ::= 'assert' Expression ';'

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

+/:$compliance 1.4:/

 

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

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

 /:$readableName AssertStatement:/

+/:$compliance 1.4:/

 

 BreakStatement ::= 'break' ';'

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

@@ -1071,18 +1145,18 @@
 /.$putCase consumeClassInstanceCreationExpression(); $break ./

 --1.1 feature

 

-ClassInstanceCreationExpression ::= Primary '.' 'new' OnlyTypeArguments SimpleName '(' ArgumentListopt ')' ClassBodySimpleNameopt

+ClassInstanceCreationExpression ::= Primary '.' 'new' OnlyTypeArguments ClassType '(' ArgumentListopt ')' ClassBodySimpleNameopt

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

 

-ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodySimpleNameopt

+ClassInstanceCreationExpression ::= Primary '.' 'new' ClassType '(' ArgumentListopt ')' ClassBodySimpleNameopt

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

 

 --1.1 feature

-ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' SimpleName '(' ArgumentListopt ')' ClassBodySimpleNameopt

+ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' ClassType '(' ArgumentListopt ')' ClassBodySimpleNameopt

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

 /:$readableName ClassInstanceCreationExpression:/

 

-ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' OnlyTypeArguments SimpleName '(' ArgumentListopt ')' ClassBodySimpleNameopt

+ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' OnlyTypeArguments ClassType '(' ArgumentListopt ')' ClassBodySimpleNameopt

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

 /:$readableName ClassInstanceCreationExpression:/

 

@@ -1236,13 +1310,9 @@
 

 CastExpression ::= PushLPAREN PrimitiveType Dimsopt PushRPAREN InsideCastExpression UnaryExpression

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

-CastExpression ::= PushLPAREN Name OnlyTypeArguments Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus

+CastExpression ::= PushLPAREN Name OnlyTypeArgumentsForCastExpression Dimsopt PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus

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

-CastExpression ::= PushLPAREN Name OnlyTypeArguments PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus

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

-CastExpression ::= PushLPAREN Name OnlyTypeArguments '.' ClassOrInterfaceType PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus

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

-CastExpression ::= PushLPAREN Name OnlyTypeArguments '.' ClassOrInterfaceType Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus

+CastExpression ::= PushLPAREN Name OnlyTypeArgumentsForCastExpression '.' ClassOrInterfaceType Dimsopt PushRPAREN InsideCastExpressionWithQualifiedGenerics UnaryExpressionNotPlusMinus

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

 CastExpression ::= PushLPAREN Name PushRPAREN InsideCastExpressionLL1 UnaryExpressionNotPlusMinus

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

@@ -1250,12 +1320,19 @@
 /.$putCase consumeCastExpressionWithNameArray(); $break ./

 /:$readableName CastExpression:/

 

+OnlyTypeArgumentsForCastExpression ::= OnlyTypeArguments

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

+/:$readableName TypeArguments:/

+

 InsideCastExpression ::= $empty

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

 /:$readableName InsideCastExpression:/

 InsideCastExpressionLL1 ::= $empty

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

 /:$readableName InsideCastExpression:/

+InsideCastExpressionWithQualifiedGenerics ::= $empty

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

+/:$readableName InsideCastExpression:/

 

 MultiplicativeExpression -> UnaryExpression

 MultiplicativeExpression ::= MultiplicativeExpression '*' UnaryExpression

@@ -1380,11 +1457,6 @@
 

 -- The following rules are for optional nonterminals.

 --

-

-PackageDeclarationopt -> $empty 

-PackageDeclarationopt -> PackageDeclaration

-/:$readableName PackageDeclaration:/

-

 ClassHeaderExtendsopt ::= $empty

 ClassHeaderExtendsopt -> ClassHeaderExtends

 /:$readableName ClassHeaderExtends:/

@@ -1413,18 +1485,6 @@
 ,opt -> ,

 /:$readableName ,:/

 

-ImportDeclarationsopt ::= $empty

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

-ImportDeclarationsopt ::= ImportDeclarations

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

-/:$readableName ImportDeclarations:/

-

-TypeDeclarationsopt ::= $empty

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

-TypeDeclarationsopt ::= TypeDeclarations

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

-/:$readableName TypeDeclarations:/

-

 ClassBodyDeclarationsopt ::= $empty

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

 ClassBodyDeclarationsopt ::= NestedType ClassBodyDeclarations

@@ -1433,7 +1493,7 @@
 

 Modifiersopt ::= $empty 

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

-Modifiersopt ::= Modifiers 

+Modifiersopt ::= Modifiers

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

 /:$readableName Modifiers:/

 

@@ -1497,14 +1557,19 @@
 -----------------------------------------------

 -- 1.5 features : enum type

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

-EnumDeclaration ::= EnumHeader ClassHeaderImplementsopt EnumBody

+EnumDeclaration ::= EnumHeader EnumBody

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

 /:$readableName EnumDeclaration:/

 

-EnumHeader ::= Modifiersopt 'enum' Identifier

+EnumHeader ::= EnumHeaderName ClassHeaderImplementsopt

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

 /:$readableName EnumHeader:/

 

+EnumHeaderName ::= Modifiersopt 'enum' Identifier

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

+/:$readableName EnumHeaderName:/

+/:$compliance 1.5:/

+

 EnumBody ::= '{' EnumBodyDeclarationsopt '}'

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

 EnumBody ::= '{' ',' EnumBodyDeclarationsopt '}'

@@ -1520,9 +1585,17 @@
 /.$putCase consumeEnumConstants(); $break ./

 /:$readableName EnumConstants:/

 

-EnumConstant ::= Identifier Argumentsopt ClassBody

+EnumConstantHeaderName ::= Modifiersopt Identifier

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

+/:$readableName EnumConstantHeaderName:/

+

+EnumConstantHeader ::= EnumConstantHeaderName Argumentsopt

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

+/:$readableName EnumConstantHeader:/

+

+EnumConstant ::= EnumConstantHeader ForceNoDiet ClassBody RestoreDiet

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

-EnumConstant ::= Identifier Argumentsopt

+EnumConstant ::= EnumConstantHeader

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

 /:$readableName EnumConstant:/

 

@@ -1535,7 +1608,8 @@
 Argumentsopt -> Arguments

 /:$readableName Argumentsopt:/

 

-EnumDeclarations -> ';' ClassBodyDeclarationsopt

+EnumDeclarations ::= ';' ClassBodyDeclarationsopt

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

 /:$readableName EnumDeclarations:/

 

 EnumBodyDeclarationsopt ::= $empty

@@ -1546,18 +1620,23 @@
 -----------------------------------------------

 -- 1.5 features : enhanced for statement

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

-EnhancedForStatement ::= 'for' '(' Type PushModifiers Identifier ':' Expression ')' Statement

-/.$putCase consumeEnhancedForStatement(false); $break ./

-EnhancedForStatement ::= 'for' '(' Modifiers Type PushModifiers Identifier ':' Expression ')' Statement

-/.$putCase consumeEnhancedForStatement(true); $break ./

+EnhancedForStatement ::= EnhancedForStatementHeader Statement

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

 /:$readableName EnhancedForStatement:/

 

-EnhancedForStatementNoShortIf ::= 'for' '(' Type PushModifiers Identifier ':' Expression ')' StatementNoShortIf

-/.$putCase consumeEnhancedForStatement(false); $break ./

-EnhancedForStatementNoShortIf ::= 'for' '(' Modifiers Type PushModifiers Identifier ':' Expression ')' StatementNoShortIf

-/.$putCase consumeEnhancedForStatement(true); $break ./

+EnhancedForStatementNoShortIf ::= EnhancedForStatementHeader StatementNoShortIf

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

 /:$readableName EnhancedForStatementNoShortIf:/

 

+EnhancedForStatementHeader ::= 'for' '(' Type PushModifiers Identifier Dimsopt ':' Expression ')'

+/.$putCase consumeEnhancedForStatementHeader(false); $break ./

+/:$readableName EnhancedForStatementHeader:/

+/:$compliance 1.5:/

+EnhancedForStatementHeader ::= 'for' '(' Modifiers Type PushRealModifiers Identifier Dimsopt ':' Expression ')'

+/.$putCase consumeEnhancedForStatementHeader(true); $break ./

+/:$readableName EnhancedForStatementHeader:/

+/:$compliance 1.5:/

+

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

 -- 1.5 features : static imports

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

@@ -1568,6 +1647,7 @@
 SingleStaticImportDeclarationName ::= 'import' 'static' Name

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

 /:$readableName SingleStaticImportDeclarationName:/

+/:$compliance 1.5:/

 

 StaticImportOnDemandDeclaration ::= StaticImportOnDemandDeclarationName ';'

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

@@ -1576,6 +1656,7 @@
 StaticImportOnDemandDeclarationName ::= 'import' 'static' Name '.' '*'

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

 /:$readableName StaticImportOnDemandDeclarationName:/

+/:$compliance 1.5:/

 

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

 -- 1.5 features : generics

@@ -1583,130 +1664,178 @@
 TypeArguments ::= '<' TypeArgumentList1

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

 /:$readableName TypeArguments:/

+/:$compliance 1.5:/

 

 OnlyTypeArguments ::= '<' TypeArgumentList1

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

 /:$readableName TypeArguments:/

+/:$compliance 1.5:/

 

 TypeArgumentList1 -> TypeArgument1

+/:$compliance 1.5:/

 TypeArgumentList1 ::= TypeArgumentList ',' TypeArgument1

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

 /:$readableName TypeArgumentList1:/

+/:$compliance 1.5:/

 

 TypeArgumentList -> TypeArgument

+/:$compliance 1.5:/

 TypeArgumentList ::= TypeArgumentList ',' TypeArgument

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

 /:$readableName TypeArgumentList:/

+/:$compliance 1.5:/

 

 TypeArgument ::= ReferenceType

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

+/:$compliance 1.5:/

 TypeArgument -> Wildcard

 /:$readableName TypeArgument:/

+/:$compliance 1.5:/

 

 TypeArgument1 -> ReferenceType1

+/:$compliance 1.5:/

 TypeArgument1 -> Wildcard1

 /:$readableName TypeArgument1:/

+/:$compliance 1.5:/

 

 ReferenceType1 ::= ReferenceType '>'

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

+/:$compliance 1.5:/

 ReferenceType1 ::= ClassOrInterface '<' TypeArgumentList2

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

 /:$readableName ReferenceType1:/

+/:$compliance 1.5:/

 

 TypeArgumentList2 -> TypeArgument2

+/:$compliance 1.5:/

 TypeArgumentList2 ::= TypeArgumentList ',' TypeArgument2

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

 /:$readableName TypeArgumentList2:/

+/:$compliance 1.5:/

 

 TypeArgument2 -> ReferenceType2

+/:$compliance 1.5:/

 TypeArgument2 -> Wildcard2

 /:$readableName TypeArgument2:/

+/:$compliance 1.5:/

 

 ReferenceType2 ::= ReferenceType '>>'

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

+/:$compliance 1.5:/

 ReferenceType2 ::= ClassOrInterface '<' TypeArgumentList3

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

 /:$readableName ReferenceType2:/

+/:$compliance 1.5:/

 

 TypeArgumentList3 -> TypeArgument3

 TypeArgumentList3 ::= TypeArgumentList ',' TypeArgument3

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

 /:$readableName TypeArgumentList3:/

+/:$compliance 1.5:/

 

 TypeArgument3 -> ReferenceType3

 TypeArgument3 -> Wildcard3

 /:$readableName TypeArgument3:/

+/:$compliance 1.5:/

 

 ReferenceType3 ::= ReferenceType '>>>'

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

 /:$readableName ReferenceType3:/

+/:$compliance 1.5:/

 

 Wildcard ::= '?'

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

+/:$compliance 1.5:/

 Wildcard ::= '?' WildcardBounds

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

 /:$readableName Wildcard:/

+/:$compliance 1.5:/

 

 WildcardBounds ::= 'extends' ReferenceType

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

+/:$compliance 1.5:/

 WildcardBounds ::= 'super' ReferenceType

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

 /:$readableName WildcardBounds:/

+/:$compliance 1.5:/

 

 Wildcard1 ::= '?' '>'

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

+/:$compliance 1.5:/

 Wildcard1 ::= '?' WildcardBounds1

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

 /:$readableName Wildcard1:/

+/:$compliance 1.5:/

 

 WildcardBounds1 ::= 'extends' ReferenceType1

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

+/:$compliance 1.5:/

 WildcardBounds1 ::= 'super' ReferenceType1

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

 /:$readableName WildcardBounds1:/

+/:$compliance 1.5:/

 

 Wildcard2 ::= '?' '>>'

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

+/:$compliance 1.5:/

 Wildcard2 ::= '?' WildcardBounds2

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

 /:$readableName Wildcard2:/

+/:$compliance 1.5:/

 

 WildcardBounds2 ::= 'extends' ReferenceType2

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

+/:$compliance 1.5:/

 WildcardBounds2 ::= 'super' ReferenceType2

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

 /:$readableName WildcardBounds2:/

+/:$compliance 1.5:/

 

 Wildcard3 ::= '?' '>>>'

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

+/:$compliance 1.5:/

 Wildcard3 ::= '?' WildcardBounds3

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

 /:$readableName Wildcard3:/

+/:$compliance 1.5:/

 

 WildcardBounds3 ::= 'extends' ReferenceType3

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

+/:$compliance 1.5:/

 WildcardBounds3 ::= 'super' ReferenceType3

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

 /:$readableName WildcardBound3:/

+/:$compliance 1.5:/

+

+TypeParameterHeader ::= Identifier

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

+/:$readableName TypeParameter:/

+/:$compliance 1.5:/

 

 TypeParameters ::= '<' TypeParameterList1

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

 /:$readableName TypeParameters:/

+/:$compliance 1.5:/

 

 TypeParameterList -> TypeParameter

+/:$compliance 1.5:/

 TypeParameterList ::= TypeParameterList ',' TypeParameter

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

 /:$readableName TypeParameterList:/

+/:$compliance 1.5:/

 

-TypeParameter ::= Identifier

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

-TypeParameter ::= Identifier 'extends' ReferenceType

+TypeParameter -> TypeParameterHeader

+/:$compliance 1.5:/

+TypeParameter ::= TypeParameterHeader 'extends' ReferenceType

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

-TypeParameter ::= Identifier 'extends' ReferenceType AdditionalBoundList

+/:$compliance 1.5:/

+TypeParameter ::= TypeParameterHeader 'extends' ReferenceType AdditionalBoundList

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

 /:$readableName TypeParameter:/

+/:$compliance 1.5:/

 

 AdditionalBoundList -> AdditionalBound

+/:$compliance 1.5:/

 AdditionalBoundList ::= AdditionalBoundList AdditionalBound

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

 /:$readableName AdditionalBoundList:/

@@ -1714,28 +1843,37 @@
 AdditionalBound ::= '&' ReferenceType

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

 /:$readableName AdditionalBound:/

+/:$compliance 1.5:/

 

 TypeParameterList1 -> TypeParameter1

+/:$compliance 1.5:/

 TypeParameterList1 ::= TypeParameterList ',' TypeParameter1

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

 /:$readableName TypeParameterList1:/

+/:$compliance 1.5:/

 

-TypeParameter1 ::= Identifier '>'

+TypeParameter1 ::= TypeParameterHeader '>'

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

-TypeParameter1 ::= Identifier 'extends' ReferenceType1

+/:$compliance 1.5:/

+TypeParameter1 ::= TypeParameterHeader 'extends' ReferenceType1

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

-TypeParameter1 ::= Identifier 'extends' ReferenceType AdditionalBoundList1

+/:$compliance 1.5:/

+TypeParameter1 ::= TypeParameterHeader 'extends' ReferenceType AdditionalBoundList1

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

 /:$readableName TypeParameter1:/

+/:$compliance 1.5:/

 

 AdditionalBoundList1 -> AdditionalBound1

+/:$compliance 1.5:/

 AdditionalBoundList1 ::= AdditionalBoundList AdditionalBound1

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

 /:$readableName AdditionalBoundList1:/

+/:$compliance 1.5:/

 

 AdditionalBound1 ::= '&' ReferenceType1

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

 /:$readableName AdditionalBound1:/

+/:$compliance 1.5:/

 

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

 -- Duplicate rules to remove ambiguity for (x) --

@@ -1894,99 +2032,178 @@
 -----------------------------------------------

 -- 1.5 features : annotation - Metadata feature jsr175

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

-AnnotationTypeDeclaration ::= Modifiers '@' interface Identifier AnnotationTypeBody

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

-AnnotationTypeDeclaration ::= '@' interface Identifier AnnotationTypeBody

+AnnotationTypeDeclarationHeaderName ::= Modifiers '@' PushRealModifiers interface Identifier

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

+/:$compliance 1.5:/

+AnnotationTypeDeclarationHeaderName ::= '@' PushModifiersForHeader interface Identifier

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

+/:$readableName AnnotationTypeDeclarationHeaderName:/

+/:$compliance 1.5:/

+

+AnnotationTypeDeclarationHeader ::= AnnotationTypeDeclarationHeaderName ClassHeaderExtendsopt ClassHeaderImplementsopt

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

+/:$readableName AnnotationTypeDeclarationHeader:/

+/:$compliance 1.5:/

+

+AnnotationTypeDeclaration ::= AnnotationTypeDeclarationHeader AnnotationTypeBody

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

 /:$readableName AnnotationTypeDeclaration:/

+/:$compliance 1.5:/

 

 AnnotationTypeBody ::= '{' AnnotationTypeMemberDeclarationsopt '}'

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

 /:$readableName AnnotationTypeBody:/

+/:$compliance 1.5:/

 

 AnnotationTypeMemberDeclarationsopt ::= $empty

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

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

+/:$compliance 1.5:/

 AnnotationTypeMemberDeclarationsopt -> AnnotationTypeMemberDeclarations

-/:$readableName AnnotationTypeMemberDeclarationsopt:/

+/:$readableName AnnotationTypeMemberDeclarations:/

+/:$compliance 1.5:/

 

 AnnotationTypeMemberDeclarations -> AnnotationTypeMemberDeclaration

+/:$compliance 1.5:/

 AnnotationTypeMemberDeclarations ::= AnnotationTypeMemberDeclarations AnnotationTypeMemberDeclaration

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

 /:$readableName AnnotationTypeMemberDeclarations:/

+/:$compliance 1.5:/

 

-AnnotationTypeMemberDeclaration ::= Modifiersopt Type Identifier '(' ')' DefaultValueopt ';'

+AnnotationMethodHeaderName ::= Modifiersopt TypeParameters Type 'Identifier' '('

+/.$putCase consumeMethodHeaderNameWithTypeParameters(true); $break ./

+AnnotationMethodHeaderName ::= Modifiersopt Type 'Identifier' '('

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

+/:$readableName MethodHeaderName:/

+

+AnnotationMethodHeaderDefaultValueopt ::= $empty

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

+/:$readableName MethodHeaderDefaultValue:/

+/:$compliance 1.5:/

+AnnotationMethodHeaderDefaultValueopt ::= DefaultValue

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

+/:$readableName MethodHeaderDefaultValue:/

+/:$compliance 1.5:/

+

+AnnotationMethodHeader ::= AnnotationMethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims AnnotationMethodHeaderDefaultValueopt

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

+/:$readableName AnnotationMethodHeader:/

+/:$compliance 1.5:/

+

+AnnotationTypeMemberDeclaration ::= AnnotationMethodHeader ';'

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

-AnnotationTypeMemberDeclaration ::= ';'

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

+/:$compliance 1.5:/

 AnnotationTypeMemberDeclaration -> ConstantDeclaration

-AnnotationTypeMemberDeclaration -> ClassDeclaration

-AnnotationTypeMemberDeclaration -> InterfaceDeclaration

-AnnotationTypeMemberDeclaration -> EnumDeclaration

-AnnotationTypeMemberDeclaration -> AnnotationTypeDeclaration

+/:$compliance 1.5:/

+AnnotationTypeMemberDeclaration -> ConstructorDeclaration

+/:$compliance 1.5:/

+AnnotationTypeMemberDeclaration -> TypeDeclaration

 /:$readableName AnnotationTypeMemberDeclaration:/

-

-DefaultValueopt ::= $empty

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

-DefaultValueopt -> DefaultValue

-/:$readableName DefaultValueopt:/

+/:$compliance 1.5:/

 

 DefaultValue ::= 'default' MemberValue

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

 /:$readableName DefaultValue:/

+/:$compliance 1.5:/

 

 Annotation -> NormalAnnotation

+/:$compliance 1.5:/

 Annotation -> MarkerAnnotation

+/:$compliance 1.5:/

 Annotation -> SingleMemberAnnotation

 /:$readableName Annotation:/

+/:$compliance 1.5:/

 

-NormalAnnotation ::= '@' Name '(' MemberValuePairsopt ')'

+AnnotationName ::= '@' Name

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

+/:$readableName AnnotationName:/

+/:$compliance 1.5:/

+

+NormalAnnotation ::= AnnotationName '(' MemberValuePairsopt ')'

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

 /:$readableName NormalAnnotation:/

+/:$compliance 1.5:/

 

 MemberValuePairsopt ::= $empty

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

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

+/:$compliance 1.5:/

 MemberValuePairsopt -> MemberValuePairs

 /:$readableName MemberValuePairsopt:/

+/:$compliance 1.5:/

 

 MemberValuePairs -> MemberValuePair

+/:$compliance 1.5:/

 MemberValuePairs ::= MemberValuePairs ',' MemberValuePair

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

 /:$readableName MemberValuePairs:/

+/:$compliance 1.5:/

 

 MemberValuePair ::= SimpleName '=' MemberValue

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

 /:$readableName MemberValuePair:/

+/:$compliance 1.5:/

 

 MemberValue -> ConditionalExpression_NotName

+/:$compliance 1.5:/

+MemberValue ::= Name

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

+/:$compliance 1.5:/

 MemberValue -> Annotation

+/:$compliance 1.5:/

 MemberValue -> MemberValueArrayInitializer

 /:$readableName MemberValue:/

+/:$compliance 1.5:/

 

-MemberValueArrayInitializer ::= '{' MemberValues ',' '}'

+MemberValueArrayInitializer ::= '{' PushLeftBrace MemberValues ',' '}'

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

-MemberValueArrayInitializer ::= '{' MemberValues '}'

+/:$compliance 1.5:/

+MemberValueArrayInitializer ::= '{' PushLeftBrace MemberValues '}'

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

-MemberValueArrayInitializer ::= '{' ',' '}'

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

-MemberValueArrayInitializer ::= '{' '}'

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

+/:$compliance 1.5:/

+MemberValueArrayInitializer ::= '{' PushLeftBrace ',' '}'

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

+/:$compliance 1.5:/

+MemberValueArrayInitializer ::= '{' PushLeftBrace '}'

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

 /:$readableName MemberValueArrayInitializer:/

+/:$compliance 1.5:/

 

 MemberValues -> MemberValue

+/:$compliance 1.5:/

 MemberValues ::= MemberValues ',' MemberValue

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

 /:$readableName MemberValues:/

+/:$compliance 1.5:/

 

-MarkerAnnotation ::= '@' Name

+MarkerAnnotation ::= AnnotationName

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

 /:$readableName MarkerAnnotation:/

+/:$compliance 1.5:/

 

-SingleMemberAnnotation ::= '@' Name '(' MemberValue ')'

+SingleMemberAnnotation ::= AnnotationName '(' MemberValue ')'

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

 /:$readableName SingleMemberAnnotation:/

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

--- 1.5 features : end of annotation

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

+/:$compliance 1.5:/

+--------------------------------------

+-- 1.5 features : end of annotation --

+--------------------------------------

+

+-----------------------------------

+-- 1.5 features : recovery rules --

+-----------------------------------

+RecoveryMethodHeaderName ::= Modifiersopt TypeParameters Type 'Identifier' '('

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

+/:$compliance 1.5:/

+RecoveryMethodHeaderName ::= Modifiersopt Type 'Identifier' '('

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

+/:$readableName MethodHeaderName:/

+

+RecoveryMethodHeader ::= RecoveryMethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims AnnotationMethodHeaderDefaultValueopt

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

+RecoveryMethodHeader ::= RecoveryMethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims MethodHeaderThrowsClause

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

+/:$readableName MethodHeader:/

+-----------------------------------

+-- 1.5 features : recovery rules --

+-----------------------------------

+

 /.	}

 }./

 

@@ -2038,6 +2255,8 @@
 COMMA ::=    ','    

 DOT ::=    '.'    

 EQUAL ::=    '='    

+AT ::=    '@'    

+ELLIPSIS ::=    '...'    

 

 $end

 -- need a carriage return after the $end

diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/BufferChangedEvent.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/BufferChangedEvent.java
index 80b1bd1..a8a7fc7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/BufferChangedEvent.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/BufferChangedEvent.java
@@ -59,6 +59,8 @@
 	 * The text that was modified.
 	 */
 	private String text;
+	
+	private static final long serialVersionUID = 655379473891745999L; // backward compatible
 
 /**
  * Creates a new buffer changed event indicating that the given buffer has changed.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionProposal.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionProposal.java
index 6b94c1e..83a2df8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionProposal.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionProposal.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.codeassist.InternalCompletionProposal;
 
 /**
  * Completion proposal.
@@ -23,7 +24,7 @@
  * engine analyzes the code in the buffer, determines what kind of
  * Java language construct is at that position, and proposes ways
  * to complete that construct. These proposals are instances of
- * subclasses of <code>CompletionProposal</code>. These proposals,
+ * the class <code>CompletionProposal</code>. These proposals,
  * perhaps after sorting and filtering, are presented to the user
  * to make a choice.
  * </p>
@@ -49,7 +50,8 @@
  * @see ICodeAssist#codeComplete(int, CompletionRequestor)
  * @since 3.0
  */
-public final class CompletionProposal {
+public final class CompletionProposal extends InternalCompletionProposal {
+	private boolean updateCompletion = false;
 
 	/**
 	 * Completion is a declaration of an anonymous class.
@@ -243,7 +245,7 @@
 	 * for this kind of completion proposal at little extra cost:
 	 * <ul>
 	 * <li>{@link #getDeclarationSignature()} -
-	 * the dot-based package signature of the package that is referenced
+	 * the dot-based package name of the package that is referenced
 	 * </li>
 	 * </ul>
 	 * </p>
@@ -264,7 +266,7 @@
 	 * for this kind of completion proposal at little extra cost:
 	 * <ul>
 	 * <li>{@link #getDeclarationSignature()} -
-	 * the dot-based package signature of the package that contains
+	 * the dot-based package name of the package that contains
 	 * the type that is referenced
 	 * </li>
 	 * <li>{@link #getSignature()} -
@@ -303,6 +305,65 @@
 	 * @see #getKind()
 	 */
 	public static final int VARIABLE_DECLARATION = 10;
+
+	/**
+	 * Completion is a declaration of a new potential method.
+	 * This kind of completion might occur in a context like
+	 * <code>"new List() {si^};"</code> and complete it to
+	 * <code>"new List() {public int si() {} };"</code>.
+	 * <p>
+	 * The following additional context information is available
+	 * for this kind of completion proposal at little extra cost:
+	 * <ul>
+	 * <li>{@link #getDeclarationSignature()} -
+	 * the type signature of the type that declares the
+	 * method that is being created
+	 * </li>
+	 * <li>{@link #getName()} -
+	 * the simple name of the method that is being created
+	 * </li>
+	 * <li>{@link #getSignature()} -
+	 * the method signature of the method that is being
+	 * created
+	 * </li>
+	 * <li>{@link #getFlags()} -
+	 * the modifiers flags of the method that is being
+	 * created
+	 * </li>
+	 * </ul>
+	 * </p>
+	 * 
+	 * @see #getKind()
+	 */
+	public static final int POTENTIAL_METHOD_DECLARATION = 11;
+	
+	/**
+	 * Completion is a reference to a method name.
+	 * This kind of completion might occur in a context like
+	 * <code>"import p.X.fo^"</code> and complete it to
+	 * <code>"import p.X.foo;"</code>.
+	 * <p>
+	 * The following additional context information is available
+	 * for this kind of completion proposal at little extra cost:
+	 * <ul>
+	 * <li>{@link #getDeclarationSignature()} -
+	 * the type signature of the type that declares the method that is referenced
+	 * </li>
+	 * <li>{@link #getFlags()} -
+	 * the modifiers flags of the method that is referenced
+	 * </li>
+	 * <li>{@link #getName()} -
+	 * the simple name of the method that is referenced
+	 * </li>
+	 * <li>{@link #getSignature()} -
+	 * the method signature of the method that is referenced
+	 * </li>
+	 * </ul>
+	 * </p>
+	 * 
+	 * @see #getKind()
+	 */
+	public static final int METHOD_NAME_REFERENCE = 12;
 	
 	/**
 	 * Kind of completion request.
@@ -426,7 +487,7 @@
 	 */
 	CompletionProposal(int kind, int completionLocation) {
 		if ((kind < CompletionProposal.ANONYMOUS_CLASS_DECLARATION)
-				|| (kind > CompletionProposal.VARIABLE_DECLARATION)) {
+				|| (kind > CompletionProposal.METHOD_NAME_REFERENCE)) {
 			throw new IllegalArgumentException();
 		}
 		if (this.completion == null || completionLocation < 0) {
@@ -533,6 +594,36 @@
 	 * @return the completion string
 	 */
 	public char[] getCompletion() {
+		if(this.completionKind == METHOD_DECLARATION) {
+			this.findParameterNames(null);
+			if(this.updateCompletion) {
+				this.updateCompletion = false;
+				
+				if(this.parameterNames != null) {
+					int length = this.parameterNames.length;
+					StringBuffer completionBuffer = new StringBuffer(this.completion.length);
+						
+					int start = 0;
+					int end = CharOperation.indexOf('%', this.completion);
+	
+					completionBuffer.append(CharOperation.subarray(this.completion, start, end));
+					
+					for(int i = 0 ; i < length ; i++){
+						completionBuffer.append(this.parameterNames[i]);
+						start = end + 1;
+						end = CharOperation.indexOf('%', this.completion, start);
+						if(end > -1){
+							completionBuffer.append(CharOperation.subarray(this.completion, start, end));
+						} else {
+							completionBuffer.append(CharOperation.subarray(this.completion, start, this.completion.length));
+						}
+					}
+					int nameLength = completionBuffer.length();
+					this.completion = new char[nameLength];
+					completionBuffer.getChars(0, nameLength, this.completion, 0);
+				}
+			}
+		}
 		return this.completion;
 	}
 	
@@ -566,7 +657,7 @@
 	 * Note that while the token subrange is precisely 
 	 * specified, the replacement range is loosely
 	 * constrained and may not bear any direct relation
-	 * to the original request offset. For example, a
+	 * to the original request offset. For example,
 	 * it would be possible for a type completion to 
 	 * propose inserting an import declaration at the
 	 * top of the compilation unit; or the completion
@@ -649,7 +740,7 @@
 	}
 	
 	/**
-	 * Returns the type or package signature of the relevant
+	 * Returns the type signature or package name of the relevant
 	 * declaration in the context, or <code>null</code> if none.
 	 * <p>
 	 * This field is available for the following kinds of
@@ -665,17 +756,19 @@
 	 * of the type that declares the method that is being
 	 * implemented or overridden</li>
 	 * 	<li><code>PACKAGE_REF</code> - dot-based package 
-	 * signature of the package that is referenced</li>
+	 * name of the package that is referenced</li>
 	 * 	<li><code>TYPE_REF</code> - dot-based package 
-	 * signature of the package containing the type that is referenced</li>
+	 * name of the package containing the type that is referenced</li>
+	 *  <li><code>POTENTIAL_METHOD_DECLARATION</code> - type signature
+	 * of the type that declares the method that is being created</li>
 	 * </ul>
 	 * For kinds of completion proposals, this method returns
 	 * <code>null</code>. Clients must not modify the array
 	 * returned.
 	 * </p>
 	 * 
-	 * @return the declaration signature, or
-	 * <code>null</code> if none
+	 * @return a type signature or a package name (depending
+	 * on the kind of completion), or <code>null</code> if none
 	 * @see Signature
 	 */
 	public char[] getDeclarationSignature() {
@@ -715,6 +808,7 @@
 	 * 	<li><code>METHOD_REF</code> - the name of the method</li>
 	 * 	<li><code>METHOD_DECLARATION</code> - the name of the method</li>
 	 * 	<li><code>VARIABLE_DECLARATION</code> - the name of the variable</li>
+	 *  <li><code>POTENTIAL_METHOD_DECLARATION</code> - the name of the method</li>
 	 * </ul>
 	 * For kinds of completion proposals, this method returns
 	 * <code>null</code>. Clients must not modify the array
@@ -769,6 +863,8 @@
 	 * of the type that is referenced</li>
 	 * 	<li><code>VARIABLE_DECLARATION</code> - the type signature
 	 * of the type of the variable being declared</li>
+	 *  <li><code>POTENTIAL_METHOD_DECLARATION</code> - method signature
+	 * of the method that is being created</li>
 	 * </ul>
 	 * For kinds of completion proposals, this method returns
 	 * <code>null</code>. Clients must not modify the array
@@ -782,6 +878,211 @@
 		return this.signature;
 	}
 	
+//	/**
+//	 * Returns the package name of the relevant
+//	 * declaration in the context, or <code>null</code> if none.
+//	 * <p>
+//	 * This field is available for the following kinds of
+//	 * completion proposals:
+//	 * <ul>
+//	 * <li><code>ANONYMOUS_CLASS_DECLARATION</code> - the dot-based package name
+//	 * of the type that is being subclassed or implemented</li>
+//	 * 	<li><code>FIELD_REF</code> - the dot-based package name
+//	 * of the type that declares the field that is referenced</li>
+//	 * 	<li><code>METHOD_REF</code> - the dot-based package name
+//	 * of the type that declares the method that is referenced</li>
+//	 * 	<li><code>METHOD_DECLARATION</code> - the dot-based package name
+//	 * of the type that declares the method that is being
+//	 * implemented or overridden</li>
+//	 * </ul>
+//	 * For kinds of completion proposals, this method returns
+//	 * <code>null</code>. Clients must not modify the array
+//	 * returned.
+//	 * </p>
+//	 * 
+//	 * @return the dot-based package name, or
+//	 * <code>null</code> if none
+//	 * @see #getDeclarationSignature()
+//	 * @see #getSignature()
+//	 * 
+//	 * @since 3.1
+//	 */
+//	public char[] getDeclarationPackageName() {
+//		return this.declarationPackageName;
+//	}
+//	
+//	/**
+//	 * Returns the type name of the relevant
+//	 * declaration in the context without the package fragment,
+//	 * or <code>null</code> if none. 
+//	 * <p>
+//	 * This field is available for the following kinds of
+//	 * completion proposals:
+//	 * <ul>
+//	 * <li><code>ANONYMOUS_CLASS_DECLARATION</code> - the dot-based type name
+//	 * of the type that is being subclassed or implemented</li>
+//	 * 	<li><code>FIELD_REF</code> - the dot-based type name
+//	 * of the type that declares the field that is referenced
+//	 * or an anonymous type instanciation ("new X(){}") if it is an anonymous type</li>
+//	 * 	<li><code>METHOD_REF</code> - the dot-based type name
+//	 * of the type that declares the method that is referenced
+//	 * or an anonymous type instanciation ("new X(){}") if it is an anonymous type</li>
+//	 * 	<li><code>METHOD_DECLARATION</code> - the dot-based type name
+//	 * of the type that declares the method that is being
+//	 * implemented or overridden</li>
+//	 * </ul>
+//	 * For kinds of completion proposals, this method returns
+//	 * <code>null</code>. Clients must not modify the array
+//	 * returned.
+//	 * </p>
+//	 * 
+//	 * @return the dot-based package name, or
+//	 * <code>null</code> if none
+//	 * @see #getDeclarationSignature()
+//	 * @see #getSignature()
+//	 * 
+//	 * @since 3.1
+//	 */
+//	public char[] getDeclarationTypeName() {
+//		return this.declarationTypeName;
+//	}
+//	
+//	/**
+//	 * Returns the package name of the method or type
+//	 * relevant in the context, or <code>null</code> if none.
+//	 * <p>
+//	 * This field is available for the following kinds of
+//	 * completion proposals:
+//	 * <ul>
+//	 * 	<li><code>FIELD_REF</code> - the dot-based package name
+//	 * of the referenced field's type</li>
+//	 * 	<li><code>LOCAL_VARIABLE_REF</code> - the dot-based package name
+//	 * of the referenced local variable's type</li>
+//	 * 	<li><code>METHOD_REF</code> -  the dot-based package name
+//	 * of the return type of the method that is referenced</li>
+//	 * 	<li><code>METHOD_DECLARATION</code> - the dot-based package name
+//	 * of the return type of the method that is being implemented
+//	 * or overridden</li>
+//	 * 	<li><code>PACKAGE_REF</code> - the dot-based package name
+//	 * of the package that is referenced</li>
+//	 * 	<li><code>TYPE_REF</code> - the dot-based package name
+//	 * of the type that is referenced</li>
+//	 * 	<li><code>VARIABLE_DECLARATION</code> - the dot-based package name
+//	 * of the type of the variable being declared</li>
+//	 * </ul>
+//	 * For kinds of completion proposals, this method returns
+//	 * <code>null</code>. Clients must not modify the array
+//	 * returned.
+//	 * </p>
+//	 * 
+//	 * @return the package name, or <code>null</code> if none
+//	 * 
+//	 * @see #getDeclarationSignature()
+//	 * @see #getSignature()
+//	 * 
+//	 * @since 3.1
+//	 */
+//	public char[] getPackageName() {
+//		return this.packageName;
+//	}
+//	
+//	/**
+//	 * Returns the type name without the package fragment of the method or type
+//	 * relevant in the context, or <code>null</code> if none.
+//	 * <p>
+//	 * This field is available for the following kinds of
+//	 * completion proposals:
+//	 * <ul>
+//	 * 	<li><code>FIELD_REF</code> - the dot-based type name
+//	 * of the referenced field's type</li>
+//	 * 	<li><code>LOCAL_VARIABLE_REF</code> - the dot-based type name
+//	 * of the referenced local variable's type</li>
+//	 * 	<li><code>METHOD_REF</code> -  the dot-based type name
+//	 * of the return type of the method that is referenced</li>
+//	 * 	<li><code>METHOD_DECLARATION</code> - the dot-based type name
+//	 * of the return type of the method that is being implemented
+//	 * or overridden</li>
+//	 * 	<li><code>TYPE_REF</code> - the dot-based type name
+//	 * of the type that is referenced</li>
+//	 * 	<li><code>VARIABLE_DECLARATION</code> - the dot-based package name
+//	 * of the type of the variable being declared</li>
+//	 * </ul>
+//	 * For kinds of completion proposals, this method returns
+//	 * <code>null</code>. Clients must not modify the array
+//	 * returned.
+//	 * </p>
+//	 * 
+//	 * @return the package name, or <code>null</code> if none
+//	 * 
+//	 * @see #getDeclarationSignature()
+//	 * @see #getSignature()
+//	 * 
+//	 * @since 3.1
+//	 */
+//	public char[] getTypeName() {
+//		return this.typeName;
+//	}
+//	
+//	/**
+//	 * Returns the parameter package names of the method 
+//	 * relevant in the context, or <code>null</code> if none.
+//	 * <p>
+//	 * This field is available for the following kinds of
+//	 * completion proposals:
+//	 * <ul>
+//	 * 	<li><code>ANONYMOUS_CLASS_DECLARATION</code> - parameter package names
+//	 * of the constructor that is being invoked</li>
+//	 * 	<li><code>METHOD_REF</code> - parameter package names
+//	 * of the method that is referenced</li>
+//	 * 	<li><code>METHOD_DECLARATION</code> - parameter package names
+//	 * of the method that is being implemented or overridden</li>
+//	 * </ul>
+//	 * For kinds of completion proposals, this method returns
+//	 * <code>null</code>. Clients must not modify the array
+//	 * returned.
+//	 * </p>
+//	 * 
+//	 * @return the package name, or <code>null</code> if none
+//	 * 
+//	 * @see #getDeclarationSignature()
+//	 * @see #getSignature()
+//	 * 
+//	 * @since 3.1
+//	 */
+//	public char[][] getParameterPackageNames() {
+//		return this.parameterPackageNames;
+//	}
+//	
+//	/**
+//	 * Returns the parameter type names without teh package fragment of
+//	 * the method relevant in the context, or <code>null</code> if none.
+//	 * <p>
+//	 * This field is available for the following kinds of
+//	 * completion proposals:
+//	 * <ul>
+//	 * 	<li><code>ANONYMOUS_CLASS_DECLARATION</code> - parameter type names
+//	 * of the constructor that is being invoked</li>
+//	 * 	<li><code>METHOD_REF</code> - parameter type names
+//	 * of the method that is referenced</li>
+//	 * 	<li><code>METHOD_DECLARATION</code> - parameter type names
+//	 * of the method that is being implemented or overridden</li>
+//	 * </ul>
+//	 * For kinds of completion proposals, this method returns
+//	 * <code>null</code>. Clients must not modify the array
+//	 * returned.
+//	 * </p>
+//	 * 
+//	 * @return the package name, or <code>null</code> if none
+//	 * 
+//	 * @see #getDeclarationSignature()
+//	 * @see #getSignature()
+//	 * 
+//	 * @since 3.1
+//	 */
+//	public char[][] getParameterTypeNames() {
+//		return this.parameterTypeNames;
+//	}
+	
 	/**
 	 * Sets the signature of the method, field type, member type,
 	 * relevant in the context, or <code>null</code> if none.
@@ -832,8 +1133,10 @@
 	 * </li>
 	 * 	<li><code>VARIABLE_DECLARATION</code> - modifier flags
 	 * for the variable being declared</li>
+	 * 	<li><code>POTENTIAL_METHOD_DECLARATION</code> - modifier flags
+	 * for the method that is being created</li>
 	 * </ul>
-	 * For kinds of completion proposals, this method returns
+	 * For other kinds of completion proposals, this method returns
 	 * <code>Flags.AccDefault</code>.
 	 * </p>
 	 * 
@@ -882,7 +1185,45 @@
 	public char[][] findParameterNames(IProgressMonitor monitor) {
 		if (!this.parameterNamesComputed) {
 			this.parameterNamesComputed = true;
-			// TODO (jerome) - Missing implementation
+			
+			switch(this.completionKind) {
+				case ANONYMOUS_CLASS_DECLARATION:
+					this.parameterNames =  this.findMethodParameterNames(
+							this.declarationPackageName,
+							this.declarationTypeName,
+							CharOperation.lastSegment(this.declarationTypeName, '.'),
+							this.parameterPackageNames,
+							this.parameterTypeNames);
+					break;
+				case METHOD_REF:
+					this.parameterNames =  this.findMethodParameterNames(
+							this.declarationPackageName,
+							this.declarationTypeName,
+							this.name,
+							this.parameterPackageNames,
+							this.parameterTypeNames);
+					//this.parameterNames = this.findMethodParameterNames(
+					//		this.declarationSignature,
+					//		this.name,
+					//		Signature.getParameterTypes(this.getSignature()));
+					break;
+				case METHOD_DECLARATION:
+					this.parameterNames =  this.findMethodParameterNames(
+							this.declarationPackageName,
+							this.declarationTypeName,
+							this.name,
+							this.parameterPackageNames,
+							this.parameterTypeNames);
+					//char[][] parameterTypes = Signature.getParameterTypes(this.getSignature();
+					///this.parameterNames = this.findMethodParameterNames(
+					//		this.declarationSignature,
+					//		this.name,
+					//		parameterTypes);
+					if(this.parameterNames != null) {
+						this.updateCompletion = true;
+					}
+					break;
+			}			
 		}
 		return this.parameterNames;
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestor.java
index 52dd36e..4fdbee8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestor.java
@@ -79,7 +79,7 @@
 	 */
 	public final boolean isIgnored(int completionProposalKind) {
 		if (completionProposalKind < CompletionProposal.ANONYMOUS_CLASS_DECLARATION
-			|| completionProposalKind > CompletionProposal.VARIABLE_DECLARATION) {
+			|| completionProposalKind > CompletionProposal.METHOD_NAME_REFERENCE) {
 				throw new IllegalArgumentException();
 		}
 		return 0 != (this.ignoreSet & (1 << completionProposalKind));
@@ -98,7 +98,7 @@
 	 */
 	public final void setIgnored(int completionProposalKind, boolean ignore) {
 		if (completionProposalKind < CompletionProposal.ANONYMOUS_CLASS_DECLARATION
-			|| completionProposalKind > CompletionProposal.VARIABLE_DECLARATION) {
+			|| completionProposalKind > CompletionProposal.METHOD_NAME_REFERENCE) {
 				throw new IllegalArgumentException();
 		}
 		if (ignore) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestorAdapter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestorAdapter.java
index f5a686c..7836a68 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestorAdapter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestorAdapter.java
@@ -20,8 +20,8 @@
  *
  * @see ICompletionRequestor
  * @since 2.0
+ * @deprecated Subclass {@link CompletionRequestor} instead.
  */
-// TODO (jerome - once CompletionRequestor is working) @ deprecated Subclass {@link CompletionRequestor} instead.
 public class CompletionRequestorAdapter implements ICompletionRequestor {
 
 	/*
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java
index c11b812..db4b2ee 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java
@@ -196,27 +196,6 @@
 		try {
 			switch (id) {
 				// Type correction
-				case IProblem.FieldTypeNotFound :
-				case IProblem.ArgumentTypeNotFound :
-					this.filter = CLASSES | INTERFACES;
-					argument = arguments[2];
-					break;
-				case IProblem.SuperclassNotFound :
-					this.filter = CLASSES;
-					argument = arguments[0];
-					break;
-				case IProblem.InterfaceNotFound :
-					this.filter = INTERFACES;
-					argument = arguments[0];
-					break;
-				case IProblem.ExceptionTypeNotFound :
-					this.filter = CLASSES;
-					argument = arguments[1];
-					break;
-				case IProblem.ReturnTypeNotFound :
-					this.filter = CLASSES | INTERFACES;
-					argument = arguments[1];
-					break;
 				case IProblem.ImportNotFound :
 					this.filter = IMPORT;
 					argument = arguments[0];
@@ -308,106 +287,103 @@
 	/**
 	 * This field is not intended to be used by client.
 	 */
-	protected ICompletionRequestor completionRequestor = new ICompletionRequestor() {
-		public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {}
-		public void acceptClass(char[] packageName,char[] className,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
-			if((CorrectionEngine.this.filter & (CLASSES | INTERFACES)) != 0) {
-				CorrectionEngine.this.correctionRequestor.acceptClass(
-					packageName,
-					className,
-					CharOperation.subarray(completionName, CorrectionEngine.this.prefixLength, completionName.length),
-					modifiers,
-					CorrectionEngine.this.correctionStart,
-					CorrectionEngine.this.correctionEnd);
-			} else if((CorrectionEngine.this.filter & IMPORT) != 0) {
-				char[] fullName = CharOperation.concat(packageName, className, '.');
-				CorrectionEngine.this.correctionRequestor.acceptClass(
-					packageName,
-					className,
-					CharOperation.subarray(fullName, CorrectionEngine.this.prefixLength, fullName.length),
-					modifiers,
-					CorrectionEngine.this.correctionStart,
-					CorrectionEngine.this.correctionEnd);
+	protected CompletionRequestor completionRequestor = new CompletionRequestor() {
+		public void accept(CompletionProposal proposal) {
+			switch (proposal.getKind()) {
+				case CompletionProposal.TYPE_REF:
+					int flags = proposal.getFlags();
+					if (!(Flags.isEnum(flags) || Flags.isAnnotation(flags))) {
+						if((CorrectionEngine.this.filter & (CLASSES | INTERFACES)) != 0) {
+							char[] completionName = proposal.getCompletion();
+							CorrectionEngine.this.correctionRequestor.acceptClass(
+								proposal.getDeclarationSignature(),
+								Signature.getSignatureSimpleName(proposal.getSignature()),
+								CharOperation.subarray(completionName, CorrectionEngine.this.prefixLength, completionName.length),
+								proposal.getFlags(),
+								CorrectionEngine.this.correctionStart,
+								CorrectionEngine.this.correctionEnd);
+						} else if((CorrectionEngine.this.filter & IMPORT) != 0) {
+							char[] packageName = proposal.getDeclarationSignature();
+							char[] className = Signature.getSignatureSimpleName(proposal.getSignature());
+							char[] fullName = CharOperation.concat(packageName, className, '.');
+							CorrectionEngine.this.correctionRequestor.acceptClass(
+								packageName,
+								className,
+								CharOperation.subarray(fullName, CorrectionEngine.this.prefixLength, fullName.length),
+								proposal.getFlags(),
+								CorrectionEngine.this.correctionStart,
+								CorrectionEngine.this.correctionEnd);
+						}					
+					}
+					break;
+				case CompletionProposal.FIELD_REF:
+					if((CorrectionEngine.this.filter & FIELD) != 0) {
+						char[] declaringSignature = proposal.getDeclarationSignature();
+						char[] signature = proposal.getSignature();
+						CorrectionEngine.this.correctionRequestor.acceptField(
+							Signature.getSignatureQualifier(declaringSignature),
+							Signature.getSignatureSimpleName(declaringSignature),
+							proposal.getName(),
+							Signature.getSignatureQualifier(signature),
+							Signature.getSignatureSimpleName(signature),
+							proposal.getName(),
+							proposal.getFlags(),
+							CorrectionEngine.this.correctionStart,
+							CorrectionEngine.this.correctionEnd);
+					}
+					break;
+				case CompletionProposal.LOCAL_VARIABLE_REF:
+					if((CorrectionEngine.this.filter & LOCAL) != 0) {
+						char[] signature = proposal.getSignature();
+						CorrectionEngine.this.correctionRequestor.acceptLocalVariable(
+							proposal.getName(),
+							Signature.getSignatureQualifier(signature),
+							Signature.getSignatureSimpleName(signature),
+							proposal.getFlags(),
+							CorrectionEngine.this.correctionStart,
+							CorrectionEngine.this.correctionEnd);
+					}
+					break;
+				case CompletionProposal.METHOD_REF:
+					if((CorrectionEngine.this.filter & METHOD) != 0) {
+						char[] declaringSignature = proposal.getDeclarationSignature();
+						char[] signature = proposal.getSignature();
+						char[][] parameterTypeSignatures = Signature.getParameterTypes(signature);
+						int length = parameterTypeSignatures.length;
+						char[][] parameterPackageNames = new char[length][];
+						char[][] parameterTypeNames = new char[length][];
+						for (int i = 0; i < length; i++) {
+							parameterPackageNames[i] = Signature.getSignatureQualifier(parameterTypeSignatures[i]);
+							parameterTypeNames[i] = Signature.getSignatureSimpleName(parameterTypeSignatures[i]);
+						}
+						char[] returnTypeSignature = Signature.getReturnType(signature);
+						CorrectionEngine.this.correctionRequestor.acceptMethod(
+							Signature.getSignatureQualifier(declaringSignature),
+							Signature.getSignatureSimpleName(declaringSignature),
+							proposal.getName(),
+							parameterPackageNames,
+							parameterTypeNames,
+							proposal.findParameterNames(null),
+							Signature.getSignatureQualifier(returnTypeSignature),
+							Signature.getSignatureSimpleName(returnTypeSignature),
+							proposal.getName(),
+							proposal.getFlags(),
+							CorrectionEngine.this.correctionStart,
+							CorrectionEngine.this.correctionEnd);
+					}
+					break;
+				case CompletionProposal.PACKAGE_REF:
+					if((CorrectionEngine.this.filter & (CLASSES | INTERFACES | IMPORT)) != 0) {
+						char[] packageName = proposal.getDeclarationSignature();
+						CorrectionEngine.this.correctionRequestor.acceptPackage(
+							packageName,
+							CharOperation.subarray(packageName, CorrectionEngine.this.prefixLength, packageName.length),
+							CorrectionEngine.this.correctionStart,
+							CorrectionEngine.this.correctionEnd);
+					}
+					break;
 			}
 		}
-		public void acceptError(IProblem error) {}
-		public void acceptField(char[] declaringTypePackageName,char[] declaringTypeName,char[] name,char[] typePackageName,char[] typeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
-			if((CorrectionEngine.this.filter & FIELD) != 0) {
-				CorrectionEngine.this.correctionRequestor.acceptField(
-					declaringTypePackageName,
-					declaringTypeName,
-					name,
-					typePackageName,
-					typeName,
-					name,
-					modifiers,
-					CorrectionEngine.this.correctionStart,
-					CorrectionEngine.this.correctionEnd);
-			}
-		}
-		public void acceptInterface(char[] packageName,char[] interfaceName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
-			if((CorrectionEngine.this.filter & (CLASSES | INTERFACES)) != 0) {
-				CorrectionEngine.this.correctionRequestor.acceptInterface(
-					packageName,
-					interfaceName,
-					CharOperation.subarray(completionName, CorrectionEngine.this.prefixLength, completionName.length),
-					modifiers,
-					CorrectionEngine.this.correctionStart,
-					CorrectionEngine.this.correctionEnd);
-			} else if((CorrectionEngine.this.filter & IMPORT) != 0) {
-				char[] fullName = CharOperation.concat(packageName, interfaceName, '.');
-				CorrectionEngine.this.correctionRequestor.acceptInterface(
-					packageName,
-					interfaceName,
-					CharOperation.subarray(fullName, CorrectionEngine.this.prefixLength, fullName.length),
-					modifiers,
-					CorrectionEngine.this.correctionStart,
-					CorrectionEngine.this.correctionEnd);
-			}
-		}
-		public void acceptKeyword(char[] keywordName,int completionStart,int completionEnd, int relevance) {}
-		public void acceptLabel(char[] labelName,int completionStart,int completionEnd, int relevance) {}
-		public void acceptLocalVariable(char[] name,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd, int relevance) {
-			if((CorrectionEngine.this.filter & LOCAL) != 0) {
-				CorrectionEngine.this.correctionRequestor.acceptLocalVariable(
-					name,
-					typePackageName,
-					typeName,
-					modifiers,
-					CorrectionEngine.this.correctionStart,
-					CorrectionEngine.this.correctionEnd);
-			}
-		}
-		public void acceptMethod(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
-			if((CorrectionEngine.this.filter & METHOD) != 0) {
-				CorrectionEngine.this.correctionRequestor.acceptMethod(
-					declaringTypePackageName,
-					declaringTypeName,
-					selector,
-					parameterPackageNames,
-					parameterTypeNames,
-					parameterNames,
-					returnTypePackageName,
-					returnTypeName,
-					selector,
-					modifiers,
-					CorrectionEngine.this.correctionStart,
-					CorrectionEngine.this.correctionEnd);
-			}
-		}
-		public void acceptMethodDeclaration(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {}
-		public void acceptModifier(char[] modifierName,int completionStart,int completionEnd, int relevance) {}
-		public void acceptPackage(char[] packageName,char[] completionName,int completionStart,int completionEnd, int relevance) {
-			if((CorrectionEngine.this.filter & (CLASSES | INTERFACES | IMPORT)) != 0) {
-				CorrectionEngine.this.correctionRequestor.acceptPackage(
-					packageName,
-					CharOperation.subarray(packageName, CorrectionEngine.this.prefixLength, packageName.length),
-					CorrectionEngine.this.correctionStart,
-					CorrectionEngine.this.correctionEnd);
-			}
-		}
-		public void acceptType(char[] packageName,char[] typeName,char[] completionName,int completionStart,int completionEnd, int relevance) {}
-		public void acceptVariableName(char[] typePackageName,char[] typeName,char[] name,char[] completionName,int completionStart,int completionEnd, int relevance) {}
 	};
 	
 	/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ElementChangedEvent.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ElementChangedEvent.java
index c24b5c4..62dd7a3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ElementChangedEvent.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ElementChangedEvent.java
@@ -80,6 +80,9 @@
 	 * @since 2.0
 	 */
 	public static final int 	POST_RECONCILE = 4;	
+	
+	private static final long serialVersionUID = -8947240431612844420L; // backward compatible
+	
 	/*
 	 * Event type indicating the nature of this event. 
 	 * It can be a combination either:
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java
index 120abd7..0d5820f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java
@@ -346,6 +346,16 @@
 	 * Specification, Second Edition</em> (JLS2).
 	 * </p> 
 	 * <p>
+	 * Note that the flags of a method can include the AccVarargs flag that has no standard description. Since the AccVarargs flag has the same value as
+	 * the AccTransient flag (valid for fields only), attempting to get the description of method modifiers with the AccVarargs flag set would result in an
+	 * unexpected description. Clients should ensure that the AccVarargs is not included in the flags of a method as follows:
+	 * <pre>
+	 * IMethod method = ...
+	 * int flags = method.getFlags() & ~Flags.AccVarargs;
+	 * return Flags.toString(flags);
+	 * </pre>
+	 * </p>
+	 * <p>
 	 * Examples results:
 	 * <pre>
 	 *	  <code>"public static final"</code>
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java
index 5519b4a..fefff5d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java
@@ -180,10 +180,11 @@
 	int getEntryKind();
 
 	/**
-	 * Returns the set of patterns used to exclude resources associated with
-	 * this source entry.
+	 * Returns the set of patterns used to exclude resources or classes associated with
+	 * this classpath entry.
 	 * <p>
-	 * Exclusion patterns allow specified portions of the resource tree rooted
+	 * For source classpath entries,
+	 * exclusion patterns allow specified portions of the resource tree rooted
 	 * at this source entry's path to be filtered out. If no exclusion patterns
 	 * are specified, this source entry includes all relevent files. Each path
 	 * specified must be a relative path, and will be interpreted relative
@@ -199,6 +200,15 @@
 	 * because a source entry filters these out automatically.
 	 * </p>
 	 * <p>
+	 * Exclusion patterns on library, project, container,
+	 * and variable classpath entries (added in 3.1) are used in a similar
+	 * fashion to express access restrictions. Each path
+	 * specified is relative path encoding a package-qualified class name
+	 * (e.g., <code>java/lang/String</code>). Class names that match
+	 * the exclusion pattern should not be referred to by source code in the
+	 * project (compiler will generate a warning or error).
+	 * </p>
+	 * <p>
 	 * The pattern mechanism is similar to Ant's. Each pattern is represented as
 	 * a relative path. The path segments can be regular file or folder names or simple patterns
 	 * involving standard wildcard characters.
@@ -219,13 +229,13 @@
 	 * Combinations of *'s and ?'s are allowed.
 	 * </p>
 	 * <p>
-	 * The special pattern '**' matches zero or more segments. A path 
-	 * like <code>tests/</code> that ends in a trailing separator is interpreted
-	 * as <code>tests/&#42;&#42;</code>, and would match all files under the 
+	 * The special pattern '**' matches zero or more segments. In a source enry,
+	 * a path like <code>tests/</code> that ends in a trailing separator is interpreted
+	 * as <code>tests/&#42;&#42;</code>, and would match everything under
 	 * the folder named <code>tests</code>.
 	 * </p>
 	 * <p>
-	 * Examples:
+	 * Example patterns in source entries:
 	 * <ul>
 	 * <li>
 	 * <code>tests/&#42;&#42;</code> (or simply <code>tests/</code>) 
@@ -255,17 +265,18 @@
 	 * </p>
 	 * 
 	 * @return the possibly empty list of resource exclusion patterns 
-	 *   associated with this source entry, and <code>null</code> for other
-	 *   kinds of classpath entries
+	 *   associated with this classpath entry, or <code>null</code> if this kind
+	 *   of classpath entry does not support exclusion patterns
 	 * @since 2.1
 	 */
 	IPath[] getExclusionPatterns();
 	
 	/**
-	 * Returns the set of patterns used to explicitly define resources to be
-	 * included with this source entry.
+	 * Returns the set of patterns used to explicitly define resources or classes
+	 * to be included with this classpath entry.
 	 * <p>
-	 * When no inclusion patterns are specified, the source entry includes all
+	 * For source classpath entries,
+	 * when no inclusion patterns are specified, the source entry includes all
 	 * relevent files in the resource tree rooted at this source entry's path.
 	 * Specifying one or more inclusion patterns means that only the specified
 	 * portions of the resource tree are to be included. Each path specified
@@ -278,13 +289,22 @@
 	 * ones that are to be included, not the other way around.
 	 * </p>
 	 * <p>
+	 * Inclusion patterns on library, project, container,
+	 * and variable classpath entries (added in 3.1) are used in a similar
+	 * fashion to express access restrictions. Each path
+	 * specified is relative path encoding a package-qualified class name
+	 * (e.g., <code>java/lang/String</code>). Class names that match
+	 * the inclusion pattern can be legally referred to by source code in the
+	 * project.
+	 * </p>
+	 * <p>
 	 * See {@link #getExclusionPatterns()} for a discussion of the syntax and
 	 * semantics of path patterns. The absence of any inclusion patterns is
 	 * semantically equivalent to the explicit inclusion pattern
 	 * <code>&#42;&#42;</code>.
 	 * </p>
 	 * <p>
-	 * Examples:
+	 * Example patterns in source entries:
 	 * <ul>
 	 * <li>
 	 * The inclusion pattern <code>src/&#42;&#42;</code> by itself includes all
@@ -305,8 +325,8 @@
 	 * </p>
 	 * 
 	 * @return the possibly empty list of resource inclusion patterns 
-	 *   associated with this source entry, and <code>null</code> for other
-	 *   kinds of classpath entries
+	 *   associated with this classpath entry, or <code>null</code> if this kind
+	 *   of classpath entry does not support exclusion patterns
 	 * @since 3.0
 	 */
 	IPath[] getInclusionPatterns();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeAssist.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeAssist.java
index 460939e..eac0384 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeAssist.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeAssist.java
@@ -57,8 +57,8 @@
 	 *
 	 * @exception IllegalArgumentException if <code>requestor</code> is <code>null</code>
 	 * @since 2.0
+	 * @deprecated Use {@link #codeComplete(int, CompletionRequestor)} instead.
  	 */
-	// TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link #codeComplete(int, CompletionRequestor)} instead.
 	void codeComplete(int offset, ICompletionRequestor requestor)
 		throws JavaModelException;
 	
@@ -114,8 +114,8 @@
 	 *
 	 * @exception IllegalArgumentException if <code>requestor</code> is <code>null</code>
 	 * @since 3.0
+	 * @deprecated Use {@link #codeComplete(int, CompletionRequestor, WorkingCopyOwner)} instead.
 	 */
-    // TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link #codeComplete(int, CompletionRequestor, WorkingCopyOwner)} instead.
 	void codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner owner)
 		throws JavaModelException;
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
index 7adfc8f..a659a0e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
@@ -19,11 +19,11 @@
 /**
  * Represents an entire Java compilation unit (<code>.java</code> source file).
  * Compilation unit elements need to be opened before they can be navigated or manipulated.
- * The children are of type <code>IPackageDeclaration</code>,
- * <code>IImportContainer</code>, and <code>IType</code>,
+ * The children are of type {@link IPackageDeclaration},
+ * {@link IImportContainer}, and {@link IType},
  * and appear in the order in which they are declared in the source.
  * If a <code>.java</code> file cannot be parsed, its structure remains unknown.
- * Use <code>IJavaElement.isStructureKnown</code> to determine whether this is 
+ * Use {@link IJavaElement#isStructureKnown} to determine whether this is 
  * the case.
  * <p>
  * This interface is not intended to be implemented by clients.
@@ -37,23 +37,25 @@
 public static final int NO_AST = 0;
 
 /**
- * Changes this compilation unit handle into a working copy. A new <code>IBuffer</code> is
+ * Changes this compilation unit handle into a working copy. A new {@link IBuffer} is
  * created using this compilation unit handle's owner. Uses the primary owner is none was
  * specified when this compilation unit handle was created.
  * <p>
  * When switching to working copy mode, problems are reported to given 
- * <code>IProblemRequestor</code>.
+ * {@link IProblemRequestor}. Note that once in working copy mode, the given
+ * {@link IProblemRequestor} is ignored. Only the original {@link IProblemRequestor}
+ * is used to report subsequent problems.
  * </p>
  * <p>
  * Once in working copy mode, changes to this compilation unit or its children are done in memory.
- * Only the new buffer is affected. Using <code>commitWorkingCopy(boolean, IProgressMonitor)</code>
+ * Only the new buffer is affected. Using {@link #commitWorkingCopy(boolean, IProgressMonitor)}
  * will bring the underlying resource in sync with this compilation unit.
  * </p>
  * <p>
  * If this compilation unit was already in working copy mode, an internal counter is incremented and no
  * other action is taken on this compilation unit. To bring this compilation unit back into the original mode 
- * (where it reflects the underlying resource), <code>discardWorkingCopy</code> must be call as many 
- * times as <code>becomeWorkingCopy</code>.
+ * (where it reflects the underlying resource), {@link #discardWorkingCopy} must be call as many 
+ * times as {@link #becomeWorkingCopy(IProblemRequestor, IProgressMonitor)}.
  * </p>
  * 
  * @param problemRequestor a requestor which will get notified of problems detected during
@@ -76,7 +78,7 @@
  * <li> <code>true</code> - in this case the contents of this working copy are applied to
  * 	the underlying resource even though this working copy was created before
  *		a subsequent change in the resource</li>
- * <li> <code>false</code> - in this case a <code>JavaModelException</code> is thrown</li>
+ * <li> <code>false</code> - in this case a {@link JavaModelException} is thrown</li>
  * </ul>
  * <p>
  * Since 2.1, a working copy can be created on a not-yet existing compilation
@@ -88,7 +90,7 @@
  * @param monitor the given progress monitor
  * @throws JavaModelException if this working copy could not commit. Reasons include:
  * <ul>
- * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> A {@link org.eclipse.core.runtime.CoreException} occurred while updating an underlying resource
  * <li> This element is not a working copy (INVALID_ELEMENT_TYPES)
  * <li> A update conflict (described above) (UPDATE_CONFLICT)
  * </ul>
@@ -110,7 +112,7 @@
  * @throws JavaModelException if the element could not be created. Reasons include:
  * <ul>
  * <li> This Java element does not exist or the specified sibling does not exist (ELEMENT_DOES_NOT_EXIST)</li>
- * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> A {@link org.eclipse.core.runtime.CoreException} occurred while updating an underlying resource
  * <li> The specified sibling is not a child of this compilation unit (INVALID_SIBLING)
  * <li> The name is not a valid import name (INVALID_NAME)
  * </ul>
@@ -146,8 +148,8 @@
  *  <code>"java.awt.*"</code>)
  * @param sibling the existing element which the import declaration will be inserted immediately before (if
  *	<code> null </code>, then this import will be inserted as the last import declaration.
- * @param flags <code>Flags.AccStatic</code> for static imports, or
- * <code>Flags.AccDefault</code> for regular imports; other modifier flags
+ * @param flags {@link Flags#AccStatic} for static imports, or
+ * {@link Flags#AccDefault} for regular imports; other modifier flags
  * are ignored
  * @param monitor the progress monitor to notify
  * @return the newly inserted import declaration (or the previously existing one in case attempting to create a duplicate)
@@ -155,7 +157,7 @@
  * @throws JavaModelException if the element could not be created. Reasons include:
  * <ul>
  * <li> This Java element does not exist or the specified sibling does not exist (ELEMENT_DOES_NOT_EXIST)</li>
- * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> A {@link org.eclipse.core.runtime.CoreException} occurred while updating an underlying resource
  * <li> The specified sibling is not a child of this compilation unit (INVALID_SIBLING)
  * <li> The name is not a valid import name (INVALID_NAME)
  * </ul>
@@ -178,7 +180,7 @@
  * @throws JavaModelException if the element could not be created. Reasons include:
  * <ul>
  * <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
- * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> A {@link org.eclipse.core.runtime.CoreException} occurred while updating an underlying resource
  * <li> The name is not a valid package name (INVALID_NAME)
  * </ul>
  */
@@ -196,20 +198,20 @@
  * The value of the <code>force</code> parameter effects the resolution of
  * such a conflict:<ul>
  * <li> <code>true</code> - in this case the type is created with the new contents</li>
- * <li> <code>false</code> - in this case a <code>JavaModelException</code> is thrown</li>
+ * <li> <code>false</code> - in this case a {@link JavaModelException} is thrown</li>
  * </ul>
  *
  * @param contents the source contents of the type declaration to add.
  * @param sibling the existing element which the type will be inserted immediately before (if
- *	<code> null </code>, then this type will be inserted as the last type declaration.
- * @param force a <code> boolean </code> flag indicating how to deal with duplicates
+ *	<code>null</code>, then this type will be inserted as the last type declaration.
+ * @param force a <code>boolean</code> flag indicating how to deal with duplicates
  * @param monitor the progress monitor to notify
  * @return the newly inserted type
  *
  * @throws JavaModelException if the element could not be created. Reasons include:
  * <ul>
  * <li>The specified sibling element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
- * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> A {@link org.eclipse.core.runtime.CoreException} occurred while updating an underlying resource
  * <li> The specified sibling is not a child of this compilation unit (INVALID_SIBLING)
  * <li> The contents could not be recognized as a type declaration (INVALID_CONTENTS)
  * <li> There was a naming collision with an existing type (NAME_COLLISION)
@@ -222,8 +224,8 @@
  * This has no effect if this compilation unit was not in working copy mode.
  * </p>
  * <p>
- * If <code>becomeWorkingCopy</code> was called several times on this
- * compilation unit, <code>discardWorkingCopy</code> must be called as 
+ * If {@link #becomeWorkingCopy} was called several times on this
+ * compilation unit, {@link #discardWorkingCopy} must be called as 
  * many times before it switches back to the original mode.
  * </p>
  * 
@@ -261,13 +263,13 @@
  */
 IType findPrimaryType();
 /**
- * Finds the working copy for this compilation unit, given a <code>WorkingCopyOwner</code>. 
+ * Finds the working copy for this compilation unit, given a {@link WorkingCopyOwner}. 
  * If no working copy has been created for this compilation unit associated with this
  * working copy owner, returns <code>null</code>.
  * <p>
  * Users of this method must not destroy the resulting working copy. 
  * 
- * @param owner the given <code>WorkingCopyOwner</code>
+ * @param owner the given {@link WorkingCopyOwner}
  * @return the found working copy for this compilation unit, <code>null</code> if none
  * @see WorkingCopyOwner
  * @since 3.0
@@ -394,14 +396,14 @@
  * or this compilation unit if it is already a non-primary working copy.
  * <p>
  * Note: if intending to share a working copy amongst several clients, then 
- * <code>#getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)</code> 
+ * {@link #getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)} 
  * should be used instead.
  * </p><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 
- * <code>discardWorkingCopy()</code>.
+ * {@link #discardWorkingCopy()}.
  * </p><p>
  * Since 2.1, a working copy can be created on a not-yet existing compilation
  * unit. In particular, such a working copy can then be committed in order to create
@@ -420,14 +422,14 @@
  * Returns a shared working copy on this compilation unit using the given working copy owner to create
  * the buffer, or this compilation unit if it is already a non-primary working copy.
  * This API can only answer an already existing working copy if it is based on the same
- * original compilation unit AND was using the same working copy owner (that is, as defined by <code>Object.equals</code>).	 
+ * original compilation unit AND was using the same working copy owner (that is, as defined by {@link Object#equals}).	 
  * <p>
  * The life time of a shared working copy is as follows:
  * <ul>
- * <li>The first call to <code>getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)</code> 
+ * <li>The first call to {@link #getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)} 
  * 	creates a new working copy for this element</li>
  * <li>Subsequent calls increment an internal counter.</li>
- * <li>A call to <code>discardWorkingCopy()</code> decrements the internal counter.</li>
+ * <li>A call to {@link #discardWorkingCopy()} decrements the internal counter.</li>
  * <li>When this counter is 0, the working copy is discarded.
  * </ul>
  * So users of this method must discard exactly once the working copy.
@@ -479,7 +481,7 @@
  * Reconciles the contents of this working copy, sends out a Java delta
  * notification indicating the nature of the change of the working copy since
  * the last time it was either reconciled or made consistent 
- * (see <code>IOpenable#makeConsistent()</code>), and returns a
+ * ({@link IOpenable#makeConsistent(IProgressMonitor)}), and returns a
  * compilation unit AST if requested.
  * <p>
  * It performs the reconciliation by locally caching the contents of 
@@ -499,7 +501,7 @@
  * </p>
  * <p>
  * Compilation problems found in the new contents are notified through the
- * <code>IProblemRequestor</code> interface which was passed at
+ * {@link IProblemRequestor} interface which was passed at
  * creation, and no longer as transient markers.
  * </p>
  * <p>
@@ -543,7 +545,7 @@
  * is not a working copy.
  *
  * <p>Note: This is the inverse of committing the content of the
- * working copy to the original element with <code>commit(boolean, IProgressMonitor)</code>.
+ * working copy to the original element with {@link #commitWorkingCopy(boolean, IProgressMonitor)}.
  *
  * @throws JavaModelException if the contents of the original element
  *		cannot be accessed.  Reasons include:
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompletionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompletionRequestor.java
index 489e0e1..d387520 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompletionRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompletionRequestor.java
@@ -21,8 +21,8 @@
  *
  * @see ICodeAssist
  * @since 2.0
+ * @deprecated Use {@link CompletionRequestor} instead.
  */
-// TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link CompletionRequestor}, an abstract class with all the same methods (and more).
 public interface ICompletionRequestor {
 /**
  * Code assist notification of an anonymous type declaration completion.
@@ -54,8 +54,9 @@
  *    The default package is represented by an empty array.
  *
  * NOTE: parameter names can be retrieved from the source model after the user selects a specific method.
+ * 
+ * @deprecated Use {@link CompletionRequestor#accept(CompletionProposal)} instead.
  */
-// TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link CompletionRequestor#acceptAnonymousType(char[], char[], char[][], char[][], char[][], char[], int, int, int, int)} instead.
 void acceptAnonymousType(
 	char[] superTypePackageName,
 	char[] superTypeName,
@@ -85,8 +86,9 @@
  *    Package names are in the form "a.b.c".
  *    Nested type names are in the qualified form "A.M".
  *    The default package is represented by an empty array.
+ *    
+ * @deprecated Use {@link CompletionRequestor#accept(CompletionProposal)} instead.
  */
-// TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link CompletionRequestor#acceptClass(char[], char[], char[], int, int, int, int)} instead.
 void acceptClass(
 	char[] packageName,
 	char[] className,
@@ -105,8 +107,9 @@
  *		detected (might be in another compilation unit, if it was indirectly requested
  *		during the code assist process).
  *      Note: the problem knows its originating file name.
+ *      
+ * @deprecated Use {@link CompletionRequestor#completionFailure(IProblem)} instead.
  */
-// TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link CompletionRequestor#acceptError(IProblem)} instead.
 void acceptError(IProblem error);
 /**
  * Code assist notification of a field completion.
@@ -131,8 +134,9 @@
  *    Array types are in the qualified form "M[]" or "int[]".
  *    Nested type names are in the qualified form "A.M".
  *    The default package is represented by an empty array.
+ *
+ * @deprecated Use {@link CompletionRequestor#accept(CompletionProposal)} instead.
  */
-// TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link CompletionRequestor#acceptField(char[], char[], char[], char[], char[], char[], int, int, int, int)} instead.
 void acceptField(
 	char[] declaringTypePackageName,
 	char[] declaringTypeName,
@@ -162,8 +166,9 @@
  *    Package names are in the form "a.b.c".
  *    Nested type names are in the qualified form "A.M".
  *    The default package is represented by an empty array.
+ *    
+ * @deprecated Use {@link CompletionRequestor#accept(CompletionProposal)} instead.
  */
-// TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link CompletionRequestor#acceptInterface(char[], char[], char[], int, int, int, int)} instead.
 void acceptInterface(
 	char[] packageName,
 	char[] interfaceName,
@@ -181,8 +186,8 @@
  * 		It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
  * 		This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
  * 		value is higher.
+ * @deprecated Use {@link CompletionRequestor#accept(CompletionProposal)} instead.
  */
-// TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link CompletionRequestor#acceptKeyword(char[], int, int, int)} instead.
 void acceptKeyword(char[] keywordName, int completionStart, int completionEnd, int relevance);
 /**
  * Code assist notification of a label completion.
@@ -194,8 +199,8 @@
  * 		It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
  * 		This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
  * 		value is higher.
+ * @deprecated Use {@link CompletionRequestor#accept(CompletionProposal)} instead.
  */
-// TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link CompletionRequestor#acceptLabel(char[], int, int, int)} instead.
 void acceptLabel(char[] labelName, int completionStart, int completionEnd, int relevance);
 /**
  * Code assist notification of a local variable completion.
@@ -217,8 +222,9 @@
  *    Array types are in the qualified form "M[]" or "int[]".
  *    Nested type names are in the qualified form "A.M".
  *    The default package is represented by an empty array.
+ *    
+ * @deprecated Use {@link CompletionRequestor#accept(CompletionProposal)} instead.
  */
-// TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link CompletionRequestor#acceptLocalVariable(char[], char[], char[], int, int, int, int)} instead.
 void acceptLocalVariable(
 	char[] name,
 	char[] typePackageName,
@@ -258,8 +264,9 @@
  *    The default package is represented by an empty array.
  *
  * NOTE: parameter names can be retrieved from the source model after the user selects a specific method.
+ * 
+ * @deprecated Use {@link CompletionRequestor#accept(CompletionProposal)} instead.
  */
-// TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link CompletionRequestor#acceptMethod(char[], char[], char[], char[][], char[][], char[][], char[], char[], char[], int, int, int, int)} instead.
 void acceptMethod(
 	char[] declaringTypePackageName,
 	char[] declaringTypeName,
@@ -306,8 +313,9 @@
  *    The default package is represented by an empty array.
  *
  * NOTE: parameter names can be retrieved from the source model after the user selects a specific method.
+ * 
+ * @deprecated Use {@link CompletionRequestor#accept(CompletionProposal)} instead.
  */
-// TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link CompletionRequestor#acceptMethodDeclaration(char[], char[], char[], char[][], char[][], char[][], char[], char[], char[], int, int, int, int)} instead.
 void acceptMethodDeclaration(
 	char[] declaringTypePackageName,
 	char[] declaringTypeName,
@@ -332,8 +340,8 @@
  * 		It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
  * 		This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
  * 		value is higher.
+ * @deprecated Use {@link CompletionRequestor#accept(CompletionProposal)} instead.
  */
-// TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link CompletionRequestor#acceptModifier(char[], int, int, int)} instead.
 void acceptModifier(char[] modifierName, int completionStart, int completionEnd, int relevance);
 /**
  * Code assist notification of a package completion.
@@ -350,8 +358,8 @@
  * NOTE - All package names are presented in their readable form:
  *    Package names are in the form "a.b.c".
  *    The default package is represented by an empty array.
+ * @deprecated Use {@link CompletionRequestor#accept(CompletionProposal)} instead.
  */
-// TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link CompletionRequestor#acceptPackage(char[], char[], int, int, int)} instead.
 void acceptPackage(
 	char[] packageName,
 	char[] completionName,
@@ -375,8 +383,8 @@
  *    Package names are in the form "a.b.c".
  *    Nested type names are in the qualified form "A.M".
  *    The default package is represented by an empty array.
+ * @deprecated Use {@link CompletionRequestor#accept(CompletionProposal)} instead.
  */
-// TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link CompletionRequestor#acceptType(char[], char[], char[], int, int, int)} instead.
 void acceptType(
 	char[] packageName,
 	char[] typeName,
@@ -405,8 +413,8 @@
  *    Array types are in the qualified form "M[]" or "int[]".
  *    Nested type names are in the qualified form "A.M".
  *    The default package is represented by an empty array.
+ * @deprecated Use {@link CompletionRequestor#accept(CompletionProposal)} instead.
  */
-// TODO (jerome - once CompletionRequestor is working) @ deprecated Use {@link CompletionRequestor#acceptTypeVariable(char[], int, int, int)} instead.
 void acceptVariableName(
 	char[] typePackageName,
 	char[] typeName,
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java
index 851a290..c55c7fb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java
@@ -117,6 +117,13 @@
 	 * @since 3.0
 	 */
 	int LOCAL_VARIABLE = 14;
+	
+	/**
+	 * Constant representing a type parameter declaration.
+	 * A Java element with this type can be safely cast to <code>ITypeParameter</code>.
+	 * @since 3.1
+	 */
+	int TYPE_PARAMETER = 15;
 
 	/**
 	 * Returns whether this Java element exists in the model.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java
index 876b341..d29c6e2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java
@@ -297,4 +297,14 @@
 	 * @since 3.0
 	 */
 	public static final int COMPILER_FAILURE	= 1005;	
+	/**
+	 * Status constant indicating that an element is not on its project's claspath.
+	 * @since 3.1
+	 */
+	public static final int ELEMENT_NOT_ON_CLASSPATH	= 1006;	
+	/**
+	 * Status constant indicating that a compiler option is invalid.
+	 * @since 3.1
+	 */
+//	public static final int INVALID_COMPILER_OPTION = 1007;	
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMethod.java
index b36e650..d12fc3b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMethod.java
@@ -65,9 +65,20 @@
  * in the order declared in the source, an empty array if none
  * @see Signature
  * @since 3.0
+ * @deprecated Use #getTypeParameters() instead
  */
 String[] getTypeParameterSignatures() throws JavaModelException;
-
+/**
+ * Returns the formal type parameters for this method.
+ * Returns an empty array if this method has no formal type parameters.
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ *      exception occurs while accessing its corresponding resource.
+ * @return the formal type parameters of this method,
+ * in the order declared in the source, an empty array if none
+ * @since 3.1
+ */
+ITypeParameter[] getTypeParameters() throws JavaModelException;
 /**
  * Returns the number of parameters of this method.
  * This is a handle-only method.
@@ -149,6 +160,15 @@
  */
 String getSignature() throws JavaModelException;
 /**
+ * Returns the type parameter declared in this method with the given name.
+ * This is a handle-only method. The type parameter may or may not exist.
+ * 
+ * @param name the given simple name
+ * @return the type parameter declared in this methid with the given name
+ * @since 3.1
+ */
+ITypeParameter getTypeParameter(String name);
+/**
  * Returns whether this method is a constructor.
  *
  * @exception JavaModelException if this element does not exist or if an
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IOpenable.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IOpenable.java
index 930e063..c221c91 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IOpenable.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IOpenable.java
@@ -17,7 +17,7 @@
  * navigated or modified. Opening a textual element (such as a compilation unit)
  * involves opening a buffer on its contents.  While open, any changes to the buffer
  * can be reflected in the element's structure; 
- * see <code>isConsistent</code> and <code>makeConsistent(IProgressMonitor)</code>.
+ * see {@link #isConsistent} and {@link #makeConsistent(IProgressMonitor)}.
  * <p>
  * To reduce complexity in clients, elements are automatically opened
  * by the Java model as element properties are accessed. The Java model maintains
@@ -33,7 +33,7 @@
  * To open an element, all openable parent elements must be open.
  * The Java model automatically opens parent elements, as it automatically opens elements.
  * Opening an element may provide access to direct children and other descendants,
- * but does not automatically open any descendents which are themselves <code>IOpenable</code>.
+ * but does not automatically open any descendents which are themselves {@link IOpenable}.
  * For example, opening a compilation unit provides access to all its constituent elements,
  * but opening a package fragment does not open all compilation units in the package fragment.
  * </p>
@@ -47,7 +47,7 @@
  * Closes this element and its buffer (if any).
  * Closing an element which is not open has no effect.
  *
- * <p>Note: although <code>close</code> is exposed in the API, clients are
+ * <p>Note: although {@link #close} is exposed in the API, clients are
  * not expected to open and close elements - the Java model does this automatically
  * as elements are accessed.
  *
@@ -110,9 +110,9 @@
  * by updating the element's structure and properties as necessary.
  *<p>
  * Note: Using this functionality on a working copy will interfere with any
- * subsequent reconciling operation. Indeed, the next <code>ICompilationUnit#reconcile()</code> 
+ * subsequent reconciling operation. Indeed, the next {@link ICompilationUnit#reconcile}
  * operation will not account for changes which occurred before an
- * explicit use of <code>#makeConsistent(IProgressMonitor)</code>
+ * explicit use of {@link #makeConsistent(IProgressMonitor)}
  * <p>
  * @param progress the given progress monitor
  * @exception JavaModelException if the element is unable to access the contents
@@ -128,7 +128,7 @@
  * Opens this element and all parent elements that are not already open.
  * For compilation units, a buffer is opened on the contents of the underlying resource.
  *
- * <p>Note: although <code>open</code> is exposed in the API, clients are
+ * <p>Note: although {@link #open} is exposed in the API, clients are
  * not expected to open and close elements - the Java model does this automatically
  * as elements are accessed.
  *
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
index 0c7ac6a..7cb804d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
@@ -61,6 +61,7 @@
 	 * @exception JavaModelException if this element does not exist or if an
 	 *		exception occurs while accessing its corresponding resource.
 	 * @since 2.0
+	 * @deprecated Use {@link #codeComplete(char[],int,int,char[][],char[][],int[],boolean,CompletionRequestor)} instead.
 	 */
 	void codeComplete(
 		char[] snippet,
@@ -105,6 +106,7 @@
 	 * @exception JavaModelException if this element does not exist or if an
 	 *		exception occurs while accessing its corresponding resource.
 	 * @since 3.0
+	 * @deprecated Use {@link #codeComplete(char[],int,int,char[][],char[][],int[],boolean,CompletionRequestor,WorkingCopyOwner)} instead.
 	 */
 	void codeComplete(
 		char[] snippet,
@@ -117,7 +119,87 @@
 		ICompletionRequestor requestor,
 		WorkingCopyOwner owner)
 		throws JavaModelException;
+	
+	/**
+	 * Do code completion inside a code snippet in the context of the current type.
+	 * 
+	 * If the type can access to his source code and the insertion position is valid,
+	 * then completion is performed against source. Otherwise the completion is performed
+	 * against type structure and given locals variables.
+	 * 
+	 * @param snippet the code snippet
+	 * @param insertion the position with in source where the snippet
+	 * is inserted. This position must not be in comments.
+	 * A possible value is -1, if the position is not known.
+	 * @param position the position within snippet where the user 
+	 * is performing code assist.
+	 * @param localVariableTypeNames an array (possibly empty) of fully qualified 
+	 * type names of local variables visible at the current scope
+	 * @param localVariableNames an array (possibly empty) of local variable names 
+	 * that are visible at the current scope
+	 * @param localVariableModifiers an array (possible empty) of modifiers for 
+	 * local variables
+	 * @param isStatic whether the current scope is in a static context
+	 * @param requestor the completion requestor
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource.
+	 * @since 3.1
+	 */
+	void codeComplete(
+		char[] snippet,
+		int insertion,
+		int position,
+		char[][] localVariableTypeNames,
+		char[][] localVariableNames,
+		int[] localVariableModifiers,
+		boolean isStatic,
+		CompletionRequestor requestor)
+		throws JavaModelException;
 
+	/**
+	 * Do code completion inside a code snippet in the context of the current type.
+	 * It considers types in the working copies with the given owner first. In other words, 
+	 * the owner's working copies will take precedence over their original compilation units
+	 * in the workspace.
+	 * <p>
+	 * Note that if a working copy is empty, it will be as if the original compilation
+	 * unit had been deleted.
+	 * </p><p>
+	 * If the type can access to his source code and the insertion position is valid,
+	 * then completion is performed against source. Otherwise the completion is performed
+	 * against type structure and given locals variables.
+	 * </p>
+	 * 
+	 * @param snippet the code snippet
+	 * @param insertion the position with in source where the snippet
+	 * is inserted. This position must not be in comments.
+	 * A possible value is -1, if the position is not known.
+	 * @param position the position with in snippet where the user 
+	 * is performing code assist.
+	 * @param localVariableTypeNames an array (possibly empty) of fully qualified 
+	 * type names of local variables visible at the current scope
+	 * @param localVariableNames an array (possibly empty) of local variable names 
+	 * that are visible at the current scope
+	 * @param localVariableModifiers an array (possible empty) of modifiers for 
+	 * local variables
+	 * @param isStatic whether the current scope is in a static context
+	 * @param requestor the completion requestor
+	 * @param owner the owner of working copies that take precedence over their original compilation units
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource.
+	 * @since 3.1
+	 */
+	void codeComplete(
+		char[] snippet,
+		int insertion,
+		int position,
+		char[][] localVariableTypeNames,
+		char[][] localVariableNames,
+		int[] localVariableModifiers,
+		boolean isStatic,
+		CompletionRequestor requestor,
+		WorkingCopyOwner owner)
+		throws JavaModelException;
 
 
 	/**
@@ -334,6 +416,17 @@
 	String getFullyQualifiedName(char enclosingTypeSeparator);
 	
 	/**
+	 * Returns this type's fully qualified name followed by its type parameters between angle brakets if it is a generic type.
+	 * For example, "p.X<T>", "java.util.Map<java.lang.String, p.X>"
+	 * 
+	 * @exception JavaModelException if this element does not exist or if an
+	 *      exception occurs while accessing its corresponding resource.
+	 * @return the fully qualified parameterized representation of this type
+	 * @since 3.1
+	 */
+	String getFullyQualifiedParameterizedName() throws JavaModelException;
+
+	/**
 	 * Returns the initializer with the specified position relative to
 	 * the order they are defined in the source.
 	 * Numbering starts at 1 (thus the first occurrence is occurrence 1, not occurrence 0).
@@ -499,8 +592,21 @@
 	 * in the order declared in the source, an empty array if none
 	 * @see Signature
 	 * @since 3.0
+	 * @deprecated Use #getTypeParameters() instead
 	 */
 	String[] getTypeParameterSignatures() throws JavaModelException;
+	
+	/**
+	 * Returns the formal type parameters for this type.
+	 * Returns an empty array if this type has no formal type parameters.
+	 *
+	 * @exception JavaModelException if this element does not exist or if an
+	 *      exception occurs while accessing its corresponding resource.
+	 * @return the formal type parameters of this type,
+	 * in the order declared in the source, an empty array if none
+	 * @since 3.1
+	 */
+	ITypeParameter[] getTypeParameters() throws JavaModelException;
 
 	/**
 	 * Returns the member type declared in this type with the given simple name.
@@ -512,6 +618,16 @@
 	IType getType(String name);
 	
 	/**
+	 * Returns the type parameter declared in this type with the given name.
+	 * This is a handle-only method. The type parameter may or may not exist.
+	 * 
+	 * @param name the given simple name
+	 * @return the type parameter declared in this type with the given name
+	 * @since 3.1
+	 */
+	ITypeParameter getTypeParameter(String name);
+	
+	/**
 	 * Returns the type-qualified name of this type, 
 	 * including qualification for any enclosing types,
 	 * but not including package qualification.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeParameter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeParameter.java
new file mode 100644
index 0000000..cac2888
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeParameter.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core;
+
+
+/**
+ * Represents a type parameter defined by a type of a method
+ * in a compilation unit or a class file.
+ * <p>
+ * Type parameters are obtained using {@link IType#getTypeParameter(String)} and
+ * {@link IMethod#getTypeParameter(String)}.
+ * </p><p>
+ * Note that type parameters are not children of their declaring type or method. To get a list
+ * of the type parameters use {@link IType#getTypeParameters()} for a type and use
+ * {@link IMethod#getTypeParameters()} for a method.
+ * </p>
+ *
+ * @since 3.1
+ */
+public interface ITypeParameter extends IJavaElement, ISourceReference {
+
+	/**
+	 * Returns the names of the class and interface bounds of this type parameter. Returns an empty
+	 * array if this type parameter has no bounds. A bound name is the name as it appears in the
+	 * source (without the <code>extends</code> keyword) if the type parameter comes from a
+	 * compilation unit. It is the dot-separated fully qualified name of the bound if the type
+	 * parameter comes from a class file.
+	 * 
+	 * @return the names of the bounds
+	 * @throws JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource
+	 */
+	String[] getBounds() throws JavaModelException;
+	
+	/**
+	 * Returns the declaring member of this type parameter. This can be either an <code>IType</code>
+	 * or an <code>IMethod</code>.
+	 * <p>
+	 * This is a handle-only method.
+	 * </p>
+	 * 
+	 * @return the declaring member of this type parameter.
+	 */
+	IMember getDeclaringMember();
+	
+	/**
+	 * Returns the source range of this type parameter's name,
+	 * or <code>null</code> if this type parameter does not have
+	 * associated source code (for example, in a binary type).
+	 *
+	 * @exception JavaModelException if this element does not exist or if an
+	 *      exception occurs while accessing its corresponding resource.
+	 * @return the source range of this type parameter's name,
+	 * or <code>null</code> if this type parameter does not have
+	 * associated source code (for example, in a binary type)
+	 */
+	ISourceRange getNameRange() throws JavaModelException;
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
index 5188437..6c7e56d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
@@ -127,7 +127,7 @@
 		if (name == null) {
 			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("convention.unit.nullName"), null); //$NON-NLS-1$
 		}
-		if (!org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(name)) {
+		if (!org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(name)) {
 			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("convention.unit.notJavaName"), null); //$NON-NLS-1$
 		}
 		String identifier;
@@ -367,6 +367,7 @@
 		IWorkspace workspace = ResourcesPlugin.getWorkspace();
 		StringTokenizer st = new StringTokenizer(name, new String(new char[] {DOT}));
 		boolean firstToken = true;
+		IStatus warningStatus = null;
 		while (st.hasMoreTokens()) {
 			String typeName = st.nextToken();
 			typeName = typeName.trim(); // grammar allows spaces
@@ -379,10 +380,15 @@
 				return status;
 			}
 			if (firstToken && scannedID.length > 0 && Character.isUpperCase(scannedID[0])) {
-				return new Status(IStatus.WARNING, JavaCore.PLUGIN_ID, -1, Util.bind("convention.package.uppercaseName"), null); //$NON-NLS-1$
+				if (warningStatus == null) {
+					warningStatus = new Status(IStatus.WARNING, JavaCore.PLUGIN_ID, -1, Util.bind("convention.package.uppercaseName"), null); //$NON-NLS-1$
+				}
 			}
 			firstToken = false;
 		}
+		if (warningStatus != null) {
+			return warningStatus;
+		}
 		return JavaModelStatus.VERIFIED_OK;
 	}
 	
@@ -421,7 +427,7 @@
 
 		return ClasspathEntry.validateClasspath(javaProject, rawClasspath, projectOutputLocation);
 	}
-	
+
 	/**
 	 * Returns a Java model status describing the problem related to this classpath entry if any, 
 	 * a status object with code <code>IStatus.OK</code> if the entry is fine (that is, if the
@@ -436,4 +442,159 @@
 	public static IJavaModelStatus validateClasspathEntry(IJavaProject project, IClasspathEntry entry, boolean checkSourceAttachment){
 		return ClasspathEntry.validateClasspathEntry(project, entry, checkSourceAttachment, true/*recurse in container*/);
 	}
+
+	/**
+	 * Validate that all compiler options of the given project match keys and values
+	 * described in {@link JavaCore#getDefaultOptions()} method.
+	 * 
+	 * @param javaProject the given java project
+	 * @param inheritJavaCoreOptions inherit project options from JavaCore or not.
+	 * @return a status object with code <code>IStatus.OK</code> if all project
+	 *		compiler options are valid, otherwise a status object indicating what is wrong
+	 *		with the keys and their value.
+	 * @since 3.1
+	 * TODO (frederic) finalize for all possible options (JavaCore, DefaultCodeFormatterOptions, AssistOptions) and open to API
+	 */
+	/*
+	public static IStatus validateCompilerOptions(IJavaProject javaProject, boolean inheritJavaCoreOptions)	  {
+		return validateCompilerOptions(javaProject.getOptions(inheritJavaCoreOptions));
+	}
+	*/
+	
+	/**
+	 * Validate that all compiler options of the given project match keys and values
+	 * described in {@link JavaCore#getDefaultOptions()} method.
+	 * 
+	 * @param compilerOptions Map of options
+	 * @return a status object with code <code>IStatus.OK</code> if all 
+	 *		compiler options are valid, otherwise a status object indicating what is wrong
+	 *		with the keys and their value.
+	 * @since 3.1
+	 */
+	/*
+	public static IStatus validateCompilerOptions(Map compilerOptions)	  {
+
+		// Get current options
+		String compliance = (String) compilerOptions.get(JavaCore.COMPILER_COMPLIANCE);
+		String source = (String) compilerOptions.get(JavaCore.COMPILER_SOURCE);
+		String target = (String) compilerOptions.get(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM);
+		if (compliance == null && source == null && target == null) {
+			return JavaModelStatus.VERIFIED_OK; // default is OK
+		}
+		
+		// Initialize multi-status
+		List errors = new ArrayList();
+		
+		// Set default for compliance if necessary (not set on project and not inherited...)
+		if (compliance == null) {
+			compliance = JavaCore.getOption(JavaCore.COMPILER_COMPLIANCE);
+		}
+		
+		// Verify compliance level value and set source and target default if necessary
+		long complianceLevel = 0;
+		long sourceLevel = 0;
+		long targetLevel = 0;
+		if (JavaCore.VERSION_1_3.equals(compliance)) {
+			complianceLevel = ClassFileConstants.JDK1_3;
+			if (source == null) {
+				source = JavaCore.VERSION_1_3;
+				sourceLevel = ClassFileConstants.JDK1_3;
+			}
+			if (target == null) {
+				target = JavaCore.VERSION_1_1;
+				targetLevel = ClassFileConstants.JDK1_1;
+			}
+		} else if (JavaCore.VERSION_1_4.equals(compliance)) {
+			complianceLevel = ClassFileConstants.JDK1_4;
+			if (source == null) {
+				source = JavaCore.VERSION_1_3;
+				sourceLevel = ClassFileConstants.JDK1_3;
+			}
+			if (target == null) {
+				target = JavaCore.VERSION_1_2;
+				targetLevel = ClassFileConstants.JDK1_2;
+			}
+		} else if (JavaCore.VERSION_1_5.equals(compliance)) {
+			complianceLevel = ClassFileConstants.JDK1_5;
+			if (source == null) {
+				source = JavaCore.VERSION_1_5;
+				sourceLevel = ClassFileConstants.JDK1_5;
+			}
+			if (target == null) {
+				target = JavaCore.VERSION_1_5;
+				targetLevel = ClassFileConstants.JDK1_5;
+			}
+		} else {
+			// compliance is not valid
+			errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.invalidCompilerOption", compliance==null?"":compliance, JavaCore.COMPILER_COMPLIANCE))); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+
+		// Verify source value and set default for target if necessary
+		 if (JavaCore.VERSION_1_4.equals(source)) {
+			sourceLevel = ClassFileConstants.JDK1_4;
+			if (target == null) {
+				target = JavaCore.VERSION_1_4;
+				targetLevel = ClassFileConstants.JDK1_4;
+			}
+		} else if (JavaCore.VERSION_1_5.equals(source)) {
+			sourceLevel = ClassFileConstants.JDK1_5;
+			if (target == null) {
+				target = JavaCore.VERSION_1_5;
+				targetLevel = ClassFileConstants.JDK1_5;
+			}
+		} else if (JavaCore.VERSION_1_3.equals(source)) {
+			sourceLevel = ClassFileConstants.JDK1_3;
+		} else {
+			// source is not valid
+			errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.invalidCompilerOption", source==null?"":source, JavaCore.COMPILER_SOURCE))); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+
+		// Verify target value
+		 if (targetLevel == 0) {
+			 targetLevel = CompilerOptions.versionToJdkLevel(target);
+			 if (targetLevel == 0) {
+				// target is not valid
+				errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.invalidCompilerOption", target==null?"":target, JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM))); //$NON-NLS-1$ //$NON-NLS-2$
+			 }
+		}
+
+		// Check and set compliance/source/target compatibilities (only if they have valid values)
+		if (complianceLevel != 0 && sourceLevel != 0 && targetLevel != 0) {
+			// target must be 1.5 if source is 1.5
+			if (sourceLevel >= ClassFileConstants.JDK1_5 && targetLevel < ClassFileConstants.JDK1_5) {
+				errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.incompatibleTargetForSource", target, JavaCore.VERSION_1_5))); //$NON-NLS-1$
+			}
+	   		else
+		   		// target must be 1.4 if source is 1.4
+	   			if (sourceLevel >= ClassFileConstants.JDK1_4 && targetLevel < ClassFileConstants.JDK1_4) {
+					errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.incompatibleTargetForSource", target, JavaCore.VERSION_1_4))); //$NON-NLS-1$
+	   		}
+			// target cannot be greater than compliance level
+			if (complianceLevel < targetLevel){ 
+				errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.incompatibleComplianceForTarget", compliance, JavaCore.VERSION_1_4))); //$NON-NLS-1$
+			}
+			// compliance must be 1.5 if source is 1.5
+			if (source.equals(JavaCore.VERSION_1_5) && complianceLevel < ClassFileConstants.JDK1_5) {
+				errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.incompatibleComplianceForSource", compliance, JavaCore.VERSION_1_5))); //$NON-NLS-1$
+			} else 
+				// compliance must be 1.4 if source is 1.4
+				if (source.equals(JavaCore.VERSION_1_4) && complianceLevel < ClassFileConstants.JDK1_4) { 
+					errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.incompatibleComplianceForSource", compliance, JavaCore.VERSION_1_4))); //$NON-NLS-1$
+			}
+		}
+
+		// Return status
+		int size = errors.size();
+		switch (size) {
+			case 0:
+				return JavaModelStatus.VERIFIED_OK;
+			case 1:
+				return (IStatus) errors.get(0);
+			default:
+				IJavaModelStatus[] allStatus = new IJavaModelStatus[size];
+				errors.toArray(allStatus);
+				return JavaModelStatus.newMultiStatus(allStatus);
+		}
+	}
+	*/
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
index b586249..7c8013d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
@@ -64,13 +64,16 @@
 import org.eclipse.core.runtime.*;
 import org.eclipse.core.runtime.jobs.ISchedulingRule;
 import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.InstanceScope;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.util.MementoTokenizer;
 import org.eclipse.jdt.internal.core.util.Util;
 import org.osgi.framework.BundleContext;
+import org.osgi.service.prefs.BackingStoreException;
 
 /**
  * The plug-in runtime class for the Java model plug-in containing the core
@@ -262,6 +265,12 @@
 	/**
 	 * Possible  configurable option ID.
 	 * @see #getDefaultOptions()
+	 * @since 3.1
+	 */
+	public static final String COMPILER_PB_ENUM_IDENTIFIER = PLUGIN_ID + ".compiler.problem.enumIdentifier"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String COMPILER_PB_STATIC_ACCESS_RECEIVER = PLUGIN_ID + ".compiler.problem.staticAccessReceiver"; //$NON-NLS-1$
@@ -370,6 +379,43 @@
 	/**
 	 * Possible  configurable option ID.
 	 * @see #getDefaultOptions()
+	 * @deprecated - got renamed into {@link #COMPILER_PB_UNCHECKED_TYPE_OPERATION}
+	 * @since 3.1
+	 */
+	public static final String COMPILER_PB_UNSAFE_TYPE_OPERATION = PLUGIN_ID + ".compiler.problem.uncheckedTypeOperation"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.1
+	 */
+	public static final String COMPILER_PB_UNCHECKED_TYPE_OPERATION = PLUGIN_ID + ".compiler.problem.uncheckedTypeOperation"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.1
+	 */
+	public static final String COMPILER_PB_FINAL_PARAMETER_BOUND = PLUGIN_ID + ".compiler.problem.finalParameterBound"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.1
+	 */
+	public static final String COMPILER_PB_MISSING_SERIAL_VERSION = PLUGIN_ID + ".compiler.problem.missingSerialVersion"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.1
+	 */
+	public static final String COMPILER_PB_VARARGS_ARGUMENT_NEED_CAST = PLUGIN_ID + ".compiler.problem.varargsArgumentNeedCast"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.1
+	 */
+	public static final String COMPILER_PB_INCONSISTENT_NULL_CHECK = PLUGIN_ID + ".compiler.problem.inconsistentNullCheck"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
 	 * @since 3.0
 	 */
 	public static final String COMPILER_PB_INVALID_JAVADOC = PLUGIN_ID + ".compiler.problem.invalidJavadoc"; //$NON-NLS-1$
@@ -384,6 +430,18 @@
 	 * @see #getDefaultOptions()
 	 * @since 3.0
 	 */
+	public static final String COMPILER_PB_INVALID_JAVADOC_TAGS__DEPRECATED_REF = PLUGIN_ID + ".compiler.problem.invalidJavadocTagsDeprecatedRef"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_INVALID_JAVADOC_TAGS__NOT_VISIBLE_REF = PLUGIN_ID + ".compiler.problem.invalidJavadocTagsNotVisibleRef"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
 	public static final String COMPILER_PB_INVALID_JAVADOC_TAGS_VISIBILITY = PLUGIN_ID + ".compiler.problem.invalidJavadocTagsVisibility"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
@@ -484,6 +542,12 @@
 	/**
 	 * Possible  configurable option ID.
 	 * @see #getDefaultOptions()
+	 * @since 3.1
+	 */
+	public static final String COMPILER_PB_FORBIDDEN_REFERENCE = PLUGIN_ID + ".compiler.problem.forbiddenReference"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
 	 */
 	public static final String CORE_JAVA_BUILD_ORDER = PLUGIN_ID + ".computeJavaBuildOrder"; //$NON-NLS-1$
 	/**
@@ -703,7 +767,13 @@
 	 * @since 2.1
 	 */
 	public static final String CODEASSIST_ARGUMENT_SUFFIXES = PLUGIN_ID + ".codeComplete.argumentSuffixes"; //$NON-NLS-1$
-
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.1
+	 */
+	public static final String CODEASSIST_RESTRICTIONS_CHECK = PLUGIN_ID + ".codeComplete.restrictionsCheck"; //$NON-NLS-1$
+	
 	// *************** Possible values for configurable options. ********************
 	
 	/**
@@ -872,6 +942,14 @@
 	public static final String PRIVATE = "private"; //$NON-NLS-1$
 	
 	/**
+	 * New Preferences API
+	 * @since 3.1
+	 */
+	public static final IEclipsePreferences[] preferencesLookup = new IEclipsePreferences[2];
+	static final int PREF_INSTANCE = 0;
+	static final int PREF_DEFAULT = 1;
+
+	/**
 	 * Creates the Java core plug-in.
 	 * <p>
 	 * The plug-in instance is created automatically by the 
@@ -1399,6 +1477,33 @@
 	 * Note: more options might be added in further releases.
 	 * <pre>
 	 * RECOGNIZED OPTIONS:
+	 * 
+	 * COMPILER / Setting Compliance Level
+	 *    Select the compliance level for the compiler. In "1.3" mode, source and target settings
+	 *    should not go beyond "1.3" level.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.compliance"
+	 *     - possible values:   { "1.3", "1.4", "1.5" }
+	 *     - default:           "1.4"
+	 * 
+	 * COMPILER / Setting Source Compatibility Mode
+	 *    Specify whether which source level compatibility is used. From 1.4 on, 'assert' is a keyword
+	 *    reserved for assertion support. Also note, than when toggling to 1.4 mode, the target VM
+	 *   level should be set to "1.4" and the compliance mode should be "1.4".
+	 *   Source level 1.5 is necessary to enable generics, autoboxing, covariance, annotations, enumerations
+	 *   enhanced for loop, static imports and varargs. Once toggled, the target VM level should be set to "1.5"
+	 *   and the compliance mode should be "1.5".
+	 *     - option id:         "org.eclipse.jdt.core.compiler.source"
+	 *     - possible values:   { "1.3", "1.4", "1.5" }
+	 *     - default:           "1.3"
+	 * 
+	 * COMPILER / Defining Target Java Platform
+	 *    For binary compatibility reason, .class files can be tagged to with certain VM versions and later.
+	 *    Note that "1.4" target require to toggle compliance mode to "1.4" too. Similarily, "1.5" target require
+	 *    to toggle compliance mode to "1.5".
+	 *     - option id:         "org.eclipse.jdt.core.compiler.codegen.targetPlatform"
+	 *     - possible values:   { "1.1", "1.2", "1.3", "1.4", "1.5" }
+	 *     - default:           "1.2"
+	 *
 	 * COMPILER / Generating Local Variable Debug Attribute
  	 *    When generated, this attribute will enable local variable names 
 	 *    to be displayed in debugger, only in place where variables are 
@@ -1428,18 +1533,13 @@
 	 *     - possible values:   { "preserve", "optimize out" }
 	 *     - default:           "preserve"
 	 * 
-	 * COMPILER / Defining Target Java Platform
-	 *    For binary compatibility reason, .class files can be tagged to with certain VM versions and later.
-	 *    Note that "1.4" target require to toggle compliance mode to "1.4" too.
-	 *     - option id:         "org.eclipse.jdt.core.compiler.codegen.targetPlatform"
-	 *     - possible values:   { "1.1", "1.2", "1.3", "1.4" }
-	 *     - default:           "1.2"
-	 *
 	 * COMPILER / Inline JSR Bytecode Instruction
 	 *    When enabled, the compiler will no longer generate JSR instructions, but rather inline corresponding
 	 *   subroutine code sequences (mostly corresponding to try finally blocks). The generated code will thus
 	 *   get bigger, but will load faster on virtual machines since the verification process is then much simpler. 
 	 *  This mode is anticipating support for the Java Specification Request 202.
+	 *  Note that JSR inlining is optional only for target platform lesser than 1.5. From 1.5 on, the JSR
+	 *  inlining is mandatory (also see related setting "org.eclipse.jdt.core.compiler.codegen.targetPlatform").
 	 *     - option id:         "org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode"
 	 *     - possible values:   { "enabled", "disabled" }
 	 *     - default:           "disabled"
@@ -1590,7 +1690,14 @@
 	 *    used as an identifier (reserved keyword in 1.4)
 	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.assertIdentifier"
 	 *     - possible values:   { "error", "warning", "ignore" }
-	 *     - default:           "ignore"
+	 *     - default:           "warning"
+	 * 
+	 * COMPILER / Reporting Usage of 'enum' Identifier
+	 *    When enabled, the compiler will issue an error or a warning whenever 'enum' is 
+	 *    used as an identifier (reserved keyword in 1.5)
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.enumIdentifier"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "warning"
 	 * 
 	 * COMPILER / Reporting Non-Static Reference to a Static Member
 	 *    When enabled, the compiler will issue an error or a warning whenever a static field
@@ -1691,6 +1798,53 @@
 	 *     - possible values:   { "error", "warning", "ignore" }
 	 *     - default:           "ignore"
 	 *
+	 * COMPILER / Reporting Unchecked Type Operation
+	 *    When enabled, the compiler will issue an error or a warning whenever an operation involves generic types, and potentially
+	 *    invalidates type safety since involving raw types (e.g. invoking #foo(X<String>) with arguments  (X)).
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "warning"
+	 * 
+	 * COMPILER / Reporting final Bound for Type Parameter
+	 *    When enabled, the compiler will issue an error or a warning whenever a generic type parameter is associated with a 
+	 *    bound corresponding to a final type; since final types cannot be further extended, the parameter is pretty useless.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.finalParameterBound"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 * 
+	 * COMPILER / Reporting Missing Declaration of serialVersionUID Field on Serializable Class
+	 *    When enabled, the compiler will issue an error or a warning whenever a serializable class is missing a local declaration 
+	 *    of a serialVersionUID field. This field must be declared as static final and be of type long.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingSerialVersion"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "warning"
+	 * 
+	 * COMPILER / Reporting Varargs Argument Needing a Cast in Method/Constructor Invocation
+	 *    When enabled, the compiler will issue an error or a warning whenever a varargs arguments should be cast
+	 *    when passed to a method/constructor invocation. (e.g. Class.getMethod(String name, Class ... args )  
+	 *    invoked with arguments ("foo", null)).
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "warning"
+	 * 
+	 * COMPILER / Reporting Null Reference or Dereference
+	 *    When enabled, the compiler will issue an error or a warning whenever assumption were made on a variable
+	 *    with respect to holding null/non-null values, but the assumption is not followed in a consistent manner.
+	 *    Situations include:
+	 *         - if variable was assumed to be null and further used to access field or methods
+	 *         - if variable was assumed to be null or non-null and further tested for null cases.
+	 *         
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.nullReference"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "warning"
+	 * 
+	 * COMPILER / Reporting Boxing/Unboxing Conversion
+	 *    When enabled, the compiler will issue an error or a warning whenever a boxing or an unboxing
+	 *    conversion is performed.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.autoboxing"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 * 
 	 * COMPILER / Reporting Invalid Javadoc Comment
 	 *    This is the generic control for the severity of Javadoc problems.
 	 *    When enabled, the compiler will issue an error or a warning for a problem in Javadoc.
@@ -1715,6 +1869,22 @@
 	 *     - possible values:   { "disabled", "enabled" }
 	 *     - default:           "enabled"
 	 * 
+	 * COMPILER / Reporting Invalid Javadoc Tags with Deprecated References
+	 *    Specify whether the compiler will report deprecated references used in Javadoc tags.
+	 *    <br>Note that this diagnosis can be enabled based on the visibility of the construct associated with the Javadoc;
+	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility".
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef"
+	 *     - possible values:   { "enabled", "disabled" }
+	 *     - default:           "enabled"
+	 * 
+	 * COMPILER / Reporting Invalid Javadoc Tags with Not Visible References
+	 *    Specify whether the compiler will report non-visible references used in Javadoc tags.
+	 *    <br>Note that this diagnosis can be enabled based on the visibility of the construct associated with the Javadoc;
+	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility".
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef"
+	 *     - possible values:   { "enabled", "disabled" }
+	 *     - default:           "enabled"
+	 * 
 	 * COMPILER / Reporting Missing Javadoc Tags
 	 *    This is the generic control for the severity of Javadoc missing tag problems.
 	 *    When enabled, the compiler will issue an error or a warning when tags are missing in Javadoc comments.
@@ -1759,21 +1929,6 @@
 	 *     - possible values:   { "enabled", "disabled" }
 	 *     - default:           "enabled"
 	 * 
-	 * COMPILER / Setting Source Compatibility Mode
-	 *    Specify whether which source level compatibility is used. From 1.4 on, 'assert' is a keyword
-	 *    reserved for assertion support. Also note, than when toggling to 1.4 mode, the target VM
-	 *   level should be set to "1.4" and the compliance mode should be "1.4".
-	 *     - option id:         "org.eclipse.jdt.core.compiler.source"
-	 *     - possible values:   { "1.3", "1.4" }
-	 *     - default:           "1.3"
-	 * 
-	 * COMPILER / Setting Compliance Level
-	 *    Select the compliance level for the compiler. In "1.3" mode, source and target settings
-	 *    should not go beyond "1.3" level.
-	 *     - option id:         "org.eclipse.jdt.core.compiler.compliance"
-	 *     - possible values:   { "1.3", "1.4" }
-	 *     - default:           "1.4"
-	 * 
 	 * COMPILER / Maximum number of problems reported per compilation unit
 	 *    Specify the maximum number of problems reported on each compilation unit.
 	 *     - option id:         "org.eclipse.jdt.core.compiler.maxProblemPerUnit"
@@ -1807,6 +1962,13 @@
 	 *     - possible values:   { "enabled", "disabled" }
 	 *     - default:           "enabled"
 	 *
+	 * COMPILER / Reporting Forbidden Reference to Type with Restricted Access
+	 *    When enabled, the compiler will issue an error or a warning when referring to a type with restricted access, as defined according
+	 *    to the access restriction specifications.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.forbiddenReference"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "warning"
+	 *
 	 * BUILDER / Specifying Filters for Resource Copying Control
 	 *    Allow to specify some filters to control the resource copy process.
 	 *     - option id:         "org.eclipse.jdt.core.builder.resourceCopyExclusionFilter"
@@ -2020,6 +2182,13 @@
 	 *     - option id:         "org.eclipse.jdt.core.codeComplete.argumentSuffixes"
 	 *     - possible values:   { "&lt;suffix&gt;[,&lt;suffix&gt;]*" } where &lt;suffix&gt; is a String without any wild-card 
 	 *     - default:           ""
+	 *     
+	 *  CODEASSIST / Activate Access Restrictions Sensitive Completion
+	 *    When active, completion doesn't show that is access restricted.
+	 *     - option id:         "org.eclipse.jdt.core.codeComplete.restrictionsCheck"
+	 *     - possible values:   { "enabled", "disabled" }
+	 *     - default:           "disabled"
+	 * 
 	 * </pre>
 	 * 
 	 * @return a mutable table containing the default settings of all known options
@@ -2031,14 +2200,15 @@
 		Hashtable defaultOptions = new Hashtable(10);
 
 		// see #initializeDefaultPluginPreferences() for changing default settings
-		Preferences preferences = getPlugin().getPluginPreferences();
+		IEclipsePreferences defaultPreferences = getDefaultPreferences();
 		HashSet optionNames = JavaModelManager.getJavaModelManager().optionNames;
 		
 		// initialize preferences to their default
 		Iterator iterator = optionNames.iterator();
 		while (iterator.hasNext()) {
 		    String propertyName = (String) iterator.next();
-		    defaultOptions.put(propertyName, preferences.getDefaultString(propertyName));
+		    String value = defaultPreferences.get(propertyName, null);
+		    if (value != null) defaultOptions.put(propertyName, value);
 		}
 		// get encoding through resource plugin
 		defaultOptions.put(CORE_ENCODING, getEncoding());
@@ -2048,6 +2218,26 @@
 		
 		return defaultOptions;
 	}
+ 
+	/**
+	 * @since 3.1
+	 */
+	public static IEclipsePreferences getInstancePreferences() {
+		if (preferencesLookup[PREF_INSTANCE] == null) {
+			preferencesLookup[PREF_INSTANCE] = new InstanceScope().getNode(PLUGIN_ID);
+		}
+		return preferencesLookup[PREF_INSTANCE];
+	}
+ 
+	/**
+	 * @since 3.1
+	 */
+	public static IEclipsePreferences getDefaultPreferences() {
+		if (preferencesLookup[PREF_DEFAULT] == null) {
+			preferencesLookup[PREF_DEFAULT] = new DefaultScope().getNode(PLUGIN_ID);
+		}
+		return preferencesLookup[PREF_DEFAULT];
+	}
 
 	/**
 	 * Returns the workspace root default charset encoding.
@@ -2090,6 +2280,7 @@
 	 * @param optionName the name of an option
 	 * @return the String value of a given option
 	 * @see JavaCore#getDefaultOptions()
+	 * @see JavaCorePreferenceInitializer for changing default settings
 	 * @since 2.0
 	 */
 	public static String getOption(String optionName) {
@@ -2104,8 +2295,9 @@
 		}
 		String propertyName = optionName;
 		if (JavaModelManager.getJavaModelManager().optionNames.contains(propertyName)){
-			Preferences preferences = getPlugin().getPluginPreferences();
-			return preferences.getString(propertyName).trim();
+			IPreferencesService service = Platform.getPreferencesService();
+			String value =  service.get(optionName, null, preferencesLookup);
+			return value==null ? null : value.trim();
 		}
 		return null;
 	}
@@ -2119,39 +2311,34 @@
 	 * 
 	 * @return table of current settings of all options 
 	 *   (key type: <code>String</code>; value type: <code>String</code>)
-	 * @see JavaCore#getDefaultOptions()
+	 * @see #getDefaultOptions()
+	 * @see JavaCorePreferenceInitializer for changing default settings
 	 */
 	public static Hashtable getOptions() {
-		
-		Hashtable options = new Hashtable(10);
 
-		// see #initializeDefaultPluginPreferences() for changing default settings
-		Plugin plugin = getPlugin();
-		if (plugin != null) {
-			Preferences preferences = getPlugin().getPluginPreferences();
-			HashSet optionNames = JavaModelManager.getJavaModelManager().optionNames;
-			
-			// initialize preferences to their default
-			Iterator iterator = optionNames.iterator();
-			while (iterator.hasNext()) {
-			    String propertyName = (String) iterator.next();
-			    options.put(propertyName, preferences.getDefaultString(propertyName));
-			}
-			// get preferences not set to their default
-			String[] propertyNames = preferences.propertyNames();
-			for (int i = 0; i < propertyNames.length; i++){
-				String propertyName = propertyNames[i];
-				String value = preferences.getString(propertyName).trim();
-				if (optionNames.contains(propertyName)){
-					options.put(propertyName, value);
-				}
-			}
-			// get encoding through resource plugin
-			options.put(CORE_ENCODING, getEncoding()); 
-			// backward compatibility
-			options.put(COMPILER_PB_INVALID_IMPORT, ERROR);
-			options.put(COMPILER_PB_UNREACHABLE_CODE, ERROR);
+		// init
+		Hashtable options = new Hashtable(10);
+		HashSet optionNames = JavaModelManager.getJavaModelManager().optionNames;
+		IPreferencesService service = Platform.getPreferencesService();
+
+		// set options using preferences service lookup
+		Iterator iterator = optionNames.iterator();
+		while (iterator.hasNext()) {
+		    String propertyName = (String) iterator.next();
+		    String propertyValue = service.get(propertyName, null, preferencesLookup);
+		    if (propertyValue != null) {
+			    options.put(propertyName, propertyValue);
+		    }
 		}
+
+		// get encoding through resource plugin
+		options.put(CORE_ENCODING, getEncoding()); 
+
+		// backward compatibility
+		options.put(COMPILER_PB_INVALID_IMPORT, ERROR);
+		options.put(COMPILER_PB_UNREACHABLE_CODE, ERROR);
+
+		// return built map
 		return options;
 	}
 
@@ -2209,7 +2396,7 @@
 					
 					case IResource.PROJECT :  
 						// internal project
-						return JavaCore.newProjectEntry(resolvedPath, entry.isExported());
+						return JavaCore.newProjectEntry(resolvedPath, entry.getInclusionPatterns(), entry.getExclusionPatterns(), entry.isExported());
 						
 					case IResource.FILE : 
 						if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(resolvedResource.getName())) {
@@ -2218,6 +2405,8 @@
 									resolvedPath,
 									getResolvedVariablePath(entry.getSourceAttachmentPath()),
 									getResolvedVariablePath(entry.getSourceAttachmentRootPath()),
+									entry.getInclusionPatterns(), 
+									entry.getExclusionPatterns(), 
 									entry.isExported());
 						}
 						break;
@@ -2228,6 +2417,8 @@
 								resolvedPath,
 								getResolvedVariablePath(entry.getSourceAttachmentPath()),
 								getResolvedVariablePath(entry.getSourceAttachmentRootPath()),
+								entry.getInclusionPatterns(), 
+								entry.getExclusionPatterns(), 
 								entry.isExported());
 				}
 			}
@@ -2243,6 +2434,8 @@
 							resolvedPath,
 							getResolvedVariablePath(entry.getSourceAttachmentPath()),
 							getResolvedVariablePath(entry.getSourceAttachmentRootPath()),
+							entry.getInclusionPatterns(), 
+							entry.getExclusionPatterns(), 
 							entry.isExported());
 				}
 			} else { // external binary folder
@@ -2251,6 +2444,8 @@
 							resolvedPath,
 							getResolvedVariablePath(entry.getSourceAttachmentPath()),
 							getResolvedVariablePath(entry.getSourceAttachmentRootPath()),
+							entry.getInclusionPatterns(), 
+							entry.getExclusionPatterns(), 
 							entry.isExported());
 				}
 			}
@@ -2332,135 +2527,6 @@
 		if (result == null) return JavaModelManager.NO_WORKING_COPY;
 		return result;
 	}
-		
-	/**
-	 * Initializes the default preferences settings for this plug-in.
-	 */
-	protected void initializeDefaultPluginPreferences() {
-		
-		Preferences preferences = getPluginPreferences();
-		HashSet optionNames = JavaModelManager.getJavaModelManager().optionNames;
-		
-		// Compiler settings
-		Map compilerOptionsMap = new CompilerOptions().getMap(); // compiler defaults
-		for (Iterator iter = compilerOptionsMap.entrySet().iterator(); iter.hasNext();) {
-			Map.Entry entry = (Map.Entry) iter.next();
-			String optionName = (String) entry.getKey();
-			preferences.setDefault(optionName, (String)entry.getValue());
-			optionNames.add(optionName);
-		}
-		// override some compiler defaults
-		preferences.setDefault(COMPILER_LOCAL_VARIABLE_ATTR, GENERATE);
-		preferences.setDefault(COMPILER_CODEGEN_UNUSED_LOCAL, PRESERVE);
-		preferences.setDefault(COMPILER_TASK_TAGS, DEFAULT_TASK_TAGS);
-		preferences.setDefault(COMPILER_TASK_PRIORITIES, DEFAULT_TASK_PRIORITIES);
-		preferences.setDefault(COMPILER_TASK_CASE_SENSITIVE, ENABLED);
-		preferences.setDefault(COMPILER_DOC_COMMENT_SUPPORT, ENABLED);
-
-		// Builder settings
-		preferences.setDefault(CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, ""); //$NON-NLS-1$
-		optionNames.add(CORE_JAVA_BUILD_RESOURCE_COPY_FILTER);
-
-		preferences.setDefault(CORE_JAVA_BUILD_INVALID_CLASSPATH, ABORT); 
-		optionNames.add(CORE_JAVA_BUILD_INVALID_CLASSPATH);
-	
-		preferences.setDefault(CORE_JAVA_BUILD_DUPLICATE_RESOURCE, WARNING); 
-		optionNames.add(CORE_JAVA_BUILD_DUPLICATE_RESOURCE);
-		
-		preferences.setDefault(CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER, CLEAN); 
-		optionNames.add(CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER);
-
-		// JavaCore settings
-		preferences.setDefault(CORE_JAVA_BUILD_ORDER, IGNORE); 
-		optionNames.add(CORE_JAVA_BUILD_ORDER);
-	
-		preferences.setDefault(CORE_INCOMPLETE_CLASSPATH, ERROR); 
-		optionNames.add(CORE_INCOMPLETE_CLASSPATH);
-		
-		preferences.setDefault(CORE_CIRCULAR_CLASSPATH, ERROR); 
-		optionNames.add(CORE_CIRCULAR_CLASSPATH);
-		
-		preferences.setDefault(CORE_INCOMPATIBLE_JDK_LEVEL, IGNORE); 
-		optionNames.add(CORE_INCOMPATIBLE_JDK_LEVEL);
-		
-		preferences.setDefault(CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, ENABLED); 
-		optionNames.add(CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS);
-
-		preferences.setDefault(CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, ENABLED); 
-		optionNames.add(CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS);
-
-		// encoding setting comes from resource plug-in
-		optionNames.add(CORE_ENCODING);
-		
-		// Formatter settings
-		Map codeFormatterOptionsMap = DefaultCodeFormatterConstants.getJavaConventionsSettings(); // code formatter defaults
-		for (Iterator iter = codeFormatterOptionsMap.entrySet().iterator(); iter.hasNext();) {
-			Map.Entry entry = (Map.Entry) iter.next();
-			String optionName = (String) entry.getKey();
-			preferences.setDefault(optionName, (String)entry.getValue());
-			optionNames.add(optionName);
-		}		
-		preferences.setDefault(FORMATTER_NEWLINE_OPENING_BRACE, DO_NOT_INSERT); 
-		optionNames.add(FORMATTER_NEWLINE_OPENING_BRACE);
-
-		preferences.setDefault(FORMATTER_NEWLINE_CONTROL, DO_NOT_INSERT);
-		optionNames.add(FORMATTER_NEWLINE_CONTROL);
-
-		preferences.setDefault(FORMATTER_CLEAR_BLANK_LINES, PRESERVE_ONE); 
-		optionNames.add(FORMATTER_CLEAR_BLANK_LINES);
-
-		preferences.setDefault(FORMATTER_NEWLINE_ELSE_IF, DO_NOT_INSERT);
-		optionNames.add(FORMATTER_NEWLINE_ELSE_IF);
-
-		preferences.setDefault(FORMATTER_NEWLINE_EMPTY_BLOCK, INSERT); 
-		optionNames.add(FORMATTER_NEWLINE_EMPTY_BLOCK);
-
-		preferences.setDefault(FORMATTER_LINE_SPLIT, "80"); //$NON-NLS-1$
-		optionNames.add(FORMATTER_LINE_SPLIT);
-
-		preferences.setDefault(FORMATTER_COMPACT_ASSIGNMENT, NORMAL); 
-		optionNames.add(FORMATTER_COMPACT_ASSIGNMENT);
-
-		preferences.setDefault(FORMATTER_TAB_CHAR, TAB); 
-		optionNames.add(FORMATTER_TAB_CHAR);
-
-		preferences.setDefault(FORMATTER_TAB_SIZE, "4"); //$NON-NLS-1$ 
-		optionNames.add(FORMATTER_TAB_SIZE);
-		
-		preferences.setDefault(FORMATTER_SPACE_CASTEXPRESSION, INSERT); //$NON-NLS-1$ 
-		optionNames.add(FORMATTER_SPACE_CASTEXPRESSION);
-
-		// CodeAssist settings
-		preferences.setDefault(CODEASSIST_VISIBILITY_CHECK, DISABLED); //$NON-NLS-1$
-		optionNames.add(CODEASSIST_VISIBILITY_CHECK);
-
-		preferences.setDefault(CODEASSIST_IMPLICIT_QUALIFICATION, DISABLED); //$NON-NLS-1$
-		optionNames.add(CODEASSIST_IMPLICIT_QUALIFICATION);
-		
-		preferences.setDefault(CODEASSIST_FIELD_PREFIXES, ""); //$NON-NLS-1$
-		optionNames.add(CODEASSIST_FIELD_PREFIXES);
-		
-		preferences.setDefault(CODEASSIST_STATIC_FIELD_PREFIXES, ""); //$NON-NLS-1$
-		optionNames.add(CODEASSIST_STATIC_FIELD_PREFIXES);
-		
-		preferences.setDefault(CODEASSIST_LOCAL_PREFIXES, ""); //$NON-NLS-1$
-		optionNames.add(CODEASSIST_LOCAL_PREFIXES);
-		
-		preferences.setDefault(CODEASSIST_ARGUMENT_PREFIXES, ""); //$NON-NLS-1$
-		optionNames.add(CODEASSIST_ARGUMENT_PREFIXES);
-		
-		preferences.setDefault(CODEASSIST_FIELD_SUFFIXES, ""); //$NON-NLS-1$
-		optionNames.add(CODEASSIST_FIELD_SUFFIXES);
-		
-		preferences.setDefault(CODEASSIST_STATIC_FIELD_SUFFIXES, ""); //$NON-NLS-1$
-		optionNames.add(CODEASSIST_STATIC_FIELD_SUFFIXES);
-		
-		preferences.setDefault(CODEASSIST_LOCAL_SUFFIXES, ""); //$NON-NLS-1$
-		optionNames.add(CODEASSIST_LOCAL_SUFFIXES);
-		
-		preferences.setDefault(CODEASSIST_ARGUMENT_SUFFIXES, ""); //$NON-NLS-1$
-		optionNames.add(CODEASSIST_ARGUMENT_SUFFIXES);
-	}
 	
 	/**
 	 * Returns whether the given marker references the given Java element.
@@ -2550,51 +2616,49 @@
 
 	/**
 	 * Creates and returns a new classpath entry of kind <code>CPE_CONTAINER</code>
-	 * for the given path. The path of the container will be used during resolution so as to map this
-	 * container entry to a set of other classpath entries the container is acting for.
-	 * <p>
-	 * A container entry allows to express indirect references to a set of libraries, projects and variable entries,
-	 * which can be interpreted differently for each Java project where it is used.
-	 * A classpath container entry can be resolved using <code>JavaCore.getResolvedClasspathContainer</code>,
-	 * and updated with <code>JavaCore.classpathContainerChanged</code>
-	 * <p>
-	 * A container is exclusively resolved by a <code>ClasspathContainerInitializer</code> registered onto the
-	 * extension point "org.eclipse.jdt.core.classpathContainerInitializer".
-	 * <p>
-	 * A container path must be formed of at least one segment, where: <ul>
-	 * <li> the first segment is a unique ID identifying the target container, there must be a container initializer registered
-	 * 	onto this ID through the extension point  "org.eclipse.jdt.core.classpathContainerInitializer". </li>
-	 * <li> the remaining segments will be passed onto the initializer, and can be used as additional
-	 * 	hints during the initialization phase. </li>
-	 * </ul>
-	 * <p>
-	 * Example of an ClasspathContainerInitializer for a classpath container denoting a default JDK container:
-	 * 
-	 * containerEntry = JavaCore.newContainerEntry(new Path("MyProvidedJDK/default"));
-	 * 
-	 * <extension
-	 *    point="org.eclipse.jdt.core.classpathContainerInitializer">
-	 *    <containerInitializer
-	 *       id="MyProvidedJDK"
-	 *       class="com.example.MyInitializer"/> 
-	 * <p>
-	 * Note that this operation does not attempt to validate classpath containers
-	 * or access the resources at the given paths.
-	 * <p>
-	 * The resulting entry is not exported to dependent projects. This method is equivalent to
-	 * <code>newContainerEntry(-,false)</code>.
+	 * for the given path. This method is fully equivalent to calling
+	 * {@link #newContainerEntry(IPath, IPath[], IPath[], boolean)
+	 * newContainerEntry(containerPath, new IPath[0], new IPath[0], false)}.
 	 * <p>
 	 * @param containerPath the path identifying the container, it must be formed of two
 	 * 	segments
 	 * @return a new container classpath entry
 	 * 
 	 * @see JavaCore#getClasspathContainer(IPath, IJavaProject)
-	 * @see JavaCore#newContainerEntry(IPath, boolean)
 	 * @since 2.0
 	 */
 	public static IClasspathEntry newContainerEntry(IPath containerPath) {
 			
-		return newContainerEntry(containerPath, false);
+		return newContainerEntry(
+			containerPath,
+			ClasspathEntry.INCLUDE_ALL,
+			ClasspathEntry.EXCLUDE_NONE, 
+			false);
+	}
+
+	/**
+	 * Creates and returns a new classpath entry of kind <code>CPE_CONTAINER</code>
+	 * for the given path. This method is fully equivalent to calling
+	 * {@link #newContainerEntry(IPath, IPath[], IPath[], boolean)
+	 * newContainerEntry(containerPath, new IPath[0], new IPath[0], isExported)}. 
+	 * 
+	 * @param containerPath the path identifying the container, it must be formed of at least
+	 * 	one segment (ID+hints)
+	 * @param isExported a boolean indicating whether this entry is contributed to dependent
+	 *    projects in addition to the output location
+	 * @return a new container classpath entry
+	 * 
+	 * @see JavaCore#getClasspathContainer(IPath, IJavaProject)
+	 * @see JavaCore#setClasspathContainer(IPath, IJavaProject[], IClasspathContainer[], IProgressMonitor)
+	 * @since 2.0
+	 */
+	public static IClasspathEntry newContainerEntry(IPath containerPath, boolean isExported) {
+			
+		return newContainerEntry(
+			containerPath,
+			ClasspathEntry.INCLUDE_ALL,
+			ClasspathEntry.EXCLUDE_NONE, 
+			isExported);
 	}
 
 	/**
@@ -2618,20 +2682,67 @@
 	 * </ul>
 	 * <p>
 	 * Example of an ClasspathContainerInitializer for a classpath container denoting a default JDK container:
-	 * 
+	 * <pre>
 	 * containerEntry = JavaCore.newContainerEntry(new Path("MyProvidedJDK/default"));
 	 * 
-	 * <extension
-	 *    point="org.eclipse.jdt.core.classpathContainerInitializer">
-	 *    <containerInitializer
+	 * &lt;extension
+	 *    point="org.eclipse.jdt.core.classpathContainerInitializer"&gt;
+	 *    &lt;containerInitializer
 	 *       id="MyProvidedJDK"
-	 *       class="com.example.MyInitializer"/> 
+	 *       class="com.example.MyInitializer"/&gt; 
+	 * </pre>
+	 * <p>
+	 * The inclusion patterns determines the initial set of accessible source and class files in 
+	 * the container; the exclusion patterns are then used to reduce this
+	 * set. A source or class file that is not accessible can still be refered to but it is 
+	 * tagged as being not accessible - the Java builder will create a problem 
+	 * marker for example. The severity of this marker is controled through
+	 * the {@link #COMPILER_PB_FORBIDDEN_REFERENCE} compiler option.
+	 * Note this is different from inclusion and 
+	 * exclusion patterns on source classpath entries, where a source file that
+	 * is excluded is not even compiled.
+	 * When no inclusion patterns are specified, all source and class files
+	 * in the container are initially accessible. On the other hand, specifying one 
+	 * or more inclusion patterns means that all <b>and only</b> source and
+	 * class files matching at least one of the specified patterns are accessible. 
+	 * If exclusion patterns are specified, the initial set of accessible source and 
+	 * class files is then reduced by eliminating source and class files matched 
+	 * by at least one of the exclusion patterns. Inclusion and exclusion 
+	 * patterns look like relative file paths with wildcards and are interpreted 
+	 * relative to each entry's path of the container. Patterns are case-sensitive 
+	 * and they can contain '**', '*' or '?' wildcards (see 
+	 * {@link IClasspathEntry#getExclusionPatterns()} for the full description
+	 * of their syntax and semantics).
+	 * </p>
+	 * <p>
+	 * For example, if one of the container's entry path is 
+	 * <code>/Project/someLib.jar</code>, there are no inclusion filters, and the
+	 * exclusion pattern is 
+	 * <code>com/xyz/tests/&#42;&#42;</code>, then class files
+	 * like <code>/Project/someLib.jar/com/xyz/Foo.class</code>
+	 * and <code>/Project/someLib.jar/com/xyz/utils/Bar.class</code> would be accessible,
+	 * whereas <code>/Project/someLib.jar/com/xyz/tests/T1.class</code>
+	 * and <code>/Project/someLib.jar/com/xyz/tests/quick/T2.class</code> would not be
+	 * accessible. 
+	 * </p>
+	 * <p>
+	 * The <code>isExported</code> flag indicates whether this entry is contributed to dependent
+	 * projects. If not exported, dependent projects will not see any of the classes from this entry.
+	 * If exported, dependent projects will concatenate the inclusion patterns of this entry with the
+	 * inclusion patterns of the projects, and they will concatenate the exclusion patterns of this entry
+	 * with the exclusion patterns of the project. 
+	 * </p>
 	 * <p>
 	 * Note that this operation does not attempt to validate classpath containers
 	 * or access the resources at the given paths.
-	 * <p>
+	 * </p>
+	 * 
 	 * @param containerPath the path identifying the container, it must be formed of at least
 	 * 	one segment (ID+hints)
+	 * @param inclusionPatterns the possibly empty list of inclusion patterns
+	 *    represented as relative paths
+	 * @param exclusionPatterns the possibly empty list of exclusion patterns
+	 *    represented as relative paths
 	 * @param isExported a boolean indicating whether this entry is contributed to dependent
 	 *    projects in addition to the output location
 	 * @return a new container classpath entry
@@ -2639,9 +2750,13 @@
 	 * @see JavaCore#getClasspathContainer(IPath, IJavaProject)
 	 * @see JavaCore#setClasspathContainer(IPath, IJavaProject[], IClasspathContainer[], IProgressMonitor)
 	 * @see JavaCore#newContainerEntry(IPath, boolean)
-	 * @since 2.0
-	 */
-	public static IClasspathEntry newContainerEntry(IPath containerPath, boolean isExported) {
+	 * @since 3.1
+	 */	
+	public static IClasspathEntry newContainerEntry(
+			IPath containerPath, 
+			IPath[] inclusionPatterns, 
+			IPath[] exclusionPatterns, 
+			boolean isExported) {
 			
 		if (containerPath == null) Assert.isTrue(false, "Container path cannot be null"); //$NON-NLS-1$
 		if (containerPath.segmentCount() < 1) {
@@ -2653,37 +2768,22 @@
 			IPackageFragmentRoot.K_SOURCE,
 			IClasspathEntry.CPE_CONTAINER,
 			containerPath,
-			ClasspathEntry.INCLUDE_ALL,
-			ClasspathEntry.EXCLUDE_NONE, 
+			inclusionPatterns,
+			exclusionPatterns, 
 			null, // source attachment
 			null, // source attachment root
 			null, // specific output folder
 			isExported);
-	}
-
+	}	
+	
 	/**
 	 * Creates and returns a new non-exported classpath entry of kind <code>CPE_LIBRARY</code> for the 
 	 * JAR or folder identified by the given absolute path. This specifies that all package fragments 
 	 * within the root will have children of type <code>IClassFile</code>.
-	 * <p>
-	 * A library entry is used to denote a prerequisite JAR or root folder containing binaries.
-	 * The target JAR can either be defined internally to the workspace (absolute path relative
-	 * to the workspace root) or externally to the workspace (absolute path in the file system).
-	 * The target root folder can only be defined internally to the workspace (absolute path relative
-	 * to the workspace root). To use a binary folder external to the workspace, it must first be
-	 * linked (see IFolder#createLink(...)).
-	 * <p>
-	 * e.g. Here are some examples of binary path usage<ul>
-	 *	<li><code> "c:/jdk1.2.2/jre/lib/rt.jar" </code> - reference to an external JAR</li>
-	 *	<li><code> "/Project/someLib.jar" </code> - reference to an internal JAR </li>
-	 *	<li><code> "/Project/classes/" </code> - reference to an internal binary folder</li>
-	 * </ul>
-	 * Note that this operation does not attempt to validate or access the 
-	 * resources at the given paths.
-	 * <p>
-	 * The resulting entry is not exported to dependent projects. This method is equivalent to
-	 * <code>newLibraryEntry(-,-,-,false)</code>.
-	 * <p>
+	 * This method is fully equivalent to calling
+	 * {@link #newLibraryEntry(IPath, IPath, IPath, IPath[], IPath[], boolean)
+	 * newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, new IPath[0], new IPath[0], false)}.
+	 *
 	 * @param path the absolute path of the binary archive
 	 * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder, 
 	 *    or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
@@ -2691,15 +2791,53 @@
 	 * @param sourceAttachmentRootPath the location of the root within the source archive or folder
 	 *    or <code>null</code> if this location should be automatically detected.
 	 * @return a new library classpath entry
-	 * 
-	 * @see #newLibraryEntry(IPath, IPath, IPath, boolean)
 	 */
 	public static IClasspathEntry newLibraryEntry(
 		IPath path,
 		IPath sourceAttachmentPath,
 		IPath sourceAttachmentRootPath) {
 			
-		return newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, false);
+		return newLibraryEntry(
+			path,
+			sourceAttachmentPath,
+			sourceAttachmentRootPath,
+			ClasspathEntry.INCLUDE_ALL, 
+			ClasspathEntry.EXCLUDE_NONE, 
+			false);
+	}
+
+	/**
+	 * Creates and returns a new classpath entry of kind <code>CPE_LIBRARY</code> for the JAR or folder
+	 * identified by the given absolute path. This specifies that all package fragments within the root 
+	 * will have children of type <code>IClassFile</code>.
+	 * This method is fully equivalent to calling
+	 * {@link #newLibraryEntry(IPath, IPath, IPath, IPath[], IPath[], boolean)
+	 * newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, new IPath[0], new IPath[0], isExported)}.
+	 * 
+	 * @param path the absolute path of the binary archive
+	 * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder, 
+	 *    or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
+	 *   and will be automatically converted to <code>null</code>.
+	 * @param sourceAttachmentRootPath the location of the root within the source archive or folder
+	 *    or <code>null</code> if this location should be automatically detected.
+	 * @param isExported indicates whether this entry is contributed to dependent
+	 * 	  projects in addition to the output location
+	 * @return a new library classpath entry
+	 * @since 2.0
+	 */
+	public static IClasspathEntry newLibraryEntry(
+		IPath path,
+		IPath sourceAttachmentPath,
+		IPath sourceAttachmentRootPath,
+		boolean isExported) {
+			
+		return newLibraryEntry(
+			path,
+			sourceAttachmentPath,
+			sourceAttachmentRootPath,
+			ClasspathEntry.INCLUDE_ALL, 
+			ClasspathEntry.EXCLUDE_NONE, 
+			isExported);
 	}
 
 	/**
@@ -2722,6 +2860,47 @@
 	 * Note that this operation does not attempt to validate or access the 
 	 * resources at the given paths.
 	 * <p>
+	 * The inclusion patterns determines the initial set of accessible class files in 
+	 * the library; the exclusion patterns are then used to reduce this
+	 * set. A class file that is not accessible can still be refered to but it is 
+	 * tagged as being not accessible - the Java builder will create a problem 
+	 * marker for example. The severity of this marker is controled through
+	 * the {@link #COMPILER_PB_FORBIDDEN_REFERENCE} compiler option.
+	 * Note this is different from inclusion and 
+	 * exclusion patterns on source classpath entries, where a source file that
+	 * is excluded is not even compiled.
+	 * When no inclusion patterns are specified, all class files
+	 * in the resource tree (or in the jar file) rooted at the library
+	 * entry's path are initially accessible. On the other hand, specifying one 
+	 * or more inclusion patterns means that all <b>and only</b> class 
+	 * files matching at least one of the specified patterns are accessible. 
+	 * If exclusion patterns are specified, the initial set of accessible class files is 
+	 * then reduced by eliminating class files matched by at least one of 
+	 * the exclusion patterns. Inclusion and exclusion patterns look like 
+	 * relative file paths with wildcards and are interpreted relative to the 
+	 * library entry's path. Patterns are case-sensitive and they can 
+	 * contain '**', '*' or '?' wildcards (see 
+	 * {@link IClasspathEntry#getExclusionPatterns()} for the full description
+	 * of their syntax and semantics).
+	 * </p>
+	 * <p>
+	 * For example, if the library path is 
+	 * <code>/Project/someLib.jar</code>, there are no inclusion filters, and the
+	 * exclusion pattern is 
+	 * <code>com/xyz/tests/&#42;&#42;</code>, then class files
+	 * like <code>/Project/someLib.jar/com/xyz/Foo.class</code>
+	 * and <code>/Project/someLib.jar/com/xyz/utils/Bar.class</code> would be accessible,
+	 * whereas <code>/Project/someLib.jar/com/xyz/tests/T1.class</code>
+	 * and <code>/Project/someLib.jar/com/xyz/tests/quick/T2.class</code> would not be
+	 * accessible. 
+	 * </p>
+	 * <p>
+	 * The <code>isExported</code> flag indicates whether this entry is contributed to dependent
+	 * projects. If not exported, dependent projects will not see any of the classes from this entry.
+	 * If exported, dependent projects will concatenate the inclusion patterns of this entry with the
+	 * inclusion patterns of the projects, and they will concatenate the exclusion patterns of this entry
+	 * with the exclusion patterns of the project. 
+	 * </p>
 	 * 
 	 * @param path the absolute path of the binary archive
 	 * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder, 
@@ -2729,16 +2908,20 @@
 	 *   and will be automatically converted to <code>null</code>.
 	 * @param sourceAttachmentRootPath the location of the root within the source archive or folder
 	 *    or <code>null</code> if this location should be automatically detected.
-	 * @param isExported indicates whether this entry is contributed to dependent
-	 * 	  projects in addition to the output location
+	 * @param inclusionPatterns the possibly empty list of inclusion patterns
+	 *    represented as relative paths
+	 * @param exclusionPatterns the possibly empty list of exclusion patterns
+	 *    represented as relative paths
 	 * @return a new library classpath entry
-	 * @since 2.0
+	 * @since 3.1
 	 */
 	public static IClasspathEntry newLibraryEntry(
-		IPath path,
-		IPath sourceAttachmentPath,
-		IPath sourceAttachmentRootPath,
-		boolean isExported) {
+			IPath path,
+			IPath sourceAttachmentPath,
+			IPath sourceAttachmentRootPath,
+			IPath[] inclusionPatterns, 
+			IPath[] exclusionPatterns, 
+			boolean isExported) {
 			
 		if (path == null) Assert.isTrue(false, "Library path cannot be null"); //$NON-NLS-1$
 		if (!path.isAbsolute()) Assert.isTrue(false, "Path for IClasspathEntry must be absolute"); //$NON-NLS-1$
@@ -2755,35 +2938,23 @@
 			IPackageFragmentRoot.K_BINARY,
 			IClasspathEntry.CPE_LIBRARY,
 			JavaProject.canonicalizedPath(path),
-			ClasspathEntry.INCLUDE_ALL, 
-			ClasspathEntry.EXCLUDE_NONE, 
+			inclusionPatterns, 
+			exclusionPatterns, 
 			sourceAttachmentPath,
 			sourceAttachmentRootPath,
 			null, // specific output folder
 			isExported);
 	}
-
+	
 	/**
 	 * Creates and returns a new non-exported classpath entry of kind <code>CPE_PROJECT</code>
 	 * for the project identified by the given absolute path.
-	 * <p>
-	 * A project entry is used to denote a prerequisite project on a classpath.
-	 * The referenced project will be contributed as a whole, either as sources (in the Java Model, it
-	 * contributes all its package fragment roots) or as binaries (when building, it contributes its 
-	 * whole output location).
-	 * <p>
-	 * A project reference allows to indirect through another project, independently from its internal layout. 
-	 * <p>
-	 * The prerequisite project is referred to using an absolute path relative to the workspace root.
-	 * <p>
-	 * The resulting entry is not exported to dependent projects. This method is equivalent to
-	 * <code>newProjectEntry(_,false)</code>.
-	 * <p>
+	 * This method is fully equivalent to calling
+	 * {@link #newProjectEntry(IPath, IPath[], IPath[], boolean)
+	 * newProjectEntry(path, new IPath[0], new IPath[0], false)}.
 	 * 
 	 * @param path the absolute path of the binary archive
 	 * @return a new project classpath entry
-	 * 
-	 * @see JavaCore#newProjectEntry(IPath, boolean)
 	 */
 	public static IClasspathEntry newProjectEntry(IPath path) {
 		return newProjectEntry(path, false);
@@ -2792,16 +2963,9 @@
 	/**
 	 * Creates and returns a new classpath entry of kind <code>CPE_PROJECT</code>
 	 * for the project identified by the given absolute path.
-	 * <p>
-	 * A project entry is used to denote a prerequisite project on a classpath.
-	 * The referenced project will be contributed as a whole, either as sources (in the Java Model, it
-	 * contributes all its package fragment roots) or as binaries (when building, it contributes its 
-	 * whole output location).
-	 * <p>
-	 * A project reference allows to indirect through another project, independently from its internal layout. 
-	 * <p>
-	 * The prerequisite project is referred to using an absolute path relative to the workspace root.
-	 * <p>
+	 * This method is fully equivalent to calling
+	 * {@link #newProjectEntry(IPath, IPath[], IPath[], boolean)
+	 * newProjectEntry(path, new IPath[0], new IPath[0], isExported)}.
 	 * 
 	 * @param path the absolute path of the prerequisite project
 	 * @param isExported indicates whether this entry is contributed to dependent
@@ -2813,12 +2977,93 @@
 		
 		if (!path.isAbsolute()) Assert.isTrue(false, "Path for IClasspathEntry must be absolute"); //$NON-NLS-1$
 		
+		return newProjectEntry(
+			path,
+			ClasspathEntry.INCLUDE_ALL, 
+			ClasspathEntry.EXCLUDE_NONE, 
+			isExported);
+	}
+
+	/**
+	 * Creates and returns a new classpath entry of kind <code>CPE_PROJECT</code>
+	 * for the project identified by the given absolute path.
+	 * <p>
+	 * A project entry is used to denote a prerequisite project on a classpath.
+	 * The referenced project will be contributed as a whole, either as sources (in the Java Model, it
+	 * contributes all its package fragment roots) or as binaries (when building, it contributes its 
+	 * whole output location).
+	 * </p>
+	 * <p>
+	 * A project reference allows to indirect through another project, independently from its internal layout. 
+	 * </p><p>
+	 * The prerequisite project is referred to using an absolute path relative to the workspace root.
+	 * </p>
+	 * <p>
+	 * The inclusion patterns determines the initial set of accessible source and class files in 
+	 * the project; the exclusion patterns are then used to reduce this
+	 * set. A source or class file that is not accessible can still be refered to but it is 
+	 * tagged as being not accessible - the Java builder will create a problem 
+	 * marker for example. The severity of this marker is controled through
+	 * the {@link #COMPILER_PB_FORBIDDEN_REFERENCE} compiler option.
+	 * Note this is different from inclusion and 
+	 * exclusion patterns on source classpath entries, where a source file that
+	 * is excluded is not even compiled.
+	 * When no inclusion patterns are specified, all source and class files
+	 * in the project are initially accessible. On the other hand, specifying one 
+	 * or more inclusion patterns means that all <b>and only</b> source and
+	 * class files matching at least one of the specified patterns are accessible. 
+	 * If exclusion patterns are specified, the initial set of accessible source and 
+	 * class files is then reduced by eliminating source and class files matched 
+	 * by at least one of the exclusion patterns. Inclusion and exclusion 
+	 * patterns look like relative file paths with wildcards and are interpreted 
+	 * relative to each entry's path of the project. Patterns are case-sensitive 
+	 * and they can contain '**', '*' or '?' wildcards (see 
+	 * {@link IClasspathEntry#getExclusionPatterns()} for the full description
+	 * of their syntax and semantics).
+	 * </p>
+	 * <p>
+	 * For example, if one of the project's entry path is 
+	 * <code>/Project/someLib.jar</code>, there are no inclusion filters, and the
+	 * exclusion pattern is 
+	 * <code>com/xyz/tests/&#42;&#42;</code>, then class files
+	 * like <code>/Project/someLib.jar/com/xyz/Foo.class</code>
+	 * and <code>/Project/someLib.jar/com/xyz/utils/Bar.class</code> would be accessible,
+	 * whereas <code>/Project/someLib.jar/com/xyz/tests/T1.class</code>
+	 * and <code>/Project/someLib.jar/com/xyz/tests/quick/T2.class</code> would not be
+	 * accessible. 
+	 * </p>
+	 * <p>
+	 * The <code>isExported</code> flag indicates whether this entry is contributed to dependent
+	 * projects. If not exported, dependent projects will not see any of the classes from this entry.
+	 * If exported, dependent projects will concatenate the inclusion patterns of this entry with the
+	 * inclusion patterns of the projects, and they will concatenate the exclusion patterns of this entry
+	 * with the exclusion patterns of the project. 
+	 * </p>
+	 * 
+	 * @param path the absolute path of the prerequisite project
+	 * @param inclusionPatterns the possibly empty list of inclusion patterns
+	 *    represented as relative paths
+	 * @param exclusionPatterns the possibly empty list of exclusion patterns
+	 *    represented as relative paths
+	 * @param isExported indicates whether this entry is contributed to dependent
+	 * 	  projects in addition to the output location
+	 * @return a new project classpath entry
+	 * @since 3.1
+	 */
+	public static IClasspathEntry newProjectEntry(
+			IPath path, 
+			IPath[] inclusionPatterns, 
+			IPath[] exclusionPatterns, 
+			boolean isExported) {
+		
+		if (!path.isAbsolute()) Assert.isTrue(false, "Path for IClasspathEntry must be absolute"); //$NON-NLS-1$
+		
 		return new ClasspathEntry(
 			IPackageFragmentRoot.K_SOURCE,
 			IClasspathEntry.CPE_PROJECT,
 			path,
-			ClasspathEntry.INCLUDE_ALL, 
-			ClasspathEntry.EXCLUDE_NONE, 
+			inclusionPatterns, 
+			exclusionPatterns, 
 			null, // source attachment
 			null, // source attachment root
 			null, // specific output folder
@@ -2996,30 +3241,9 @@
 
 	/**
 	 * Creates and returns a new non-exported classpath entry of kind <code>CPE_VARIABLE</code>
-	 * for the given path. The first segment of the path is the name of a classpath variable.
-	 * The trailing segments of the path will be appended to resolved variable path.
-	 * <p>
-	 * A variable entry allows to express indirect references on a classpath to other projects or libraries,
-	 * depending on what the classpath variable is referring.
-	 * <p>
-	 *	It is possible to register an automatic initializer (<code>ClasspathVariableInitializer</code>),
-	 * which will be invoked through the extension point "org.eclipse.jdt.core.classpathVariableInitializer".
-	 * After resolution, a classpath variable entry may either correspond to a project or a library entry. </li>	 
-	 * <p>
-	 * e.g. Here are some examples of variable path usage<ul>
-	 * <li> "JDTCORE" where variable <code>JDTCORE</code> is 
-	 *		bound to "c:/jars/jdtcore.jar". The resolved classpath entry is denoting the library "c:\jars\jdtcore.jar"</li>
-	 * <li> "JDTCORE" where variable <code>JDTCORE</code> is 
-	 *		bound to "/Project_JDTCORE". The resolved classpath entry is denoting the project "/Project_JDTCORE"</li>
-	 * <li> "PLUGINS/com.example/example.jar" where variable <code>PLUGINS</code>
-	 *      is bound to "c:/eclipse/plugins". The resolved classpath entry is denoting the library "c:/eclipse/plugins/com.example/example.jar"</li>
-	 * </ul>
-	 * Note that this operation does not attempt to validate classpath variables
-	 * or access the resources at the given paths.
-	 * <p>
-	 * The resulting entry is not exported to dependent projects. This method is equivalent to
-	 * <code>newVariableEntry(-,-,-,false)</code>.
-	 * <p>
+	 * for the given path. This method is fully equivalent to calling
+	 * {@link #newVariableEntry(IPath, IPath, IPath, IPath[], IPath[], boolean)
+	 * newLibraryEntry(variablePath, variableSourceAttachmentPath, sourceAttachmentRootPath, new IPath[0], new IPath[0], false)}.
 	 * 
 	 * @param variablePath the path of the binary archive; first segment is the
 	 *   name of a classpath variable
@@ -3030,8 +3254,6 @@
 	 * @param sourceAttachmentRootPath the location of the root within the source archive
 	 *    or <code>null</code> if <code>archivePath</code> is also <code>null</code>
 	 * @return a new library classpath entry
-	 * 
-	 * @see JavaCore#newVariableEntry(IPath, IPath, IPath, boolean)
 	 */
 	public static IClasspathEntry newVariableEntry(
 		IPath variablePath,
@@ -3043,6 +3265,40 @@
 
 	/**
 	 * Creates and returns a new non-exported classpath entry of kind <code>CPE_VARIABLE</code>
+	 * for the given path. This method is fully equivalent to calling
+	 * {@link #newVariableEntry(IPath, IPath, IPath, IPath[], IPath[], boolean)
+	 * newLibraryEntry(variablePath, variableSourceAttachmentPath, sourceAttachmentRootPath, new IPath[0], new IPath[0], false)}.
+	 * 
+	 * @param variablePath the path of the binary archive; first segment is the
+	 *   name of a classpath variable
+	 * @param variableSourceAttachmentPath the path of the corresponding source archive, 
+	 *    or <code>null</code> if none; if present, the first segment is the
+	 *    name of a classpath variable (not necessarily the same variable
+	 *    as the one that begins <code>variablePath</code>)
+	 * @param variableSourceAttachmentRootPath the location of the root within the source archive
+	 *    or <code>null</code> if <code>archivePath</code> is also <code>null</code>
+	 * @param isExported indicates whether this entry is contributed to dependent
+	 * 	  projects in addition to the output location
+	 * @return a new variable classpath entry
+	 * @since 2.0
+	 */
+	public static IClasspathEntry newVariableEntry(
+			IPath variablePath,
+			IPath variableSourceAttachmentPath,
+			IPath variableSourceAttachmentRootPath,
+			boolean isExported) {
+
+		return newVariableEntry(
+			variablePath,
+			variableSourceAttachmentPath, // source attachment
+			variableSourceAttachmentRootPath, // source attachment root			
+			ClasspathEntry.INCLUDE_ALL, 
+			ClasspathEntry.EXCLUDE_NONE, 
+			isExported);
+	}
+
+	/**
+	 * Creates and returns a new non-exported classpath entry of kind <code>CPE_VARIABLE</code>
 	 * for the given path. The first segment of the path is the name of a classpath variable.
 	 * The trailing segments of the path will be appended to resolved variable path.
 	 * <p>
@@ -3061,9 +3317,51 @@
 	 * <li> "PLUGINS/com.example/example.jar" where variable <code>PLUGINS</code>
 	 *      is bound to "c:/eclipse/plugins". The resolved classpath entry is denoting the library "c:/eclipse/plugins/com.example/example.jar"</li>
 	 * </ul>
+	 * <p>
+	 * The inclusion patterns determines the initial set of accessible source and class files in 
+	 * the project or library; the exclusion patterns are then used to reduce this
+	 * set. A source or class file that is not accessible can still be refered to but it is 
+	 * tagged as being not accessible - the Java builder will create a problem 
+	 * marker for example. The severity of this marker is controled through
+	 * the {@link #COMPILER_PB_FORBIDDEN_REFERENCE} compiler option.
+	 * Note this is different from inclusion and 
+	 * exclusion patterns on source classpath entries, where a source file that
+	 * is excluded is not even compiled.
+	 * When no inclusion patterns are specified, all source and class files
+	 * in the project or library are initially accessible. On the other hand, specifying one 
+	 * or more inclusion patterns means that all <b>and only</b> source and
+	 * class files matching at least one of the specified patterns are accessible. 
+	 * If exclusion patterns are specified, the initial set of accessible source and 
+	 * class files is then reduced by eliminating source and class files matched 
+	 * by at least one of the exclusion patterns. Inclusion and exclusion 
+	 * patterns look like relative file paths with wildcards and are interpreted 
+	 * relative to the resolved entry's path. Patterns are case-sensitive 
+	 * and they can contain '**', '*' or '?' wildcards (see 
+	 * {@link IClasspathEntry#getExclusionPatterns()} for the full description
+	 * of their syntax and semantics).
+	 * </p>
+	 * <p>
+	 * For example, if the resolved entry path is 
+	 * <code>/Project/someLib.jar</code>, there are no inclusion filters, and the
+	 * exclusion pattern is 
+	 * <code>com/xyz/tests/&#42;&#42;</code>, then class files
+	 * like <code>/Project/someLib.jar/com/xyz/Foo.class</code>
+	 * and <code>/Project/someLib.jar/com/xyz/utils/Bar.class</code> would be accessible,
+	 * whereas <code>/Project/someLib.jar/com/xyz/tests/T1.class</code>
+	 * and <code>/Project/someLib.jar/com/xyz/tests/quick/T2.class</code> would not be
+	 * accessible. 
+	 * </p>
+	 * <p>
+	 * The <code>isExported</code> flag indicates whether this entry is contributed to dependent
+	 * projects. If not exported, dependent projects will not see any of the classes from this entry.
+	 * If exported, dependent projects will concatenate the inclusion patterns of this entry with the
+	 * inclusion patterns of the projects, and they will concatenate the exclusion patterns of this entry
+	 * with the exclusion patterns of the project. 
+	 * </p>
+	 * <p>
 	 * Note that this operation does not attempt to validate classpath variables
 	 * or access the resources at the given paths.
-	 * <p>
+	 * </p>
 	 *
 	 * @param variablePath the path of the binary archive; first segment is the
 	 *   name of a classpath variable
@@ -3073,16 +3371,22 @@
 	 *    as the one that begins <code>variablePath</code>)
 	 * @param variableSourceAttachmentRootPath the location of the root within the source archive
 	 *    or <code>null</code> if <code>archivePath</code> is also <code>null</code>
+	 * @param inclusionPatterns the possibly empty list of inclusion patterns
+	 *    represented as relative paths
+	 * @param exclusionPatterns the possibly empty list of exclusion patterns
+	 *    represented as relative paths
 	 * @param isExported indicates whether this entry is contributed to dependent
 	 * 	  projects in addition to the output location
 	 * @return a new variable classpath entry
-	 * @since 2.0
-	 */
+	 * @since 3.1
+	 */	
 	public static IClasspathEntry newVariableEntry(
-		IPath variablePath,
-		IPath variableSourceAttachmentPath,
-		IPath variableSourceAttachmentRootPath,
-		boolean isExported) {
+			IPath variablePath,
+			IPath variableSourceAttachmentPath,
+			IPath variableSourceAttachmentRootPath,
+			IPath[] inclusionPatterns, 
+			IPath[] exclusionPatterns, 
+			boolean isExported) {
 
 		if (variablePath == null) Assert.isTrue(false, "Variable path cannot be null"); //$NON-NLS-1$
 		if (variablePath.segmentCount() < 1) {
@@ -3095,14 +3399,13 @@
 			IPackageFragmentRoot.K_SOURCE,
 			IClasspathEntry.CPE_VARIABLE,
 			variablePath,
-			ClasspathEntry.INCLUDE_ALL, 
-			ClasspathEntry.EXCLUDE_NONE, 
+			inclusionPatterns, 
+			exclusionPatterns, 
 			variableSourceAttachmentPath, // source attachment
 			variableSourceAttachmentRootPath, // source attachment root			
 			null, // specific output folder
 			isExported);
-	}
-
+	}	
 	/**
 	 * Removed the given classpath variable. Does nothing if no value was
 	 * set for this classpath variable.
@@ -3432,7 +3735,7 @@
 						// force a refresh of the affected project (will compute deltas)
 						affectedProject.setRawClasspath(
 								affectedProject.getRawClasspath(),
-								SetClasspathOperation.ReuseOutputLocation,
+								SetClasspathOperation.REUSE_PATH,
 								progressMonitor,
 								canChangeResources,
 								oldResolvedPaths[i],
@@ -3562,26 +3865,37 @@
 	 * @param newOptions the new options (key type: <code>String</code>; value type: <code>String</code>),
 	 *   or <code>null</code> to reset all options to their default values
 	 * @see JavaCore#getDefaultOptions()
+	 * @see JavaCorePreferenceInitializer for changing default settings
 	 */
 	public static void setOptions(Hashtable newOptions) {
 		
-		// see #initializeDefaultPluginPreferences() for changing default settings
-		Preferences preferences = getPlugin().getPluginPreferences();
+		try {
+			IEclipsePreferences defaultPreferences = getDefaultPreferences();
+			IEclipsePreferences instancePreferences = getInstancePreferences();
 
-		if (newOptions == null){
-			newOptions = JavaCore.getDefaultOptions();
-		}
-		Enumeration keys = newOptions.keys();
-		while (keys.hasMoreElements()){
-			String key = (String)keys.nextElement();
-			if (!JavaModelManager.getJavaModelManager().optionNames.contains(key)) continue; // unrecognized option
-			if (key.equals(CORE_ENCODING)) continue; // skipped, contributed by resource prefs
-			String value = (String)newOptions.get(key);
-			preferences.setValue(key, value);
-		}
+			if (newOptions == null){
+				instancePreferences.clear();
+			} else {
+				Enumeration keys = newOptions.keys();
+				while (keys.hasMoreElements()){
+					String key = (String)keys.nextElement();
+					if (!JavaModelManager.getJavaModelManager().optionNames.contains(key)) continue; // unrecognized option
+					if (key.equals(CORE_ENCODING)) continue; // skipped, contributed by resource prefs
+					String value = (String)newOptions.get(key);
+					String defaultValue = defaultPreferences.get(key, null);
+					if (defaultValue != null && defaultValue.equals(value)) {
+						instancePreferences.remove(key);
+					} else {
+						instancePreferences.put(key, value);
+					}
+				}
+			}
 
-		// persist options
-		getPlugin().savePluginPreferences();
+			// persist options
+			instancePreferences.flush();
+		} catch (BackingStoreException e) {
+			// fails silently
+		}
 	}
 
 	/* (non-Javadoc)
@@ -3633,8 +3947,34 @@
 			// request state folder creation (workaround 19885)
 			JavaCore.getPlugin().getStateLocation();
 
+			// Listen to instance preferences node removal from parent in order to refresh stored one
+			IEclipsePreferences.INodeChangeListener listener = new IEclipsePreferences.INodeChangeListener() {
+				public void added(IEclipsePreferences.NodeChangeEvent event) {
+					// do nothing
+				}
+				public void removed(IEclipsePreferences.NodeChangeEvent event) {
+					if (event.getChild() == preferencesLookup[PREF_INSTANCE]) {
+						preferencesLookup[PREF_INSTANCE] = new InstanceScope().getNode(PLUGIN_ID);
+					}
+				}
+			};
+			((IEclipsePreferences) getInstancePreferences().parent()).addNodeChangeListener(listener);
+
+			// Listen to default preferences node removal from parent in order to refresh stored one
+			listener = new IEclipsePreferences.INodeChangeListener() {
+				public void added(IEclipsePreferences.NodeChangeEvent event) {
+					// do nothing
+				}
+				public void removed(IEclipsePreferences.NodeChangeEvent event) {
+					if (event.getChild() == preferencesLookup[PREF_DEFAULT]) {
+						preferencesLookup[PREF_DEFAULT] = new DefaultScope().getNode(PLUGIN_ID);
+					}
+				}
+			};
+			((IEclipsePreferences) getDefaultPreferences().parent()).addNodeChangeListener(listener);
+
 			// retrieve variable values
-			JavaCore.getPlugin().getPluginPreferences().addPropertyChangeListener(new JavaModelManager.PluginPreferencesListener());
+			getInstancePreferences().addPreferenceChangeListener(new JavaModelManager.EclipsePreferencesListener());
 			manager.loadVariablesAndContainers();
 
 			final IWorkspace workspace = ResourcesPlugin.getWorkspace();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java
index 416b066..a5144b8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java
@@ -32,6 +32,9 @@
  * @see IJavaModelStatusConstants
  */
 public class JavaModelException extends CoreException {
+
+	private static final long serialVersionUID = -760398656505871287L; // backward compatible
+	
 	CoreException nestedCoreException;
 /**
  * Creates a Java model exception that wrappers the given <code>Throwable</code>.
@@ -98,13 +101,15 @@
 /**
  * Returns whether this exception indicates that a Java model element does not
  * exist. Such exceptions have a status with a code of
- * <code>IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST</code>.
+ * <code>IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST</code> or
+ * <code>IJavaModelStatusConstants.ELEMENT_NOT_ON_CLASSPATH</code>.
  * This is a convenience method.
  *
  * @return <code>true</code> if this exception indicates that a Java model
  *   element does not exist
  * @see IJavaModelStatus#isDoesNotExist()
  * @see IJavaModelStatusConstants#ELEMENT_DOES_NOT_EXIST
+ * @see IJavaModelStatusConstants#ELEMENT_NOT_ON_CLASSPATH
  */
 public boolean isDoesNotExist() {
 	IJavaModelStatus javaModelStatus = getJavaModelStatus();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/NamingConventions.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/NamingConventions.java
index a8a8214..66bb9ef 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/NamingConventions.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/NamingConventions.java
@@ -424,8 +424,8 @@
 		AssistOptions assistOptions = new AssistOptions(javaProject.getOptions(true));
 		return	removePrefixAndSuffix(
 			localName,
-			assistOptions.argumentPrefixes,
-			assistOptions.argumentSuffixes);
+			assistOptions.localPrefixes,
+			assistOptions.localSuffixes);
 	}
 	
 	/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Signature.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Signature.java
index 408ba59..7a2fa00 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Signature.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Signature.java
@@ -11,8 +11,11 @@
  *******************************************************************************/
 package org.eclipse.jdt.core;
 
+import java.util.ArrayList;
+
 import org.eclipse.jdt.core.compiler.CharOperation;
 
+
 /**
  * Provides methods for encoding and decoding type and method signature strings.
  * <p>
@@ -197,13 +200,29 @@
 	public static final char C_TYPE_VARIABLE	= 'T';
 	
 	/**
-	 * Character constant indicating a wildcard type argument 
+	 * Character constant indicating an unbound wildcard type argument 
 	 * in a signature.
 	 * Value is <code>'&ast;'</code>.
 	 * @since 3.0
 	 */
 	public static final char C_STAR	= '*';
 	
+	/**
+	 * Character constant indicating a bound wildcard type argument 
+	 * in a signature with extends clause.
+	 * Value is <code>'+'</code>.
+	 * @since 3.1
+	 */
+	public static final char C_EXTENDS	= '+';
+	
+	/**
+	 * Character constant indicating a bound wildcard type argument 
+	 * in a signature with super clause.
+	 * Value is <code>'-'</code>.
+	 * @since 3.1
+	 */
+	public static final char C_SUPER	= '-';
+	
 	/** 
 	 * Character constant indicating the dot in a signature. 
 	 * Value is <code>'.'</code>.
@@ -348,15 +367,17 @@
 	 */
 	public static int ARRAY_TYPE_SIGNATURE = 4;
 
-	private static final char[] BOOLEAN = {'b', 'o', 'o', 'l', 'e', 'a', 'n'};
-	private static final char[] BYTE = {'b', 'y', 't', 'e'};
-	private static final char[] CHAR = {'c', 'h', 'a', 'r'};
-	private static final char[] DOUBLE = {'d', 'o', 'u', 'b', 'l', 'e'};
-	private static final char[] FLOAT = {'f', 'l', 'o', 'a', 't'};
-	private static final char[] INT = {'i', 'n', 't'};
-	private static final char[] LONG = {'l', 'o', 'n', 'g'};
-	private static final char[] SHORT = {'s', 'h', 'o', 'r', 't'};
-	private static final char[] VOID = {'v', 'o', 'i', 'd'};
+	private static final char[] BOOLEAN = "boolean".toCharArray(); //$NON-NLS-1$
+	private static final char[] BYTE = "byte".toCharArray(); //$NON-NLS-1$
+	private static final char[] CHAR = "char".toCharArray(); //$NON-NLS-1$
+	private static final char[] DOUBLE = "double".toCharArray(); //$NON-NLS-1$
+	private static final char[] FLOAT = "float".toCharArray(); //$NON-NLS-1$
+	private static final char[] INT = "int".toCharArray(); //$NON-NLS-1$
+	private static final char[] LONG = "long".toCharArray(); //$NON-NLS-1$
+	private static final char[] SHORT = "short".toCharArray(); //$NON-NLS-1$
+	private static final char[] VOID = "void".toCharArray(); //$NON-NLS-1$
+	private static final char[] EXTENDS = "extends".toCharArray(); //$NON-NLS-1$
+	private static final char[] SUPER = "super".toCharArray(); //$NON-NLS-1$
 	
 	private static final String EMPTY = new String(CharOperation.NO_CHAR);
 		
@@ -364,12 +385,26 @@
 	// Not instantiable
 }
 
-private static boolean checkPrimitiveType(char[] primitiveTypeName, char[] typeName) {
-	return CharOperation.fragmentEquals(primitiveTypeName, typeName, 0, true) &&
-		(typeName.length == primitiveTypeName.length
-		 || Character.isWhitespace(typeName[primitiveTypeName.length])
-		 || typeName[primitiveTypeName.length] == C_ARRAY
-		 || typeName[primitiveTypeName.length] == C_DOT);
+private static int checkName(char[] name, char[] typeName, int pos, int length) {
+    if (CharOperation.fragmentEquals(name, typeName, pos, true)) {
+        pos += name.length;
+        if (pos == length) return pos;
+        char currentChar = typeName[pos];
+        switch (currentChar) {
+            case ' ' :
+            case '.' :
+            case '<' :
+            case '>' :
+            case '[' :
+            case ',' :
+                return pos;
+			default:
+			    if (Character.isWhitespace(currentChar))
+			    	return pos;
+			    
+        }
+    }
+    return -1;
 }
 
 /**
@@ -457,9 +492,57 @@
 }
 
 /**
+ * Creates a new type parameter signature with the given name and bounds.
+ *
+ * @param typeParameterName the type parameter name
+ * @param boundSignatures the signatures of associated bounds or empty array if none
+ * @return the encoded type parameter signature
+ * 
+ * @since 3.1
+ */
+public static char[] createTypeParameterSignature(char[] typeParameterName, char[][] boundSignatures) {
+	int length = boundSignatures.length;
+	if (length == 0) {
+		return CharOperation.append(typeParameterName, C_COLON); // param signature with no bounds still gets trailing colon
+	}
+	int boundsSize = 0;
+	for (int i = 0; i < length; i++) {
+		boundsSize += boundSignatures[i].length + 1;
+	}
+	int nameLength = typeParameterName.length;
+	char[] result = new char[nameLength + boundsSize];
+	System.arraycopy(typeParameterName, 0, result, 0, nameLength);
+	int index = nameLength;
+	for (int i = 0; i < length; i++) {
+		result[index++] = C_COLON;
+		int boundLength = boundSignatures[i].length;
+		System.arraycopy(boundSignatures[i], 0, result, index, boundLength);
+		index += boundLength;
+	}
+	return result;
+}
+
+/**
+ * Creates a new type parameter signature with the given name and bounds.
+ *
+ * @param typeParameterName the type parameter name
+ * @param boundSignatures the signatures of associated bounds or empty array if none
+ * @return the encoded type parameter signature
+ * 
+ * @since 3.1
+ */
+public static String createTypeParameterSignature(String typeParameterName, String[] boundSignatures) {
+	int length = boundSignatures.length;
+	char[][] boundSignatureChars = new char[length][];
+	for (int i = 0; i < length; i++) {
+		boundSignatureChars[i] = boundSignatures[i].toCharArray();
+	}
+	return new String(createTypeParameterSignature(typeParameterName.toCharArray(), boundSignatureChars));
+}
+
+/**
  * Creates a new type signature from the given type name encoded as a character
- * array. The type name may contain primitive types or array types. However,
- * parameterized types are not supported.
+ * array. The type name may contain primitive types, array types or parameterized types.
  * This method is equivalent to
  * <code>createTypeSignature(new String(typeName),isResolved)</code>, although
  * more efficient for callers with character arrays rather than strings. If the 
@@ -476,10 +559,10 @@
 public static String createTypeSignature(char[] typeName, boolean isResolved) {
 	return new String(createCharArrayTypeSignature(typeName, isResolved));
 }
+
 /**
  * Creates a new type signature from the given type name encoded as a character
- * array. The type name may contain primitive types or array types. However,
- * parameterized types are not supported.
+ * array. The type name may contain primitive types or array types or parameterized types.
  * This method is equivalent to
  * <code>createTypeSignature(new String(typeName),isResolved).toCharArray()</code>,
  * although more efficient for callers with character arrays rather than strings.
@@ -499,129 +582,237 @@
 	if (typeName == null) throw new IllegalArgumentException("null"); //$NON-NLS-1$
 	int length = typeName.length;
 	if (length == 0) throw new IllegalArgumentException(new String(typeName));
+	StringBuffer buffer = new StringBuffer(5);
+	int pos = encodeTypeSignature(typeName, 0, isResolved, length, buffer);
+	pos = consumeWhitespace(typeName, pos, length);
+	if (pos < length) throw new IllegalArgumentException(new String(typeName));
+	char[] result = new char[length = buffer.length()];
+	buffer.getChars(0, length, result, 0);
+	return result;	
+}
+private static int consumeWhitespace(char[] typeName, int pos, int length) {
+    while (pos < length) {
+        char currentChar = typeName[pos];
+        if (currentChar != ' ' && !CharOperation.isWhitespace(currentChar)) {
+            break;
+        }
+        pos++;
+    }
+    return pos;
+}
+private static int encodeQualifiedName(char[] typeName, int pos, int length, StringBuffer buffer) {
+    int count = 0;
+    char lastAppendedChar = 0;
+    nameLoop: while (pos < length) {
+	    char currentChar = typeName[pos];
+		switch (currentChar) {
+		    case '<' :
+		    case '>' :
+		    case '[' :
+		    case ',' :
+		        break nameLoop;
+			case '.' :
+			    buffer.append(C_DOT);
+				lastAppendedChar = C_DOT;
+			    count++;
+			    break;
+			default:
+			    if (currentChar == ' ' || Character.isWhitespace(currentChar)) {
+			        if (lastAppendedChar == C_DOT) { // allow spaces after a dot
+			            pos = consumeWhitespace(typeName, pos, length) - 1; // will be incremented
+			            break; 
+			        }
+			        // allow spaces before a dot
+				    int checkPos = checkNextChar(typeName, '.', pos, length, true);
+				    if (checkPos > 0) {
+				        buffer.append(C_DOT);			// process dot immediately to avoid one iteration
+				        lastAppendedChar = C_DOT;
+				        count++;
+				        pos = checkPos;
+				        break;
+				    }
+				    break nameLoop;
+			    }
+			    buffer.append(currentChar);
+			    lastAppendedChar = currentChar;
+				count++;
+			    break;
+		}
+	    pos++;
+    }
+    if (count == 0) throw new IllegalArgumentException(new String(typeName));
+	return pos;
+}
 
-	int arrayCount = CharOperation.occurencesOf('[', typeName);
-	char[] sig;
-	
-	switch (typeName[0]) {
+private static int encodeArrayDimension(char[] typeName, int pos, int length, StringBuffer buffer) {
+    int checkPos;
+    while (pos < length && (checkPos = checkNextChar(typeName, '[', pos, length, true)) > 0) {
+        pos = checkNextChar(typeName, ']', checkPos, length, false);
+        buffer.append(C_ARRAY);
+    }
+    return pos;
+}
+private static int checkArrayDimension(char[] typeName, int pos, int length) {
+    int genericBalance = 0;
+    while (pos < length) {
+		switch(typeName[pos]) {
+		    case '<' :
+		        genericBalance++;
+		        break;
+		    case ',' :
+			    if (genericBalance == 0) return -1;
+			    break;
+			case '>':
+			    if (genericBalance == 0) return -1;
+			    genericBalance--;
+		        break;
+			case '[':
+			    if (genericBalance == 0) {
+			        return pos;
+			    }
+		}
+		pos++;
+    }
+    return -1;
+}
+private static int checkNextChar(char[] typeName, char expectedChar, int pos, int length, boolean isOptional) {
+    pos = consumeWhitespace(typeName, pos, length);
+    if (pos < length && typeName[pos] == expectedChar) 
+        return pos + 1;
+    if (!isOptional) throw new IllegalArgumentException(new String(typeName));
+    return -1;
+}
+
+private static int encodeTypeSignature(char[] typeName, int start, boolean isResolved, int length, StringBuffer buffer) {
+    int pos = start;
+    pos = consumeWhitespace(typeName, pos, length);
+    if (pos >= length) throw new IllegalArgumentException(new String(typeName));
+    int checkPos;
+    char currentChar = typeName[pos];
+    switch (currentChar) {
 		// primitive type?
 		case 'b' :
-			if (checkPrimitiveType(BOOLEAN, typeName)) {
-				sig = new char[arrayCount+1];
-				sig[arrayCount] = C_BOOLEAN;
-				break;
-			} else if (checkPrimitiveType(BYTE, typeName)) {
-				sig = new char[arrayCount+1];
-				sig[arrayCount] = C_BYTE;
-				break;
+		    checkPos = checkName(BOOLEAN, typeName, pos, length);
+		    if (checkPos > 0) {
+		        pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+			    buffer.append(C_BOOLEAN);
+			    return pos;
+			} 
+		    checkPos = checkName(BYTE, typeName, pos, length);
+		    if (checkPos > 0) {
+		        pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+			    buffer.append(C_BYTE);
+			    return pos;
 			}
+		    break;
 		case 'c':
-			if (checkPrimitiveType(CHAR, typeName)) {
-				sig = new char[arrayCount+1];
-				sig[arrayCount] = C_CHAR;
-				break;
-			}
+		    checkPos = checkName(CHAR, typeName, pos, length);
+		    if (checkPos > 0) {
+		        pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+			    buffer.append(C_CHAR);
+			    return pos;
+			} 
+		    break;
 		case 'd':
-			if (checkPrimitiveType(DOUBLE, typeName)) {
-				sig = new char[arrayCount+1];
-				sig[arrayCount] = C_DOUBLE;
-				break;
-			}
+		    checkPos = checkName(DOUBLE, typeName, pos, length);
+		    if (checkPos > 0) {
+		        pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+			    buffer.append(C_DOUBLE);
+			    return pos;
+			} 
+		    break;
 		case 'f':
-			if (checkPrimitiveType(FLOAT, typeName)) {
-				sig = new char[arrayCount+1];
-				sig[arrayCount] = C_FLOAT;
-				break;
-			}
+		    checkPos = checkName(FLOAT, typeName, pos, length);
+		    if (checkPos > 0) {
+		        pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+			    buffer.append(C_FLOAT);
+			    return pos;
+			} 
+		    break;
 		case 'i':
-			if (checkPrimitiveType(INT, typeName)) {
-				sig = new char[arrayCount+1];
-				sig[arrayCount] = C_INT;
-				break;
-			}
+		    checkPos = checkName(INT, typeName, pos, length);
+		    if (checkPos > 0) {
+		        pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+			    buffer.append(C_INT);
+			    return pos;
+			} 
+		    break;
 		case 'l':
-			if (checkPrimitiveType(LONG, typeName)) {
-				sig = new char[arrayCount+1];
-				sig[arrayCount] = C_LONG;
-				break;
-			}
+		    checkPos = checkName(LONG, typeName, pos, length);
+		    if (checkPos > 0) {
+		        pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+			    buffer.append(C_LONG);
+			    return pos;
+			} 
+		    break;
 		case 's':
-			if (checkPrimitiveType(SHORT, typeName)) {
-				sig = new char[arrayCount+1];
-				sig[arrayCount] = C_SHORT;
-				break;
-			}
+		    checkPos = checkName(SHORT, typeName, pos, length);
+		    if (checkPos > 0) {
+		        pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+			    buffer.append(C_SHORT);
+			    return pos;
+			} 
+		    break;
 		case 'v':
-			if (checkPrimitiveType(VOID, typeName)) {
-				sig = new char[arrayCount+1];
-				sig[arrayCount] = C_VOID;
-				break;
+		    checkPos = checkName(VOID, typeName, pos, length);
+		    if (checkPos > 0) {
+		        pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+			    buffer.append(C_VOID);
+			    return pos;
 			}
-		default:
-			// non primitive type
-			int sigLength = arrayCount + 1 + length + 1; // for example '[[[Ljava.lang.String;'
-			sig = new char[sigLength];
-			int sigIndex = arrayCount+1; // index in sig
-			int startID = 0; // start of current ID in typeName
-			int index = 0; // index in typeName
-			while (index < length) {
-				char currentChar = typeName[index];
-				switch (currentChar) {
-					case '.':
-						if (startID == -1) throw new IllegalArgumentException(new String(typeName));
-						if (startID < index) {
-							sig = CharOperation.append(sig, sigIndex, typeName, startID, index);
-							sigIndex += index-startID;
-						}
-						sig[sigIndex++] = C_DOT;
-						index++;
-						startID = index;
-						break;
-					case '[':
-						if (startID != -1) {
-							if (startID < index) {
-								sig = CharOperation.append(sig, sigIndex, typeName, startID, index);
-								sigIndex += index-startID;
-							}
-							startID = -1; // no more id after []
-						}
-						index++;
-						break;
-					default :
-						if (startID != -1 && CharOperation.isWhitespace(currentChar)) {
-							if (startID < index) {
-								sig = CharOperation.append(sig, sigIndex, typeName, startID, index);
-								sigIndex += index-startID;
-							}
-							startID = index+1;
-						}
-						index++;
-						break;
-				}
+		    break;
+		case '?':
+			// wildcard
+			pos = consumeWhitespace(typeName, pos+1, length);
+			checkPos = checkName(EXTENDS, typeName, pos, length);
+			if (checkPos > 0) {
+				buffer.append(C_EXTENDS);
+				pos = encodeTypeSignature(typeName, checkPos, isResolved, length, buffer);
+				return pos;
 			}
-			// last id
-			if (startID != -1 && startID < index) {
-				sig = CharOperation.append(sig, sigIndex, typeName, startID, index);
-				sigIndex += index-startID;
+			checkPos = checkName(SUPER, typeName, pos, length);
+			if (checkPos > 0) {
+				buffer.append(C_SUPER);
+				pos = encodeTypeSignature(typeName, checkPos, isResolved, length, buffer);
+				return pos;
 			}
-			
-			// add L (or Q) at the beigininig and ; at the end
-			sig[arrayCount] = isResolved ? C_RESOLVED : C_UNRESOLVED;
-			sig[sigIndex++] = C_NAME_END;
-			
-			// resize if needed
-			if (sigLength > sigIndex) {
-				System.arraycopy(sig, 0, sig = new char[sigIndex], 0, sigIndex);
-			}
+			buffer.append(C_STAR);
+			return pos;
+    }		    
+    // non primitive type
+    checkPos = checkArrayDimension(typeName, pos, length);
+	int end;
+	if (checkPos > 0) {
+	    end = encodeArrayDimension(typeName, checkPos, length, buffer);
+	} else {
+	    end = -1;
 	}
-
-	// add array info
-	for (int i = 0; i < arrayCount; i++) {
-		sig[i] = C_ARRAY;
+	buffer.append(isResolved ? C_RESOLVED : C_UNRESOLVED);
+	while (true) { // loop on qualifiedName[<args>][.qualifiedName[<args>]*
+	    pos = encodeQualifiedName(typeName, pos, length, buffer);
+		checkPos = checkNextChar(typeName, '<', pos, length, true);
+		if (checkPos > 0) {
+			buffer.append(C_GENERIC_START);
+		    pos = encodeTypeSignature(typeName, checkPos, isResolved, length, buffer);
+		    while ((checkPos = checkNextChar(typeName, ',', pos, length, true)) > 0) {
+			    pos = encodeTypeSignature(typeName, checkPos, isResolved, length, buffer);
+		    }
+		    pos = checkNextChar(typeName, '>', pos, length, false);
+			buffer.append(C_GENERIC_END);
+		}
+		checkPos = checkNextChar(typeName, '.', pos, length, true);
+		if (checkPos > 0) {
+			buffer.append(C_DOT);
+			pos = checkPos;
+		} else {
+			break;
+		}
 	}
-	
-	return sig;
+	buffer.append(C_NAME_END);
+	if (end > 0) pos = end; // skip array dimension which were preprocessed
+    return pos;
 }
+
 /**
  * Creates a new type signature from the given type name. If the type name is qualified,
  * then it is expected to be dot-based. The type name may contain primitive
@@ -1138,6 +1329,7 @@
 public static int getParameterCount(String methodSignature) throws IllegalArgumentException {
 	return getParameterCount(methodSignature.toCharArray());
 }
+
 /**
  * Extracts the parameter type signatures from the given method signature. 
  * The method signature is expected to be dot-based.
@@ -1179,6 +1371,7 @@
 		throw new IllegalArgumentException();
 	}
 }
+
 /**
  * Extracts the parameter type signatures from the given method signature. 
  * The method signature is expected to be dot-based.
@@ -1190,15 +1383,241 @@
  */
 public static String[] getParameterTypes(String methodSignature) throws IllegalArgumentException {
 	char[][] parameterTypes = getParameterTypes(methodSignature.toCharArray());
-	int length = parameterTypes.length;
-	String[] result = new String[length];
-	for (int i = 0; i < length; i++) {
-		result[i] = new String(parameterTypes[i]);
+	return CharOperation.toStrings(parameterTypes);
+}
+
+/**
+ * Extracts the thrown exception type signatures from the given method signature if any
+ * The method signature is expected to be dot-based.
+ *
+ * @param methodSignature the method signature
+ * @return the list of thrown exception type signatures
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ */
+public static String[] getThrownExceptionTypes(String methodSignature) throws IllegalArgumentException {
+	char[][] parameterTypes = getThrownExceptionTypes(methodSignature.toCharArray());
+	return CharOperation.toStrings(parameterTypes);
+}
+
+/**
+ * Extracts the thrown exception type signatures from the given method signature if any
+ * The method signature is expected to be dot-based.
+ *
+ * @param methodSignature the method signature
+ * @return the list of thrown exception type signatures
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ */
+public static char[][] getThrownExceptionTypes(char[] methodSignature) throws IllegalArgumentException {
+	// skip type parameters
+	int paren = CharOperation.lastIndexOf(C_PARAM_END, methodSignature);
+	if (paren == -1) {
+		throw new IllegalArgumentException();
 	}
+	// ignore return type
+	int exceptionStart = scanTypeSignature(methodSignature, paren+1) + 1;
+	int length = methodSignature.length;
+	if (exceptionStart == length) return CharOperation.NO_CHAR_CHAR;
+	
+	ArrayList exceptionList = new ArrayList(1);
+	int i = exceptionStart;
+	while (i < length) {
+		i = scanTypeSignature(methodSignature, i) + 1;
+		exceptionList.add(CharOperation.subarray(methodSignature, exceptionStart,i));	
+		exceptionStart = i;
+	}
+	char[][] result;
+	exceptionList.toArray(result = new char[exceptionList.size()][]);
 	return result;
 }
 
 /**
+ * Extracts the type argument signatures from the given type signature.
+ * Returns an empty array if the type signature is not a parameterized type signature.
+ *
+ * @param parameterizedTypeSignature the parameterized type signature
+ * @return the signatures of the type arguments
+ * @exception IllegalArgumentException if the signature is syntactically incorrect
+ * 
+ * @since 3.1
+ */
+public static char[][] getTypeArguments(char[] parameterizedTypeSignature) throws IllegalArgumentException {
+	int length = parameterizedTypeSignature.length;
+	if (length < 2 || parameterizedTypeSignature[length-2] != C_GENERIC_END)
+		// cannot have type arguments otherwise signature would end by ">;"
+		return CharOperation.NO_CHAR_CHAR;
+	int count = 1; // start to count generic end/start peers
+	int start = length - 2;
+	while (start >= 0 && count > 0) {
+		switch (parameterizedTypeSignature[--start]) {
+			case C_GENERIC_START:
+				count--;
+				break;
+			case C_GENERIC_END:
+				count++;
+				break;
+		}
+	}
+	if (start < 0) // invalid number of generic start/end
+		throw new IllegalArgumentException();
+	ArrayList args = new ArrayList();
+	int p = start + 1;
+	while (true) {
+		if (p >= parameterizedTypeSignature.length) {
+			throw new IllegalArgumentException();
+		}
+		char c = parameterizedTypeSignature[p];
+		if (c == C_GENERIC_END) {
+			int size = args.size();
+			char[][] result = new char[size][];
+			args.toArray(result);
+			return result;
+		}
+		int e = scanTypeArgumentSignature(parameterizedTypeSignature, p);
+		args.add(CharOperation.subarray(parameterizedTypeSignature, p, e+1));
+		p = e + 1;
+	}
+}
+
+/**
+ * Extracts the type argument signatures from the given type signature.
+ * Returns an empty array if the type signature is not a parameterized type signature.
+ *
+ * @param parameterizedTypeSignature the parameterized type signature
+ * @return the signatures of the type arguments
+ * @exception IllegalArgumentException if the signature is syntactically incorrect
+ * 
+ * @since 3.1
+ */
+public static String[] getTypeArguments(String parameterizedTypeSignature) throws IllegalArgumentException {
+	char[][] args = getTypeArguments(parameterizedTypeSignature.toCharArray());
+	return CharOperation.toStrings(args);
+}
+
+/**
+ * Extracts the type erasure signature from the given parameterized type signature.
+ * Returns the given type signature if it is not parameterized.
+ * 
+ * @param parameterizedTypeSignature the parameterized type signature
+ * @return the signature of the type erasure
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ * 
+ * @since 3.1
+ */
+public static char[] getTypeErasure(char[] parameterizedTypeSignature) throws IllegalArgumentException {
+	int end = CharOperation.indexOf(C_GENERIC_START, parameterizedTypeSignature);
+	if (end == -1) return parameterizedTypeSignature;
+	int length = parameterizedTypeSignature.length;
+	char[] result = new char[length];
+	int pos = 0;
+	int start = 0;
+	int deep= 0;
+	for (int idx=end; idx<length; idx++) {
+		switch (parameterizedTypeSignature[idx]) {
+			case C_GENERIC_START:
+				if (deep == 0) {
+					int size = idx-start;
+					System.arraycopy(parameterizedTypeSignature, start, result, pos, size);
+					end = idx;
+					pos += size;
+				}
+				deep++;
+				break;
+			case C_GENERIC_END:
+				deep--;
+				if (deep < 0) throw new IllegalArgumentException();
+				if (deep == 0) start = idx+1;
+				break;
+		}
+	}
+	if (deep > 0) throw new IllegalArgumentException();
+	int size = pos+length-start;
+	char[] resized = new char[size];
+	System.arraycopy(result, 0, resized, 0, pos);
+	System.arraycopy(parameterizedTypeSignature, start, resized, pos, length-start);
+	return resized;
+}
+
+/**
+ * Extracts the type erasure signature from the given parameterized type signature.
+ * Returns the given type signature if it is not parameterized.
+ * 
+ * @param parameterizedTypeSignature the parameterized type signature
+ * @return the signature of the type erasure
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ * 
+ * @since 3.1
+ */
+public static String getTypeErasure(String parameterizedTypeSignature) throws IllegalArgumentException {
+	return new String(getTypeErasure(parameterizedTypeSignature.toCharArray()));
+}
+
+/**
+ * Extracts the type parameter signatures from the given method or type signature. 
+ * The method or type signature is expected to be dot-based.
+ *
+ * @param methodOrTypeSignature the method or type signature
+ * @return the list of type parameter signatures
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ * 
+ * @since 3.1
+ */
+public static char[][] getTypeParameters(char[] methodOrTypeSignature) throws IllegalArgumentException {
+	try {
+		int length = methodOrTypeSignature.length;
+		if (length == 0) return CharOperation.NO_CHAR_CHAR;
+		if (methodOrTypeSignature[0] != C_GENERIC_START) return CharOperation.NO_CHAR_CHAR;
+		
+		ArrayList paramList = new ArrayList(1);
+		int paramStart = 1, i = 1;  // start after leading '<'
+		while (i < length) {
+			if (methodOrTypeSignature[i] == C_GENERIC_END) {
+				int size = paramList.size();
+				if (size == 0) throw new IllegalArgumentException(); 
+				char[][] result;
+				paramList.toArray(result = new char[size][]);
+				return result;
+			}
+			i = CharOperation.indexOf(C_COLON, methodOrTypeSignature, i);
+			if (i < 0 || i >= length) throw new IllegalArgumentException();
+			// iterate over bounds
+			nextBound: while (methodOrTypeSignature[i] == ':') {
+				i++; // skip colon
+				if (methodOrTypeSignature[i] == ':') {
+					continue nextBound; // empty bound
+				}
+				i = scanTypeSignature(methodOrTypeSignature, i);
+				i++; // position at start of next param if any
+			}
+			paramList.add(CharOperation.subarray(methodOrTypeSignature, paramStart, i));
+			paramStart = i; // next param start from here
+		}
+	} catch (ArrayIndexOutOfBoundsException e) {
+		// invalid signature, fall through
+	}
+	throw new IllegalArgumentException();
+}
+/**
+ * Extracts the type parameter signatures from the given method or type signature. 
+ * The method or type signature is expected to be dot-based.
+ *
+ * @param methodOrTypeSignature the method or type signature
+ * @return the list of type parameter signatures
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ * 
+ * @since 3.1
+ */
+public static String[] getTypeParameters(String methodOrTypeSignature) throws IllegalArgumentException {
+	char[][] params = getTypeParameters(methodOrTypeSignature.toCharArray());
+	return CharOperation.toStrings(params);
+}
+
+/**
  * Extracts the type variable name from the given formal type parameter
  * signature. The signature is expected to be dot-based.
  *
@@ -1289,12 +1708,7 @@
  */
 public static String[] getTypeParameterBounds(String formalTypeParameterSignature) throws IllegalArgumentException {
 	char[][] bounds = getTypeParameterBounds(formalTypeParameterSignature.toCharArray());
-	int length = bounds.length;
-	String[] result = new String[length];
-	for (int i = 0; i < length; i++) {
-		result[i] = new String(bounds[i]);
-	}
-	return result;
+	return CharOperation.toStrings(bounds);
 }
 
 /**
@@ -1306,6 +1720,7 @@
  * <code>
  * getQualifier({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g'}
  * getQualifier({'O', 'u', 't', 'e', 'r', '.', 'I', 'n', 'n', 'e', 'r'}) -> {'O', 'u', 't', 'e', 'r'}
+ * getQualifier({'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l', '.', 'L', 'i', 's', 't', '<', 'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', '>'}) -> {'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l'}
  * </code>
  * </pre>
  * </p>
@@ -1317,7 +1732,8 @@
  * @since 2.0
  */
 public static char[] getQualifier(char[] name) {
-	int lastDot = CharOperation.lastIndexOf(C_DOT, name);
+	int firstGenericStart = CharOperation.indexOf(C_GENERIC_START, name);
+	int lastDot = CharOperation.lastIndexOf(C_DOT, name, 0, firstGenericStart == -1 ? name.length-1 : firstGenericStart);
 	if (lastDot == -1) {
 		return CharOperation.NO_CHAR;
 	}
@@ -1332,6 +1748,7 @@
  * <code>
  * getQualifier("java.lang.Object") -> "java.lang"
  * getQualifier("Outer.Inner") -> "Outer"
+ * getQualifier("java.util.List<java.lang.String>") -> "java.util"
  * </code>
  * </pre>
  * </p>
@@ -1342,11 +1759,9 @@
  * @exception NullPointerException if name is null
  */
 public static String getQualifier(String name) {
-	int lastDot = name.lastIndexOf(C_DOT);
-	if (lastDot == -1) {
-		return EMPTY;
-	}
-	return name.substring(0, lastDot);
+	char[] qualifier = getQualifier(name.toCharArray());
+	if (qualifier.length == 0) return EMPTY;
+	return new String(qualifier);
 }
 /**
  * Extracts the return type from the given method signature. The method signature is 
@@ -1361,14 +1776,13 @@
  */
 public static char[] getReturnType(char[] methodSignature) throws IllegalArgumentException {
 	// skip type parameters
-	int i = CharOperation.lastIndexOf(C_PARAM_END, methodSignature);
-	if (i == -1) {
+	int paren = CharOperation.lastIndexOf(C_PARAM_END, methodSignature);
+	if (paren == -1) {
 		throw new IllegalArgumentException();
 	}
-	// ignore any thrown exceptions
-	int j = CharOperation.indexOf('^', methodSignature);
-	int last = (j == -1 ? methodSignature.length : j);
-	return CharOperation.subarray(methodSignature, i + 1, last);
+	// there could be thrown exceptions behind, thus scan one type exactly
+	int last = scanTypeSignature(methodSignature, paren+1);
+	return CharOperation.subarray(methodSignature, paren + 1, last+1);
 }
 /**
  * Extracts the return type from the given method signature. The method signature is 
@@ -1383,6 +1797,137 @@
 	return new String(getReturnType(methodSignature.toCharArray()));
 }
 /**
+ * Returns package fragment of a type signature. The package fragment separator must be '.'
+ * and the type fragment separator must be '$'.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * getSignatureQualifier({'L', 'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l', '.', 'M', 'a', 'p', '$', 'E', 'n', 't', 'r', 'y', ';'}) -> {'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l'}
+ * </code>
+ * </pre>
+ * </p>
+ * 
+ * @param typeSignature the type signature
+ * @return the package fragment (separators are '.')
+ * @since 3.1
+ */
+public static char[] getSignatureQualifier(char[] typeSignature) {
+	if(typeSignature == null) return CharOperation.NO_CHAR;
+	
+	char[] qualifiedType = Signature.toCharArray(typeSignature);
+	
+	int dotCount = 0;
+	indexFound: for(int i = 0; i < typeSignature.length; i++) {
+		switch(typeSignature[i]) {
+			case C_DOT:
+				dotCount++;
+				break;
+			case C_GENERIC_START:
+				break indexFound;
+			case C_DOLLAR:
+				break indexFound;
+		}
+	}
+	
+	if(dotCount > 0) {
+		for(int i = 0; i < qualifiedType.length; i++) {
+			if(qualifiedType[i] == '.') {
+				dotCount--;
+			}
+			if(dotCount <= 0) {
+				return CharOperation.subarray(qualifiedType, 0, i);
+			}
+		}
+	}
+	return CharOperation.NO_CHAR;
+}
+/**
+ * Returns package fragment of a type signature. The package fragment separator must be '.'
+ * and the type fragment separator must be '$'.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * getSignatureQualifier("Ljava.util.Map$Entry") -> "java.util"
+ * </code>
+ * </pre>
+ * </p>
+ * 
+ * @param typeSignature the type signature
+ * @return the package fragment (separators are '.')
+ * @since 3.1
+ */
+public static String getSignatureQualifier(String typeSignature) {
+	return new String(getSignatureQualifier(typeSignature == null ? null : typeSignature.toCharArray()));
+}
+/**
+ * Returns type fragment of a type signature. The package fragment separator must be '.'
+ * and the type fragment separator must be '$'.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * getSignatureSimpleName({'L', 'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l', '.', 'M', 'a', 'p', '$', 'E', 'n', 't', 'r', 'y', ';'}) -> {'M', 'a', 'p', '.', 'E', 'n', 't', 'r', 'y'}
+ * </code>
+ * </pre>
+ * </p>
+ * 
+ * @param typeSignature the type signature
+ * @return the type fragment (separators are '.')
+ * @since 3.1
+ */
+public static char[] getSignatureSimpleName(char[] typeSignature) {
+	if(typeSignature == null) return CharOperation.NO_CHAR;
+	
+	char[] qualifiedType = Signature.toCharArray(typeSignature);
+	
+	int dotCount = 0;
+	indexFound: for(int i = 0; i < typeSignature.length; i++) {
+		switch(typeSignature[i]) {
+			case C_DOT:
+				dotCount++;
+				break;
+			case C_GENERIC_START:
+				break indexFound;
+			case C_DOLLAR:
+				break indexFound;
+		}
+	}
+	
+	if(dotCount > 0) {
+		for(int i = 0; i < qualifiedType.length; i++) {
+			if(qualifiedType[i] == '.') {
+				dotCount--;
+			}
+			if(dotCount <= 0) {
+				return CharOperation.subarray(qualifiedType, i + 1, qualifiedType.length);
+			}
+		}
+	}
+	return qualifiedType;
+}
+/**
+ * Returns type fragment of a type signature. The package fragment separator must be '.'
+ * and the type fragment separator must be '$'.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * getSignatureSimpleName("Ljava.util.Map$Entry") -> "Map.Entry"
+ * </code>
+ * </pre>
+ * </p>
+ * 
+ * @param typeSignature the type signature
+ * @return the type fragment (separators are '.')
+ * @since 3.1
+ */
+public static String getSignatureSimpleName(String typeSignature) {
+	return new String(getSignatureSimpleName(typeSignature == null ? null : typeSignature.toCharArray()));
+}
+	
+/**
  * Returns the last segment of the given dot-separated qualified name.
  * Returns the given name if it is not qualified.
  * <p>
@@ -1400,11 +1945,42 @@
  * @since 2.0
  */
 public static char[] getSimpleName(char[] name) {
-	int lastDot = CharOperation.lastIndexOf(C_DOT, name);
-	if (lastDot == -1) {
-		return name;
+
+	int lastDot = -1, lastGenericStart = -1, lastGenericEnd = -1;
+	int depth = 0;
+	int length = name.length;
+	lastDotLookup: for (int i = length -1; i >= 0; i--) {
+		switch (name[i]) {
+			case '.':
+				if (depth == 0) {
+					lastDot = i;
+					break lastDotLookup;
+				}
+				break;
+			case '<':
+				depth--;
+				if (depth == 0) lastGenericStart = i;
+				break;
+			case '>':
+				if (depth == 0) lastGenericEnd = i;
+				depth++;
+				break;
+		}
 	}
-	return CharOperation.subarray(name, lastDot + 1, name.length);
+	if (lastGenericStart < 0) {
+		if (lastDot < 0) {
+			return name;
+		}
+		return  CharOperation.subarray(name, lastDot + 1, length);
+	}
+	StringBuffer buffer = new StringBuffer(10);
+	int nameStart = lastDot < 0 ? 0 : lastDot+1;
+	buffer.append(name, nameStart, lastGenericStart - nameStart);
+	appendArgumentSimpleNames(name, lastGenericStart, lastGenericEnd, buffer);
+	buffer.append(name, lastGenericEnd+1, length-lastGenericEnd-1); // copy trailing portion, may contain dimensions	
+	char[] result = new char[length = buffer.length()];
+	buffer.getChars(0, length, result, 0);
+	return result;	
 }
 /**
  * Returns the last segment of the given dot-separated qualified name.
@@ -1415,6 +1991,9 @@
  * <code>
  * getSimpleName("java.lang.Object") -> "Object"
  * </code>
+ * <code>
+ * getSimpleName("java.util.Map<java.lang.String, java.lang.Object>") -> "Map<String,Object>"
+ * </code>
  * </pre>
  * </p>
  *
@@ -1423,11 +2002,125 @@
  * @exception NullPointerException if name is null
  */
 public static String getSimpleName(String name) {
-	int lastDot = name.lastIndexOf(C_DOT);
-	if (lastDot == -1) {
-		return name;
+	int lastDot = -1, lastGenericStart = -1, lastGenericEnd = -1;
+	int depth = 0;
+	int length = name.length();
+	lastDotLookup: for (int i = length -1; i >= 0; i--) {
+		switch (name.charAt(i)) {
+			case '.':
+				if (depth == 0) {
+					lastDot = i;
+					break lastDotLookup;
+				}
+				break;
+			case '<':
+				depth--;
+				if (depth == 0) lastGenericStart = i;
+				break;
+			case '>':
+				if (depth == 0) lastGenericEnd = i;
+				depth++;
+				break;
+		}
 	}
-	return name.substring(lastDot + 1, name.length());
+	if (lastGenericStart < 0) {
+		if (lastDot < 0) {
+			return name;
+		}
+		return name.substring(lastDot + 1, length);
+	}
+	StringBuffer buffer = new StringBuffer(10);
+	char[] nameChars = name.toCharArray();
+	int nameStart = lastDot < 0 ? 0 : lastDot+1;
+	buffer.append(nameChars, nameStart, lastGenericStart - nameStart);
+	appendArgumentSimpleNames(nameChars, lastGenericStart, lastGenericEnd, buffer);
+	buffer.append(nameChars, lastGenericEnd+1, length-lastGenericEnd-1); // copy trailing portion, may contain dimensions	
+	return buffer.toString();
+}
+
+private static void appendSimpleName(char[] name, int start, int end, StringBuffer buffer) {
+	int lastDot = -1, lastGenericStart = -1, lastGenericEnd = -1;
+	int depth = 0;
+	if (name[start] == '?') { // wildcard
+		buffer.append("? "); //$NON-NLS-1$
+		int index = consumeWhitespace(name, start+1, end+1);
+		switch (name[index]) {
+			case 'e' :
+				int checkPos = checkName(EXTENDS, name, index, end);
+			    if (checkPos > 0) {
+			        buffer.append(EXTENDS).append(' ');
+			        index = consumeWhitespace(name, checkPos, end+1);
+				}
+				break;
+			case 's' :
+				checkPos = checkName(SUPER, name, index, end+1);
+			    if (checkPos > 0) {
+			        buffer.append(SUPER).append(' ');
+			        index = consumeWhitespace(name, checkPos, end+1);
+				}
+				break;
+		}
+		start = index; // leading segment got processed
+	}
+	lastDotLookup: for (int i = end; i >= start; i--) {
+		switch (name[i]) {
+			case '.':
+				if (depth == 0) {
+					lastDot = i;
+					break lastDotLookup;
+				}
+				break;
+			case '<':
+				depth--;
+				if (depth == 0) lastGenericStart = i;
+				break;
+			case '>':
+				if (depth == 0) lastGenericEnd = i;
+				depth++;
+				break;
+		}
+	}
+	int nameStart = lastDot < 0 ? start : lastDot+1;
+	int nameEnd = lastGenericStart < 0 ? end+1 : lastGenericStart;
+	buffer.append(name, nameStart, nameEnd - nameStart);
+	if (lastGenericStart >= 0) {
+		appendArgumentSimpleNames(name, lastGenericStart, lastGenericEnd, buffer);
+		buffer.append(name, lastGenericEnd+1, end - lastGenericEnd); // copy trailing portion, may contain dimensions
+	}
+}
+// <x.y.z, a.b<c>.d<e.f>> --> <z,d<f>>
+private static void appendArgumentSimpleNames(char[] name, int start, int end, StringBuffer buffer) {
+	buffer.append('<');
+	int depth = 0;
+	int argumentStart = -1;
+	int argumentCount = 0;
+	for (int i = start; i <= end; i++) {
+		switch(name[i]) {
+			case '<' :
+				depth++;
+				if (depth == 1) {
+					argumentStart = i+1;
+				}
+				break;
+			case '>' : 
+				if (depth == 1) {
+					if (argumentCount > 0) buffer.append(',');
+					appendSimpleName(name, argumentStart, i-1, buffer);
+					argumentCount++;
+				}
+				depth--;
+				break;
+			case ',' :
+				if (depth == 1) {
+					if (argumentCount > 0) buffer.append(',');
+					appendSimpleName(name, argumentStart, i-1, buffer);
+					argumentCount++;
+					argumentStart = i+1;					
+				}
+				break;
+		}
+	}
+	buffer.append('>');
 }
 /**
  * Returns all segments of the given dot-separated qualified name.
@@ -1439,7 +2132,8 @@
  * <code>
  * getSimpleNames({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {{'j', 'a', 'v', 'a'}, {'l', 'a', 'n', 'g'}, {'O', 'b', 'j', 'e', 'c', 't'}}
  * getSimpleNames({'O', 'b', 'j', 'e', 'c', 't'}) -> {{'O', 'b', 'j', 'e', 'c', 't'}}
- * getSimpleNames("") -> {}
+ * getSimpleNames({}) -> {}
+ * getSimpleNames({'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l', '.', 'L', 'i', 's', 't', '<', 'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', '>'}) -> {{'j', 'a', 'v', 'a'}, {'l', 'a', 'n', 'g'}, {'L', 'i', 's', 't', '<', 'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g'}}
  * </code>
  * </pre>
  *
@@ -1449,26 +2143,37 @@
  * @since 2.0
  */
 public static char[][] getSimpleNames(char[] name) {
-	if (name.length == 0) {
+	int length = name == null ? 0 : name.length;
+	if (length == 0)
 		return CharOperation.NO_CHAR_CHAR;
+	
+	int wordCount = 1;
+	countingWords: for (int i = 0; i < length; i++)
+		switch(name[i]) {
+			case C_DOT:
+				wordCount++;
+				break;
+			case C_GENERIC_START:
+				break countingWords;
+		}
+	char[][] split = new char[wordCount][];
+	int last = 0, currentWord = 0;
+	for (int i = 0; i < length; i++) {
+		if (name[i] == C_GENERIC_START) break;
+		if (name[i] == C_DOT) {
+			split[currentWord] = new char[i - last];
+			System.arraycopy(
+				name,
+				last,
+				split[currentWord++],
+				0,
+				i - last);
+			last = i + 1;
+		}
 	}
-	int dot = CharOperation.indexOf(C_DOT, name);
-	if (dot == -1) {
-		return new char[][] {name};
-	}
-	int n = 1;
-	while ((dot = CharOperation.indexOf(C_DOT, name, dot + 1)) != -1) {
-		++n;
-	}
-	char[][] result = new char[n + 1][];
-	int segStart = 0;
-	for (int i = 0; i < n; ++i) {
-		dot = CharOperation.indexOf(C_DOT, name, segStart);
-		result[i] = CharOperation.subarray(name, segStart, dot);
-		segStart = dot + 1;
-	}
-	result[n] = CharOperation.subarray(name, segStart, name.length);
-	return result;
+	split[currentWord] = new char[length - last];
+	System.arraycopy(name, last, split[currentWord], 0, length - last);
+	return split;
 }
 /**
  * Returns all segments of the given dot-separated qualified name.
@@ -1481,6 +2186,7 @@
  * getSimpleNames("java.lang.Object") -> {"java", "lang", "Object"}
  * getSimpleNames("Object") -> {"Object"}
  * getSimpleNames("") -> {}
+ * getSimpleNames("java.util.List<java.lang.String>") -> {"java", "lang", "List<java.lang.String"}
  * </code>
  * </pre>
  *
@@ -1489,13 +2195,7 @@
  * @exception NullPointerException if name is null
  */
 public static String[] getSimpleNames(String name) {
-	char[][] simpleNames = getSimpleNames(name.toCharArray());
-	int length = simpleNames.length;
-	String[] result = new String[length];
-	for (int i = 0; i < length; i++) {
-		result[i] = new String(simpleNames[i]);
-	}
-	return result;
+	return CharOperation.toStrings(getSimpleNames(name.toCharArray()));
 }
 /**
  * Converts the given method signature to a readable form. The method signature is expected to
@@ -1524,6 +2224,37 @@
  * @since 2.0
  */
 public static char[] toCharArray(char[] methodSignature, char[] methodName, char[][] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType) {
+	return toCharArray(methodSignature, methodName, parameterNames, fullyQualifyTypeNames, includeReturnType, false);
+}
+/**
+ * Converts the given method signature to a readable form. The method signature is expected to
+ * be dot-based.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
+ * </code>
+ * </pre>
+ * </p>
+ * 
+ * @param methodSignature the method signature to convert
+ * @param methodName the name of the method to insert in the result, or 
+ *   <code>null</code> if no method name is to be included
+ * @param parameterNames the parameter names to insert in the result, or 
+ *   <code>null</code> if no parameter names are to be included; if supplied,
+ *   the number of parameter names must match that of the method signature
+ * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
+ *   qualified, and <code>false</code> to use only simple names
+ * @param includeReturnType <code>true</code> if the return type is to be
+ *   included
+ * @param isVargArgs <code>true</code> if the last argument should be displayed as a 
+ * variable argument,  <code>false</code> otherwise.
+ * @return the char array representation of the method signature
+ * 
+ * @since 3.1
+ */
+public static char[] toCharArray(char[] methodSignature, char[] methodName, char[][] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType, boolean isVargArgs) {
 	int firstParen = CharOperation.indexOf(C_PARAM_START, methodSignature);
 	if (firstParen == -1) {
 		throw new IllegalArgumentException();
@@ -1546,8 +2277,12 @@
 	// parameters
 	buffer.append('(');
 	char[][] pts = getParameterTypes(methodSignature);
-	for (int i = 0; i < pts.length; i++) {
-		appendTypeSignature(pts[i], 0 , fullyQualifyTypeNames, buffer);
+	for (int i = 0, max = pts.length; i < max; i++) {
+		if (i == max - 1) {
+			appendTypeSignature(pts[i], 0 , fullyQualifyTypeNames, buffer, isVargArgs);
+		} else {
+			appendTypeSignature(pts[i], 0 , fullyQualifyTypeNames, buffer);
+		}
 		if (parameterNames != null) {
 			buffer.append(' ');
 			buffer.append(parameterNames[i]);
@@ -1562,7 +2297,6 @@
 	buffer.getChars(0, buffer.length(), result, 0);
 	return result;
 }
-
 /**
  * Converts the given type signature to a readable string. The signature is expected to
  * be dot-based.
@@ -1573,6 +2307,7 @@
  * <code>
  * toString({'[', 'L', 'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', ';'}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', '[', ']'}
  * toString({'I'}) -> {'i', 'n', 't'}
+ * toString({'+', 'L', 'O', 'b', 'j', 'e', 'c', 't', ';'}) -> {'?', ' ', 'e', 'x', 't', 'e', 'n', 'd', 's', ' ', 'O', 'b', 'j', 'e', 'c', 't'}
  * </code>
  * </pre>
  * </p>
@@ -1619,11 +2354,54 @@
  * @see #scanTypeSignature(char[], int)
  */
 private static int appendTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer) {
-		// need a minimum 1 char
-		if (start >= string.length) {
-			throw new IllegalArgumentException();
+	return appendTypeSignature(string, start, fullyQualifyTypeNames, buffer, false);
+}
+/**
+ * Scans the given string for a type signature starting at the given
+ * index and appends it to the given buffer, and returns the index of the last
+ * character.
+ * 
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
+ *   qualified, and <code>false</code> to use only simple names
+ * @param buffer the string buffer to append to
+ * @param isVarArgs <code>true</code> if the type must be displayed as a
+ * variable argument, <code>false</code> otherwise. In this case, the type must be an array type
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a type signature, or if isVarArgs is <code>true</code>,
+ * and the type is not an array type signature.
+ * @see #scanTypeSignature(char[], int)
+ */
+private static int appendTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer, boolean isVarArgs) {
+	// need a minimum 1 char
+	if (start >= string.length) {
+		throw new IllegalArgumentException();
+	}
+	char c = string[start];
+	if (isVarArgs) {
+		switch (c) {
+			case C_ARRAY :
+				return appendArrayTypeSignature(string, start, fullyQualifyTypeNames, buffer, true);
+			case C_RESOLVED :
+			case C_UNRESOLVED :
+			case C_TYPE_VARIABLE :
+			case C_BOOLEAN :
+			case C_BYTE :
+			case C_CHAR :
+			case C_DOUBLE :
+			case C_FLOAT :
+			case C_INT :
+			case C_LONG :
+			case C_SHORT :
+			case C_VOID :
+			case C_STAR:
+			case C_EXTENDS:
+			case C_SUPER:
+			default:
+				throw new IllegalArgumentException(); // a var args is an array type
 		}
-		char c = string[start];
+	} else {
 		switch (c) {
 			case C_ARRAY :
 				return appendArrayTypeSignature(string, start, fullyQualifyTypeNames, buffer);
@@ -1661,11 +2439,15 @@
 			case C_VOID :
 				buffer.append(VOID);
 				return start;
+			case C_STAR:
+			case C_EXTENDS:
+			case C_SUPER:
+				return appendTypeArgumentSignature(string, start, fullyQualifyTypeNames, buffer);
 			default :
 				throw new IllegalArgumentException();
 		}
+	}
 }
-
 /**
  * Scans the given string for an array type signature starting at the given
  * index and appends it to the given buffer, and returns the index of the last
@@ -1680,6 +2462,24 @@
  * @see #scanArrayTypeSignature(char[], int)
  */
 private static int appendArrayTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer) {
+	return appendArrayTypeSignature(string, start, fullyQualifyTypeNames, buffer, false);
+}
+/**
+ * Scans the given string for an array type signature starting at the given
+ * index and appends it to the given buffer, and returns the index of the last
+ * character.
+ * 
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
+ *   qualified, and <code>false</code> to use only simple names
+ * @param isVarArgs <code>true</code> if the array type must be displayed as a
+ * variable argument, <code>false</code> otherwise
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not an array type signature
+ * @see #scanArrayTypeSignature(char[], int)
+ */
+private static int appendArrayTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer, boolean isVarArgs) {
 	// need a minimum 2 char
 	if (start >= string.length - 1) {
 		throw new IllegalArgumentException();
@@ -1689,11 +2489,13 @@
 		throw new IllegalArgumentException();
 	}
 	int e = appendTypeSignature(string, start + 1, fullyQualifyTypeNames, buffer);
-	buffer.append('[');
-	buffer.append(']');
+	if (isVarArgs) {
+		buffer.append('.').append('.').append('.');
+	} else {
+		buffer.append('[').append(']');
+	}
 	return e;
 }
-
 /**
  * Scans the given string for a class type signature starting at the given
  * index and appends it to the given buffer, and returns the index of the last
@@ -1846,10 +2648,10 @@
 		case C_STAR :
 			buffer.append('?');
 			return start;
-		case '+' :
+		case C_EXTENDS :
 			buffer.append("? extends "); //$NON-NLS-1$
 			return appendTypeSignature(string, start + 1, fullyQualifyTypeNames, buffer);
-		case '-' :
+		case C_SUPER :
 			buffer.append("? super "); //$NON-NLS-1$
 			return appendTypeSignature(string, start + 1, fullyQualifyTypeNames, buffer);
 		default :
@@ -1932,6 +2734,7 @@
  * <code>
  * toString("[Ljava.lang.String;") -> "java.lang.String[]"
  * toString("I") -> "int"
+ * toString("+QObject;") -> "? extends Object"
  * </code>
  * </pre>
  * </p>
@@ -1969,6 +2772,28 @@
  * @return the string representation of the method signature
  */
 public static String toString(String methodSignature, String methodName, String[] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType) {
+	return toString(methodSignature, methodName, parameterNames, fullyQualifyTypeNames, includeReturnType, false);
+}
+/**
+ * Converts the given method signature to a readable string. The method signature is expected to
+ * be dot-based.
+ * 
+ * @param methodSignature the method signature to convert
+ * @param methodName the name of the method to insert in the result, or 
+ *   <code>null</code> if no method name is to be included
+ * @param parameterNames the parameter names to insert in the result, or 
+ *   <code>null</code> if no parameter names are to be included; if supplied,
+ *   the number of parameter names must match that of the method signature
+ * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
+ *   qualified, and <code>false</code> to use only simple names
+ * @param includeReturnType <code>true</code> if the return type is to be
+ *   included
+ * @param isVarArgs <code>true</code> if the last argument should be displayed as a 
+ * variable argument, <code>false</code> otherwise
+ * @see #toCharArray(char[], char[], char[][], boolean, boolean)
+ * @return the string representation of the method signature
+ */
+public static String toString(String methodSignature, String methodName, String[] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType, boolean isVarArgs) {
 	char[][] params;
 	if (parameterNames == null) {
 		params = null;
@@ -1979,7 +2804,6 @@
 			params[i] = parameterNames[i].toCharArray();
 		}
 	}
-	return new String(toCharArray(methodSignature.toCharArray(), methodName == null ? null : methodName.toCharArray(), params, fullyQualifyTypeNames, includeReturnType));
+	return new String(toCharArray(methodSignature.toCharArray(), methodName == null ? null : methodName.toCharArray(), params, fullyQualifyTypeNames, includeReturnType, isVarArgs));
 }
-
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
index 80c5fea..3769c0e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
@@ -29,6 +29,7 @@
 import org.eclipse.jdt.internal.compiler.util.Util;
 import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
 import org.eclipse.jdt.internal.core.JavaModelManager;
+import org.eclipse.jdt.internal.core.PackageFragment;
 import org.eclipse.jdt.internal.core.util.ClassFileReader;
 import org.eclipse.jdt.internal.core.util.Disassembler;
 import org.eclipse.jdt.internal.core.util.PublicScanner;
@@ -184,15 +185,17 @@
 		if (root != null){
 			try {
 				if (root instanceof JarPackageFragmentRoot) {
-						
-					String archiveName = ((JarPackageFragmentRoot)root).getJar().getName();
-					String entryName = classfile.getParent().getElementName();
-					entryName = entryName.replace('.', '/');
-					if (entryName.equals("")) { //$NON-NLS-1$
-						entryName += classfile.getElementName();
-					} else {
-						entryName += '/' + classfile.getElementName();
+					String archiveName = null;
+					ZipFile jar = null;
+					try {
+						jar = ((JarPackageFragmentRoot)root).getJar();
+						archiveName = jar.getName();
+					} finally {
+						JavaModelManager.getJavaModelManager().closeZipFile(jar);
 					}
+					PackageFragment packageFragment = (PackageFragment) classfile.getParent();
+					String classFileName = classfile.getElementName();
+					String entryName = org.eclipse.jdt.internal.core.util.Util.concatWith(packageFragment.names, classFileName, '/');
 					return createDefaultClassFileReader(archiveName, entryName, decodingFlag);
 				} else {
 					IPath location = classfile.getResource().getLocation();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IEvaluationContext.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IEvaluationContext.java
index 5b2ded6..12e605f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IEvaluationContext.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IEvaluationContext.java
@@ -12,7 +12,6 @@
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.ICompletionRequestor;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IType;
@@ -113,6 +112,7 @@
 	 *	    length (INDEX_OUT_OF_BOUNDS)</li>
 	 *  </ul>
 	 * @since 2.0
+	 * @deprecated Use {@link #codeComplete(String,int,CompletionRequestor)} instead.
 	 */
 	public void codeComplete(
 		String codeSnippet,
@@ -145,6 +145,7 @@
 	 *	    length (INDEX_OUT_OF_BOUNDS)</li>
 	 *  </ul>
 	 * @since 3.0
+	 * @deprecated Use {@link #codeComplete(String,int,CompletionRequestor,WorkingCopyOwner)} instead.
 	 */
 	public void codeComplete(
 		String codeSnippet,
@@ -153,6 +154,63 @@
 		WorkingCopyOwner owner)
 		throws JavaModelException;
 	/**
+	 * Performs a code completion at the given position in the given code snippet,
+	 * reporting results to the given completion requestor.
+	 * <p>
+	 * Note that code completion does not involve evaluation.
+	 * <p>
+	 *
+	 * @param codeSnippet the code snippet to complete in
+	 * @param position the character position in the code snippet to complete at,
+	 *   or -1 indicating the beginning of the snippet
+	 * @param requestor the code completion requestor capable of accepting all
+	 *    possible types of completions
+	 * @exception JavaModelException if code completion could not be performed. Reasons include:
+	 *  <ul>
+	 *	  <li>The position specified is less than -1 or is greater than the snippet's
+	 *	    length (INDEX_OUT_OF_BOUNDS)</li>
+	 *  </ul>
+	 * @since 3.1
+	 */
+	public void codeComplete(
+		String codeSnippet,
+		int position,
+		CompletionRequestor requestor)
+		throws JavaModelException;
+	/**
+	 * Performs a code completion at the given position in the given code snippet,
+	 * reporting results to the given completion requestor.
+	 * It considers types in the working copies with the given owner first. In other words, 
+	 * the owner's working copies will take precedence over their original compilation units
+	 * in the workspace.
+	 * <p>
+	 * Note that if a working copy is empty, it will be as if the original compilation
+	 * unit had been deleted.
+	 * </p>
+	 * <p>
+	 * Note that code completion does not involve evaluation.
+	 * <p>
+	 *
+	 * @param codeSnippet the code snippet to complete in
+	 * @param position the character position in the code snippet to complete at,
+	 *   or -1 indicating the beginning of the snippet
+	 * @param requestor the code completion requestor capable of accepting all
+	 *    possible types of completions
+	 * @param owner the owner of working copies that take precedence over their original compilation units
+	 * @exception JavaModelException if code completion could not be performed. Reasons include:
+	 *  <ul>
+	 *	  <li>The position specified is less than -1 or is greater than the snippet's
+	 *	    length (INDEX_OUT_OF_BOUNDS)</li>
+	 *  </ul>
+	 * @since 3.0
+	 */
+	public void codeComplete(
+		String codeSnippet,
+		int position,
+		CompletionRequestor requestor,
+		WorkingCopyOwner owner)
+		throws JavaModelException;
+	/**
 	 * Resolves and returns a collection of Java elements corresponding to the source
 	 * code at the given positions in the given code snippet.
 	 * <p>
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMException.java
index 12c923f..ff0316f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMException.java
@@ -21,6 +21,8 @@
  * org.eclipse.jdt.core.dom package.
  */
 public class DOMException extends RuntimeException {
+	
+	private static final long serialVersionUID = 2536853590795032028L; // backward compatible	
 /**
  * Creates a new exception with no detail message.
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFileBytesDisassembler.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFileBytesDisassembler.java
index 0bf6992..77282e4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFileBytesDisassembler.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFileBytesDisassembler.java
@@ -27,7 +27,14 @@
 	/**
 	 * The mode is the default mode to disassemble IClassFileReader.
 	 */
-	public final static  int DEFAULT  = 2;
+	public final static int DEFAULT  = 2;
+	
+	/**
+	 * This mode corresponds to the detailed mode plus the constant pool contents and
+	 * any further information that would be useful for debugging purpose.
+	 * @since 3.1
+	 */
+	public final static int SYSTEM = 3;
 
 	/**
 	 * Answers back the disassembled string of the classfile bytes using the default
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFormatException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFormatException.java
index c637632..2dac04d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFormatException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFormatException.java
@@ -17,13 +17,14 @@
  * @since 2.0
  */
 public class ClassFormatException extends Exception {
+	
 	public static final int ERROR_MALFORMED_UTF8 = 1;
 	public static final int ERROR_TRUNCATED_INPUT = 2;
 	public static final int INVALID_CONSTANT_POOL_ENTRY = 3;
 	public static final int TOO_MANY_BYTES = 4;
 	public static final int INVALID_ARGUMENTS_FOR_INVOKEINTERFACE = 5;
 	public static final int INVALID_BYTECODE = 6;
-	
+
 	/**
 	 * @since 3.0
 	 */
@@ -34,12 +35,14 @@
 	 */
 	public static final int INVALID_MAGIC_NUMBER = 8;
 
+	private static final long serialVersionUID = 6582900558320612988L; // backward compatible
+	
 	/**
 	 * Constructor for ClassFormatException.
 	 * @param errorID the given error ID
 	 */
 	public ClassFormatException(int errorID) {
-		// TODO what is the errorID?
+		// TODO (olivier) what is the errorID?
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotation.java
index 6b93d30..8eb9d87 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotation.java
@@ -27,6 +27,14 @@
 	int getTypeIndex();
 	
 	/**
+	 * Answer back the type name as described in the JVM specifications.
+	 * 
+	 * @return the type name
+	 * @since 3.1
+	 */
+	char[] getTypeName();
+	
+	/**
 	 * Answer back the number of components as described in the JVM specifications.
 	 * 
 	 * @return the type index
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationComponent.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationComponent.java
index d09d109..e2c114e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationComponent.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationComponent.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials 
  * are made available under the terms of the Common Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationComponentValue.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationComponentValue.java
index 942d895..abf11f4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationComponentValue.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationComponentValue.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials 
  * are made available under the terms of the Common Public License v1.0
  * which accompanies this distribution, and is available at
@@ -21,24 +21,101 @@
 public interface IAnnotationComponentValue {
 	
 	/**
+	 * Tag value for a constant of type <code>byte</code>
+	 * @since 3.1
+	 */
+	int BYTE_TAG = 'B';
+	/**
+	 * Tag value for a constant of type <code>char</code>
+	 * @since 3.1
+	 */
+	int CHAR_TAG = 'C';
+	/**
+	 * Tag value for a constant of type <code>double</code>
+	 * @since 3.1
+	 */
+	int DOUBLE_TAG = 'D';
+	/**
+	 * Tag value for a constant of type <code>float</code>
+	 * @since 3.1
+	 */
+	int FLOAT_TAG = 'F';
+	/**
+	 * Tag value for a constant of type <code>int</code>
+	 * @since 3.1
+	 */
+	int INTEGER_TAG = 'I';
+	/**
+	 * Tag value for a constant of type <code>long</code>
+	 * @since 3.1
+	 */
+	int LONG_TAG = 'J';
+	/**
+	 * Tag value for a constant of type <code>short</code>
+	 * @since 3.1
+	 */
+	int SHORT_TAG = 'S';
+	/**
+	 * Tag value for a constant of type <code>boolean</code>
+	 * @since 3.1
+	 */
+	int BOOLEAN_TAG = 'Z';
+	/**
+	 * Tag value for a constant of type <code>java.lang.String</code>
+	 * @since 3.1
+	 */
+	int STRING_TAG = 's';
+	/**
+	 * Tag value for a value that represents an enum constant
+	 * @since 3.1
+	 */
+	int ENUM_TAG = 'e';
+	/**
+	 * Tag value for a value that represents a class
+	 * @since 3.1
+	 */
+	int CLASS_TAG = 'c';
+	/**
+	 * Tag value for a value that represents an annotation
+	 * @since 3.1
+	 */
+	int ANNOTATION_TAG = '@';
+	/**
+	 * Tag value for a value that represents an array
+	 * @since 3.1
+	 */
+	int ARRAY_TAG = '[';
+	
+	/**
 	 * Answer back the annotation component values as described in the JVM specifications.
-	 * This is initialized only of the tag item is '['.
+	 * This is initialized only if the tag item is '['.
 	 * 
 	 * @return the annotation component values
 	 */
 	IAnnotationComponentValue[] getAnnotationComponentValues();
 	
 	/**
-	 * Answer back the attribute value as described in the JVM specifications.
-	 * This is initialized only of the tag item is '@'.
+	 * Answer back the annotation value as described in the JVM specifications.
+	 * This is initialized only if the tag item is '&#064;'.
 	 * 
 	 * @return the attribute value
+	 * @since 3.1
+	 */
+	IAnnotation getAnnotationValue();
+
+	/**
+	 * Answer back the annotation value as described in the JVM specifications.
+	 * This is initialized only if the tag item is '&#064;'.
+	 * 
+	 * @return the attribute value
+	 * TODO (olivier) remove after 3.1M4
+	 * @deprecated Use getAnnotationValue() instead
 	 */
 	IAnnotation getAttributeValue();
 
 	/**
 	 * Answer back the class info as described in the JVM specifications.
-	 * This is initialized only of the tag item is 'c'.
+	 * This is initialized only if the tag item is 'c'.
 	 * 
 	 * @return the class info
 	 */
@@ -46,7 +123,7 @@
 
 	/**
 	 * Answer back the class info index as described in the JVM specifications.
-	 * This is initialized only of the tag item is 'c'.
+	 * This is initialized only if the tag item is 'c'.
 	 * 
 	 * @return the class info index
 	 */
@@ -54,7 +131,7 @@
 
 	/**
 	 * Answer back the constant value as described in the JVM specifications.
-	 * This is initialized only of the tag item is one of 'B', 'C', 'D', 'F',
+	 * This is initialized only if the tag item is one of 'B', 'C', 'D', 'F',
 	 * 'I', 'J', 'S', 'Z', or 's'.
 	 * 
 	 * @return the constant value
@@ -63,7 +140,7 @@
 
 	/**
 	 * Answer back the constant value index as described in the JVM specifications.
-	 * This is initialized only of the tag item is one of 'B', 'C', 'D', 'F',
+	 * This is initialized only if the tag item is one of 'B', 'C', 'D', 'F',
 	 * 'I', 'J', 'S', 'Z', or 's'.
 	 * 
 	 * @return the constant value index
@@ -71,20 +148,43 @@
 	int getConstantValueIndex();
 
 	/**
-	 * Answer back the enum constant as described in the JVM specifications.
-	 * This is initialized only of the tag item is 'e'.
+	 * Answer back the simple name of the enum constant represented
+	 * by this annotation component value as described in the JVM specifications.
+	 * This is initialized only if the tag item is 'e'.
 	 * 
 	 * @return the enum constant
+	 * @since 3.1
 	 */
-	IConstantPoolEntry getEnumConstant();	
+	char[] getEnumConstantName();	
 	
 	/**
-	 * Answer back the enum constant index as described in the JVM specifications.
-	 * This is initialized only of the tag item is 'e'.
+	 * Answer back the utf8 constant index as described in the JVM specifications.
+	 * This is initialized only if the tag item is 'e'.
 	 * 
 	 * @return the enum constant index
+	 * @since 3.1
 	 */
-	int getEnumConstantIndex();
+	int getEnumConstantNameIndex();
+
+	/**
+	 * Answer back the binary name of the type of the enum constant represented
+	 * by this annotation component value as described in the JVM specifications.
+	 * This is initialized only if the tag item is 'e'.
+	 * 
+	 * @return the enum constant
+	 * @since 3.1
+	 */
+	char[] getEnumConstantTypeName();	
+	
+	/**
+	 * Answer back the utf8 constant index as described in the JVM specifications.
+	 * This is initialized only if the tag item is 'e'.
+	 * 
+	 * @return the enum constant index
+	 * @since 3.1
+	 */
+	int getEnumConstantTypeNameIndex();
+
 	/**
 	 * Answer back the tag as described in the JVM specifications.
 	 * 
@@ -94,7 +194,7 @@
 	
 	/**
 	 * Answer back the number of values as described in the JVM specifications.
-	 * This is initialized only of the tag item is '['.
+	 * This is initialized only if the tag item is '['.
 	 * 
 	 * @return the number of values
 	 */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationDefaultAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationDefaultAttribute.java
index a25452d..481f970 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationDefaultAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationDefaultAttribute.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials 
  * are made available under the terms of the Common Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,7 +13,6 @@
 /**
  * Description of a annotation default attribute as described in the JVM 
  * specifications (added in J2SE 1.5).
-
  * 
  * This interface may be implemented by clients.
  *  
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IFieldInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IFieldInfo.java
index 43616b7..df0e4ef 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IFieldInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IFieldInfo.java
@@ -28,7 +28,7 @@
 	 * null otherwise
 	 */
 	IConstantValueAttribute getConstantValueAttribute();
-
+	
 	/**
 	 * Answer back the access flag of this field info.
 	 * 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IMethodInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IMethodInfo.java
index 3b6cf05..9676c43 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IMethodInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IMethodInfo.java
@@ -14,7 +14,7 @@
  * Description of a method info as described in the JVM 
  * specifications.
  *  
- * This interface may be implemented by clients. 
+ * This interface may be implemented by clients.
  * 
  * @since 2.0
  */
@@ -114,7 +114,7 @@
 	 * 	@return the exception attribute of this method info, null is none
 	 */
 	IExceptionAttribute getExceptionAttribute();
-	
+
 	/**
 	 * Answer back the attribute number of the method info. It includes the CodeAttribute
 	 * if any even if the decoding flags doesn't include METHOD_BODIES.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
index a4e34ee..ae47d02 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
@@ -68,14 +68,6 @@
 	this.options = options;
 	this.javadocParser.checkDocComment = false;
 }
-
-/*
- *
- * INTERNAL USE-ONLY
- */
-protected void adjustInterfaceModifiers() {
-	intStack[intPtr - 2] |= AccInterface;
-}
 /*
  * Will clear the comment stack when looking
  * for a potential JavaDoc which might contain @deprecated.
@@ -220,7 +212,7 @@
 
 	}
 }
-protected void consumeClassHeaderName() {
+protected void consumeClassHeaderName1() {
 	// ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
 	TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
 	if (nestedMethod[nestedType] == 0) {
@@ -251,6 +243,16 @@
 	if (typeDecl.declarationSourceStart > declSourceStart) {
 		typeDecl.declarationSourceStart = declSourceStart;
 	}
+	// consume annotations
+	int length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			typeDecl.annotations = new Annotation[length], 
+			0, 
+			length); 
+	}
 	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
 	pushOnAstStack(typeDecl);
 	// javadoc
@@ -370,6 +372,16 @@
 	cd.declarationSourceStart = intStack[intPtr--];
 	cd.modifiersSourceStart = intStack[intPtr--];
 	cd.modifiers = intStack[intPtr--];
+	// consume annotations
+	int length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			cd.annotations = new Annotation[length], 
+			0, 
+			length); 
+	}
 	// javadoc
 	cd.javadoc = this.javadoc;
 	this.javadoc = null;
@@ -388,6 +400,7 @@
 	pushOnIntStack(
 		declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition); 
 	resetModifiers();
+	pushOnExpressionStackLengthStack(0);
 }
 protected void consumeDiet() {
 	// Diet ::= $empty
@@ -450,6 +463,16 @@
 			declaration.modifiersSourceStart = intStack[intPtr--];
 			declaration.modifiers = intStack[intPtr--];
 		}
+		// consume annotations
+		int length;
+		if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+			System.arraycopy(
+				this.expressionStack, 
+				(this.expressionPtr -= length) + 1, 
+				declaration.annotations = new Annotation[length], 
+				0, 
+				length); 
+		}
 	} else {
 		type = (TypeReference) astStack[astPtr - variableIndex];
 		typeDim = type.dimensions();
@@ -538,7 +561,7 @@
 		requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
 	}
 }
-protected void consumeFormalParameter() {
+protected void consumeFormalParameter(boolean isVarArgs) {
 	// FormalParameter ::= Type VariableDeclaratorId ==> false
 	// FormalParameter ::= Modifiers Type VariableDeclaratorId ==> true
 	/*
@@ -554,14 +577,38 @@
 	identifierLengthPtr--;
 	char[] parameterName = identifierStack[identifierPtr];
 	long namePositions = identifierPositionStack[identifierPtr--];
-	TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
+	int extendedDimensions = this.intStack[this.intPtr--];
+	int endOfEllipsis = 0;
+	if (isVarArgs) {
+		endOfEllipsis = this.intStack[this.intPtr--];
+	}
+	int firstDimensions = this.intStack[this.intPtr--];
+	final int typeDimensions = firstDimensions + extendedDimensions;
+	TypeReference type = getTypeReference(typeDimensions);
+	if (isVarArgs) {
+		type = type.copyDims(typeDimensions + 1);
+		if (extendedDimensions == 0) {
+			type.sourceEnd = endOfEllipsis;
+		}
+		type.bits |= ASTNode.IsVarArgs; // set isVarArgs
+	}
 	intPtr -= 3;
 	Argument arg = 
 		new Argument(
 			parameterName, 
 			namePositions, 
 			type, 
-			intStack[intPtr + 1]); // modifiers
+			intStack[intPtr + 1]);// modifiers
+	// consume annotations
+	int length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			arg.annotations = new Annotation[length], 
+			0, 
+			length); 
+	}
 	pushOnAstStack(arg);
 	intArrayPtr--;
 }
@@ -627,7 +674,7 @@
 		interfacenameEnds, 
 		scanner.currentPosition - 1); 
 }
-protected void consumeInterfaceHeaderName() {
+protected void consumeInterfaceHeaderName1() {
 	// InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
 	TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
 	if (nestedMethod[nestedType] == 0) {
@@ -654,10 +701,20 @@
 	intPtr--;
 	int declSourceStart = intStack[intPtr--];
 	typeDecl.modifiersSourceStart = intStack[intPtr--];
-	typeDecl.modifiers = intStack[intPtr--];
+	typeDecl.modifiers = this.intStack[this.intPtr--] | AccInterface;
 	if (typeDecl.declarationSourceStart > declSourceStart) {
 		typeDecl.declarationSourceStart = declSourceStart;
 	}
+	// consume annotations
+	int length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			typeDecl.annotations = new Annotation[length], 
+			0, 
+			length); 
+	}
 	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
 	pushOnAstStack(typeDecl);
 	// javadoc
@@ -802,10 +859,14 @@
 		}
 	}
 }
-protected void consumeMethodHeaderName() {
+protected void consumeMethodHeaderName(boolean isAnnotationMethod) {
 	// MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
-	MethodDeclaration md = new MethodDeclaration(this.compilationUnit.compilationResult);
-
+	MethodDeclaration md = null;
+	if(isAnnotationMethod) {
+		md = new AnnotationMethodDeclaration(this.compilationUnit.compilationResult);
+	} else {
+		md = new MethodDeclaration(this.compilationUnit.compilationResult);
+	}
 	//name
 	md.selector = identifierStack[identifierPtr];
 	selectorSourcePositions = identifierPositionStack[identifierPtr--];
@@ -816,6 +877,16 @@
 	md.declarationSourceStart = intStack[intPtr--];
 	md.modifiersSourceStart = intStack[intPtr--];
 	md.modifiers = intStack[intPtr--];
+	// consume annotations
+	int length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack, 
+			(this.expressionPtr -= length) + 1, 
+			md.annotations = new Annotation[length], 
+			0, 
+			length); 
+	}
 	// javadoc
 	md.javadoc = this.javadoc;
 	this.javadoc = null;
@@ -851,6 +922,24 @@
 		CharOperation.concatWith(importReference.getImportName(), '.'),
 		importReference.sourceStart);
 }
+/*
+*
+* INTERNAL USE-ONLY
+*/
+protected void consumePackageDeclarationNameWithModifiers() {
+	/* persisting javadoc positions */
+	pushOnIntArrayStack(this.getJavaDocPositions());
+
+	super.consumePackageDeclarationNameWithModifiers();
+	ImportReference importReference = compilationUnit.currentPackage;
+
+	requestor.acceptPackage(
+		importReference.declarationSourceStart, 
+		importReference.declarationSourceEnd, 
+		intArrayStack[intArrayPtr--], 
+		CharOperation.concatWith(importReference.getImportName(), '.'),
+		importReference.sourceStart);
+}
 protected void consumePushModifiers() {
 	checkComment(); // might update modifiers with AccDeprecated
 	pushOnIntStack(modifiers); // modifiers
@@ -864,6 +953,38 @@
 			declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart); 
 	}
 	resetModifiers();
+	pushOnExpressionStackLengthStack(0);
+}
+protected void consumePushRealModifiers() {
+	checkComment(); // might update modifiers with AccDeprecated
+	pushOnIntStack(modifiers); // modifiers
+	if (modifiersSourceStart < 0) {
+		pushOnIntStack(-1);
+		pushOnIntStack(
+			declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition); 
+	} else {
+		pushOnIntStack(modifiersSourceStart);
+		pushOnIntStack(
+			declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart); 
+	}
+	resetModifiers();
+}
+protected void consumeSingleStaticImportDeclarationName() {
+	// SingleTypeImportDeclarationName ::= 'import' 'static' Name
+
+	/* persisting javadoc positions */
+	pushOnIntArrayStack(this.getJavaDocPositions());
+
+	super.consumeSingleStaticImportDeclarationName();
+	ImportReference importReference = (ImportReference) astStack[astPtr];
+	requestor.acceptImport(
+		importReference.declarationSourceStart, 
+		importReference.declarationSourceEnd,
+		intArrayStack[intArrayPtr--],
+		CharOperation.concatWith(importReference.getImportName(), '.'),
+		importReference.sourceStart,
+		false,
+		AccStatic);
 }
 /*
  *
@@ -883,7 +1004,25 @@
 		intArrayStack[intArrayPtr--],
 		CharOperation.concatWith(importReference.getImportName(), '.'),
 		importReference.sourceStart,
-		false);
+		false,
+		AccDefault);
+}
+protected void consumeStaticImportOnDemandDeclarationName() {
+	// SingleTypeImportDeclarationName ::= 'import' 'static' Name '.' '*'
+
+	/* persisting javadoc positions */
+	pushOnIntArrayStack(this.getJavaDocPositions());
+
+	super.consumeStaticImportOnDemandDeclarationName();
+	ImportReference importReference = (ImportReference) astStack[astPtr];
+	requestor.acceptImport(
+		importReference.declarationSourceStart, 
+		importReference.declarationSourceEnd,
+		intArrayStack[intArrayPtr--],
+		CharOperation.concatWith(importReference.getImportName(), '.'),
+		importReference.sourceStart,
+		true,
+		AccStatic);
 }
 /*
  *
@@ -933,13 +1072,8 @@
 		intArrayStack[intArrayPtr--],
 		CharOperation.concatWith(importReference.getImportName(), '.'), 
 		importReference.sourceStart,
-		true);
-}
-public CompilationUnitDeclaration endParse(int act) {
-	if (scanner.recordLineSeparator) {
-		requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
-	}
-	return super.endParse(act);
+		true,
+		AccDefault);
 }
 /*
  * Flush javadocs defined prior to a given positions.
@@ -958,57 +1092,13 @@
 
 	return lastFieldEndPosition = super.flushCommentsDefinedPriorTo(position);
 }
-protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
-This variable is a type reference and dim will be its dimensions*/
-
-	int length;
-	TypeReference ref;
-	if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
-		// single variable reference
-		if (dim == 0) {
-			ref = 
-				new SingleTypeReference(
-					identifierStack[identifierPtr], 
-					identifierPositionStack[identifierPtr--]); 
-		} else {
-			ref = 
-				new ArrayTypeReference(
-					identifierStack[identifierPtr], 
-					dim, 
-					identifierPositionStack[identifierPtr--]); 
-			ref.sourceEnd = endPosition;
-		}
-	} else {
-		if (length < 0) { //flag for precompiled type reference on base types
-			ref = TypeReference.baseTypeReference(-length, dim);
-			ref.sourceStart = intStack[intPtr--];
-			if (dim == 0) {
-				ref.sourceEnd = intStack[intPtr--];
-			} else {
-				intPtr--;
-				ref.sourceEnd = endPosition;
-			}
-		} else { //Qualified variable reference
-			char[][] tokens = new char[length][];
-			identifierPtr -= length;
-			long[] positions = new long[length];
-			System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
-			System.arraycopy(
-				identifierPositionStack, 
-				identifierPtr + 1, 
-				positions, 
-				0, 
-				length); 
-			if (dim == 0) {
-				ref = new QualifiedTypeReference(tokens, positions);
-			} else {
-				ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
-				ref.sourceEnd = endPosition;
-			}
-		}
+public CompilationUnitDeclaration endParse(int act) {
+	if (scanner.recordLineSeparator) {
+		requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
 	}
-	return ref;
+	return super.endParse(act);
 }
+
 public void initialize() {
 	//positionning the parser for a new compilation unit
 	//avoiding stack reallocation and all that....
@@ -1267,8 +1357,7 @@
 	buffer.append(super.toString());
 	return buffer.toString();
 }
-/*
- * 
+/**
  * INTERNAL USE ONLY
  */
 protected TypeReference typeReference(
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/IDocumentElementRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/IDocumentElementRequestor.java
index e1c2d8d..1c00926 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/IDocumentElementRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/IDocumentElementRequestor.java
@@ -62,7 +62,8 @@
 	int[] javaDocPositions,	
 	char[] name, 
 	int nameStartPosition,
-	boolean onDemand);
+	boolean onDemand,
+	int modifiers);
 /**
  * @param declarationStart - a source position corresponding to the start of the package
  *  declaration
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
index 8373d2b..4980020 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
@@ -1,135 +1,159 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials 
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
+ * Copyright (c) 2000, 2004 IBM Corporation and others. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Common Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/cpl-v10.html
  * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
 package org.eclipse.jdt.internal.compiler;
 
 import org.eclipse.jdt.core.compiler.IProblem;
 
 /*
- * Part of the source element parser responsible for building the output.
- * It gets notified of structural information as they are detected, relying
- * on the requestor to assemble them together, based on the notifications it got.
- *
- * The structural investigation includes:
- * - package statement
- * - import statements
- * - top-level types: package member, member types (member types of member types...)
- * - fields
- * - methods
- *
+ * Part of the source element parser responsible for building the output. It
+ * gets notified of structural information as they are detected, relying on the
+ * requestor to assemble them together, based on the notifications it got.
+ * 
+ * The structural investigation includes: - package statement - import
+ * statements - top-level types: package member, member types (member types of
+ * member types...) - fields - methods
+ * 
  * If reference information is requested, then all source constructs are
  * investigated and type, field & method references are provided as well.
- *
- * Any (parsing) problem encountered is also provided.
- *
- * All positions are relative to the exact source fed to the parser.
- *
- * Elements which are complex are notified in two steps:
- * - enter<Element> : once the element header has been identified
- * - exit<Element> : once the element has been fully consumed
- *
- * other simpler elements (package, import) are read all at once:
- * - accept<Element>
- */
- 
-public interface ISourceElementRequestor {
-void acceptConstructorReference(char[] typeName, int argCount, int sourcePosition);
-void acceptFieldReference(char[] fieldName, int sourcePosition);
-/**
- * @param declarationStart This is the position of the first character of the
- *		  				   import keyword.
- * @param declarationEnd This is the position of the ';' ending the import statement
- *						 or the end of the comment following the import.
- * @param name This is the name of the import like specified in the source including the dots. The '.*'
- *             is never included in the name.
- * @param onDemand set to true if the import is an import on demand (e.g. import java.io.*). False otherwise.
- * @param modifiers can be set to static from 1.5 on.
- */
-void acceptImport(
-	int declarationStart,
-	int declarationEnd,
-	char[] name,
-	boolean onDemand,
-	int modifiers);
-/*
- * Table of line separator position. This table is passed once at the end
- * of the parse action, so as to allow computation of normalized ranges.
- *
- * A line separator might corresponds to several characters in the source,
  * 
+ * Any (parsing) problem encountered is also provided.
+ * 
+ * All positions are relative to the exact source fed to the parser.
+ * 
+ * Elements which are complex are notified in two steps: - enter <Element> :
+ * once the element header has been identified - exit <Element> : once the
+ * element has been fully consumed
+ * 
+ * other simpler elements (package, import) are read all at once: - accept
+ * <Element>
  */
-void acceptLineSeparatorPositions(int[] positions);
-void acceptMethodReference(char[] methodName, int argCount, int sourcePosition);
-void acceptPackage(
-	int declarationStart,
-	int declarationEnd,
-	char[] name);
-void acceptProblem(IProblem problem);
-void acceptTypeReference(char[][] typeName, int sourceStart, int sourceEnd);
-void acceptTypeReference(char[] typeName, int sourcePosition);
-void acceptUnknownReference(char[][] name, int sourceStart, int sourceEnd);
-void acceptUnknownReference(char[] name, int sourcePosition);
-void enterClass(
-	int declarationStart,
-	int modifiers,
-	char[] name,
-	int nameSourceStart,
-	int nameSourceEnd,
-	char[] superclass,
-	char[][] superinterfaces);
-void enterCompilationUnit();
-void enterConstructor(
-	int declarationStart,
-	int modifiers,
-	char[] name,
-	int nameSourceStart,
-	int nameSourceEnd,	
-	char[][] parameterTypes,
-	char[][] parameterNames,
-	char[][] exceptionTypes);
-void enterField(
-	int declarationStart,
-	int modifiers,
-	char[] type,
-	char[] name,
-	int nameSourceStart,
-	int nameSourceEnd);
-void enterInitializer(
-	int declarationStart,
-	int modifiers);
-void enterInterface(
-	int declarationStart,
-	int modifiers,
-	char[] name,
-	int nameSourceStart,
-	int nameSourceEnd,
-	char[][] superinterfaces);
-void enterMethod(
-	int declarationStart,
-	int modifiers,
-	char[] returnType,
-	char[] name,
-	int nameSourceStart,
-	int nameSourceEnd,	
-	char[][] parameterTypes,
-	char[][] parameterNames,
-	char[][] exceptionTypes);
-void exitClass(int declarationEnd);
-void exitCompilationUnit(int declarationEnd);
-void exitConstructor(int declarationEnd);
-/*
- * initializationStart denotes the source start of the expression used for initializing
- * the field if any (-1 if no initialization).
- */
-void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd);
-void exitInitializer(int declarationEnd);
-void exitInterface(int declarationEnd);
-void exitMethod(int declarationEnd);
-}
+
+public interface ISourceElementRequestor {
+	
+	public static class TypeInfo {
+		public int kind;
+		public int declarationStart;
+		public int modifiers;
+		public char[] name;
+		public int nameSourceStart;
+		public int nameSourceEnd;
+		public char[] superclass;
+		public char[][] superinterfaces;
+		public TypeParameterInfo[] typeParameters;
+		public long[] annotationPositions;
+	}
+	
+	public static class TypeParameterInfo {
+		public int declarationStart;
+		public int declarationEnd;
+		public char[] name;
+		public int nameSourceStart;
+		public int nameSourceEnd;
+		public char[][] bounds;
+		public long[] annotationPositions;
+	}
+	
+	public static class MethodInfo {
+		public boolean isConstructor;
+		public boolean isAnnotation;
+		public int declarationStart;
+		public int modifiers;
+		public char[] returnType;
+		public char[] name;
+		public int nameSourceStart;
+		public int nameSourceEnd;
+		public char[][] parameterTypes;
+		public char[][] parameterNames;
+		public char[][] exceptionTypes;
+		public TypeParameterInfo[] typeParameters;
+		public long[] annotationPositions;
+	}
+	
+	public static class FieldInfo {
+		public int declarationStart;
+		public int modifiers;
+		public char[] type;
+		public char[] name;
+		public int nameSourceStart; 
+		public int nameSourceEnd;
+		public long[] annotationPositions;
+	}
+	
+	void acceptConstructorReference(char[] typeName, int argCount, int sourcePosition);
+	
+	void acceptFieldReference(char[] fieldName, int sourcePosition);
+	/**
+	 * @param declarationStart
+	 *                   This is the position of the first character of the import
+	 *                   keyword.
+	 * @param declarationEnd
+	 *                   This is the position of the ';' ending the import statement or
+	 *                   the end of the comment following the import.
+	 * @param name
+	 *                   This is the name of the import like specified in the source
+	 *                   including the dots. The '.*' is never included in the name.
+	 * @param onDemand
+	 *                   set to true if the import is an import on demand (e.g. import
+	 *                   java.io.*). False otherwise.
+	 * @param modifiers
+	 *                   can be set to static from 1.5 on.
+	 */
+	void acceptImport(int declarationStart, int declarationEnd, char[] name, boolean onDemand, int modifiers);
+
+	/*
+	 * Table of line separator position. This table is passed once at the end of
+	 * the parse action, so as to allow computation of normalized ranges.
+	 * 
+	 * A line separator might corresponds to several characters in the source,
+	 *  
+	 */
+	void acceptLineSeparatorPositions(int[] positions);
+
+	void acceptMethodReference(char[] methodName, int argCount, int sourcePosition);
+	
+	void acceptPackage(int declarationStart, int declarationEnd, char[] name);
+
+	void acceptProblem(IProblem problem);
+
+	void acceptTypeReference(char[][] typeName, int sourceStart, int sourceEnd);
+
+	void acceptTypeReference(char[] typeName, int sourcePosition);
+
+	void acceptUnknownReference(char[][] name, int sourceStart, int sourceEnd);
+
+	void acceptUnknownReference(char[] name, int sourcePosition);
+
+	void enterCompilationUnit();
+
+	void enterConstructor(MethodInfo methodInfo);
+
+	void enterField(FieldInfo fieldInfo);
+	
+	void enterInitializer(int declarationStart, int modifiers);
+	
+	void enterMethod(MethodInfo methodInfo);
+	
+	void enterType(TypeInfo typeInfo);
+	
+	void exitCompilationUnit(int declarationEnd);
+	
+	void exitConstructor(int declarationEnd);
+
+	/*
+	 * initializationStart denotes the source start of the expression used for
+	 * initializing the field if any (-1 if no initialization).
+	 */
+	void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd);
+	
+	void exitInitializer(int declarationEnd);
+	
+	void exitMethod(int declarationEnd, int defaultValueStart, int defaultValueEnd);
+	
+	void exitType(int declarationEnd);
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java
index 24e9c98..49e6a29 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java
@@ -10,6 +10,8 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler;
 
+import java.util.ArrayList;
+
 import org.eclipse.jdt.internal.compiler.env.*;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.core.compiler.*;
@@ -17,6 +19,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.parser.*;
 import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
 import org.eclipse.jdt.internal.core.util.CommentRecorderParser;
 
 /**
@@ -46,25 +49,40 @@
 	char[][] typeNames;
 	char[][] superTypeNames;
 	int nestedTypeIndex;
-	static final char[] JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
 	NameReference[] unknownRefs;
 	int unknownRefsCounter;
 	LocalDeclarationVisitor localDeclarationVisitor = null;
 	CompilerOptions options;
+	HashtableOfObjectToInt sourceEnds = new HashtableOfObjectToInt();
 	
 /**
  * An ast visitor that visits local type declarations.
  */
 public class LocalDeclarationVisitor extends ASTVisitor {
+	ArrayList declaringTypes;
+	public void pushDeclaringType(TypeDeclaration declaringType) {
+		if (this.declaringTypes == null) {
+			this.declaringTypes = new ArrayList();
+		}
+		this.declaringTypes.add(declaringType);
+	}
+	public void popDeclaringType() {
+		this.declaringTypes.remove(this.declaringTypes.size()-1);
+	}
+	public TypeDeclaration peekDeclaringType() {
+		if (this.declaringTypes == null) return null;
+		int size = this.declaringTypes.size();
+		if (size == 0) return null;
+		return (TypeDeclaration) this.declaringTypes.get(size-1);
+	}
 	public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
-		notifySourceElementRequestor(typeDeclaration, sourceType == null);
+		notifySourceElementRequestor(typeDeclaration, sourceType == null, peekDeclaringType());
 		return false; // don't visit members as this was done during notifySourceElementRequestor(...)
 	}
 	public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) {
-		notifySourceElementRequestor(typeDeclaration, sourceType == null);
+		notifySourceElementRequestor(typeDeclaration, sourceType == null, peekDeclaringType());
 		return false; // don't visit members as this was done during notifySourceElementRequestor(...)
-	}
-	
+	}	
 }
 
 public SourceElementParser(
@@ -102,8 +120,9 @@
 }
 
 public void checkComment() {
-	if (this.currentElement != null && this.scanner.commentPtr >= 0) {
-		flushCommentsDefinedPriorTo(this.endStatementPosition); // discard obsolete comments during recovery
+	// discard obsolete comments while inside methods or fields initializer (see bug 74369)
+	if (!(this.diet && this.dietInt==0) && this.scanner.commentPtr >= 0) {
+		flushCommentsDefinedPriorTo(this.endStatementPosition);
 	}
 	
 	int lastComment = this.scanner.commentPtr;
@@ -119,18 +138,20 @@
 		// check deprecation in last comment if javadoc (can be followed by non-javadoc comments which are simply ignored)	
 		while (lastComment >= 0 && this.scanner.commentStops[lastComment] < 0) lastComment--; // non javadoc comment have negative end positions
 		if (lastComment >= 0 && this.javadocParser != null) {
-			if (this.javadocParser.checkDeprecation(
-					this.scanner.commentStarts[lastComment],
-					this.scanner.commentStops[lastComment] - 1)) { //stop is one over,
+			int commentEnd = this.scanner.commentStops[lastComment] - 1; //stop is one over,
+			// do not report problem before last parsed comment while recovering code...
+			this.javadocParser.reportProblems = this.currentElement == null || commentEnd > this.lastJavadocEnd;
+			if (this.javadocParser.checkDeprecation(this.scanner.commentStarts[lastComment], commentEnd)) {
 				checkAndSetModifiers(AccDeprecated);
 			}
-			this.javadoc = this.javadocParser.docComment;	// null if check javadoc is not activated 
+			this.javadoc = this.javadocParser.docComment;	// null if check javadoc is not activated
+			if (currentElement == null) this.lastJavadocEnd = commentEnd;
 		}
 	}
 
 	if (this.reportReferenceInfo && this.javadocParser.checkDocComment && this.javadoc != null) {
 		// Report reference info in javadoc comment @throws/@exception tags
-		TypeReference[] thrownExceptions = this.javadoc.thrownExceptions;
+		TypeReference[] thrownExceptions = this.javadoc.exceptionReferences;
 		int throwsTagsNbre = thrownExceptions == null ? 0 : thrownExceptions.length;
 		for (int i = 0; i < throwsTagsNbre; i++) {
 			TypeReference typeRef = thrownExceptions[i];
@@ -144,7 +165,7 @@
 		}
 
 		// Report reference info in javadoc comment @see tags
-		Expression[] references = this.javadoc.references;
+		Expression[] references = this.javadoc.seeReferences;
 		int seeTagsNbre = references == null ? 0 : references.length;
 		for (int i = 0; i < seeTagsNbre; i++) {
 			Expression reference = references[i];
@@ -166,7 +187,7 @@
 				JavadocAllocationExpression constructor = (JavadocAllocationExpression) reference;
 				int argCount = constructor.arguments == null ? 0 : constructor.arguments.length;
 				if (constructor.type != null) {
-					char[][] compoundName = constructor.type.getTypeName();
+					char[][] compoundName = constructor.type.getParameterizedTypeName();
 					this.requestor.acceptConstructorReference(compoundName[compoundName.length-1], argCount, constructor.sourceStart);
 					if (!constructor.type.isThis()) {
 						acceptJavadocTypeReference(constructor.type);
@@ -197,67 +218,66 @@
 		requestor.acceptConstructorReference(
 			typeRef instanceof SingleTypeReference 
 				? ((SingleTypeReference) typeRef).token
-				: CharOperation.concatWith(alloc.type.getTypeName(), '.'),
+				: CharOperation.concatWith(alloc.type.getParameterizedTypeName(), '.'),
 			alloc.arguments == null ? 0 : alloc.arguments.length, 
 			alloc.sourceStart);
 	}
 }
-protected void consumeConstructorHeaderName() {
-	// ConstructorHeaderName ::=  Modifiersopt 'Identifier' '('
-
-	/* recovering - might be an empty message send */
-	if (currentElement != null){
-		if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
-			lastCheckPoint = scanner.startPosition; // force to restart at this exact position				
-			restartRecovery = true;
-			return;
-		}
+private long[] collectAnnotationPositions(Annotation[] annotations) {
+	if (annotations == null) return null;
+	int length = annotations.length;
+	long[] result = new long[length];
+	for (int i = 0; i < length; i++) {
+		Annotation annotation = annotations[i];
+		result[i] = (((long) annotation.sourceStart) << 32) + annotation.declarationSourceEnd;
 	}
-	SourceConstructorDeclaration cd = new SourceConstructorDeclaration(this.compilationUnit.compilationResult);
-
-	//name -- this is not really revelant but we do .....
-	cd.selector = identifierStack[identifierPtr];
-	long selectorSourcePositions = identifierPositionStack[identifierPtr--];
-	identifierLengthPtr--;
-
-	//modifiers
-	cd.declarationSourceStart = intStack[intPtr--];
-	cd.modifiers = intStack[intPtr--];
-	// javadoc
-	cd.javadoc = this.javadoc;
-	this.javadoc = null;
-
-	//highlight starts at the selector starts
-	cd.sourceStart = (int) (selectorSourcePositions >>> 32);
-	cd.selectorSourceEnd = (int) selectorSourcePositions;
-	pushOnAstStack(cd);
-
-	cd.sourceEnd = lParenPos;
-	cd.bodyStart = lParenPos+1;
-	listLength = 0; // initialize listLength before reading parameters/throws
-
-	// recovery
-	if (currentElement != null){
-		lastCheckPoint = cd.bodyStart;
-		if ((currentElement instanceof RecoveredType && lastIgnoredToken != TokenNameDOT)
-			|| cd.modifiers != 0){
-			currentElement = currentElement.add(cd, 0);
-			lastIgnoredToken = -1;
-		}
-	}	
+	return result;
 }
-/*
- *
- * INTERNAL USE-ONLY
- */
+protected void consumeAnnotationAsModifier() {
+	super.consumeAnnotationAsModifier();
+	Annotation annotation = (Annotation)expressionStack[expressionPtr];
+	if (reportReferenceInfo) { // accept annotation type reference
+		this.requestor.acceptTypeReference(annotation.type.getTypeName(), annotation.sourceStart, annotation.sourceEnd);
+	}
+}
+protected void consumeConstructorHeaderName() {
+	long selectorSourcePositions = this.identifierPositionStack[this.identifierPtr];
+	int selectorSourceEnd = (int) selectorSourcePositions;
+	int currentAstPtr = this.astPtr;
+	super.consumeConstructorHeaderName();
+	if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
+		this.sourceEnds.put(this.astStack[this.astPtr], selectorSourceEnd);
+}
+protected void consumeConstructorHeaderNameWithTypeParameters() {
+	long selectorSourcePositions = this.identifierPositionStack[this.identifierPtr];
+	int selectorSourceEnd = (int) selectorSourcePositions;
+	int currentAstPtr = this.astPtr;
+	super.consumeConstructorHeaderNameWithTypeParameters();
+	if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
+		this.sourceEnds.put(this.astStack[this.astPtr], selectorSourceEnd);
+}
+protected void consumeEnumConstantWithClassBody() {
+	super.consumeEnumConstantWithClassBody();
+	if ((currentToken == TokenNameCOMMA || currentToken == TokenNameSEMICOLON)
+			&& astStack[astPtr] instanceof FieldDeclaration) {
+		this.sourceEnds.put(this.astStack[this.astPtr], this.scanner.currentPosition - 1);
+	}
+}
+protected void consumeEnumConstantNoClassBody() {
+	super.consumeEnumConstantNoClassBody();
+	if ((currentToken == TokenNameCOMMA || currentToken == TokenNameSEMICOLON)
+			&& this.astStack[this.astPtr] instanceof FieldDeclaration) {
+		this.sourceEnds.put(this.astStack[this.astPtr], this.scanner.currentPosition - 1);
+	}
+}
 protected void consumeExitVariableWithInitialization() {
 	// ExitVariableWithInitialization ::= $empty
 	// the scanner is located after the comma or the semi-colon.
 	// we want to include the comma or the semi-colon
 	super.consumeExitVariableWithInitialization();
 	if ((currentToken == TokenNameCOMMA || currentToken == TokenNameSEMICOLON)
-			&& astStack[astPtr] instanceof SourceFieldDeclaration) {
-		((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
+			&& this.astStack[this.astPtr] instanceof FieldDeclaration) {
+		this.sourceEnds.put(this.astStack[this.astPtr], this.scanner.currentPosition - 1);
 	}
 }
 protected void consumeExitVariableWithoutInitialization() {
@@ -265,8 +285,8 @@
 	// do nothing by default
 	super.consumeExitVariableWithoutInitialization();
 	if ((currentToken == TokenNameCOMMA || currentToken == TokenNameSEMICOLON)
-			&& astStack[astPtr] instanceof SourceFieldDeclaration) {
-		((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
+			&& astStack[astPtr] instanceof FieldDeclaration) {
+		this.sourceEnds.put(this.astStack[this.astPtr], this.scanner.currentPosition - 1);
 	}
 }
 /*
@@ -282,45 +302,21 @@
 		requestor.acceptFieldReference(fr.token, fr.sourceStart);
 	}
 }
-protected void consumeMethodHeaderName() {
-	// MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
-	SourceMethodDeclaration md = new SourceMethodDeclaration(this.compilationUnit.compilationResult);
-
-	//name
-	md.selector = identifierStack[identifierPtr];
-	long selectorSourcePositions = identifierPositionStack[identifierPtr--];
-	identifierLengthPtr--;
-	//type
-	md.returnType = getTypeReference(intStack[intPtr--]);
-	//modifiers
-	md.declarationSourceStart = intStack[intPtr--];
-	md.modifiers = intStack[intPtr--];
-	// javadoc
-	md.javadoc = this.javadoc;
-	this.javadoc = null;
-
-	//highlight starts at selector start
-	md.sourceStart = (int) (selectorSourcePositions >>> 32);
-	md.selectorSourceEnd = (int) selectorSourcePositions;
-	pushOnAstStack(md);
-	md.sourceEnd = lParenPos;
-	md.bodyStart = lParenPos+1;
-	listLength = 0; // initialize listLength before reading parameters/throws
-	
-	// recovery
-	if (currentElement != null){
-		if (currentElement instanceof RecoveredType 
-			//|| md.modifiers != 0
-			|| (scanner.getLineNumber(md.returnType.sourceStart)
-					== scanner.getLineNumber(md.sourceStart))){
-			lastCheckPoint = md.bodyStart;
-			currentElement = currentElement.add(md, 0);
-			lastIgnoredToken = -1;			
-		} else {
-			lastCheckPoint = md.sourceStart;
-			restartRecovery = true;
-		}
-	}		
+protected void consumeMethodHeaderName(boolean isAnnotationMethod) {
+	long selectorSourcePositions = this.identifierPositionStack[this.identifierPtr];
+	int selectorSourceEnd = (int) selectorSourcePositions;
+	int currentAstPtr = this.astPtr;
+	super.consumeMethodHeaderName(isAnnotationMethod);
+	if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
+		this.sourceEnds.put(this.astStack[this.astPtr], selectorSourceEnd);
+}
+protected void consumeMethodHeaderNameWithTypeParameters(boolean isAnnotationMethod) {
+	long selectorSourcePositions = this.identifierPositionStack[this.identifierPtr];
+	int selectorSourceEnd = (int) selectorSourcePositions;
+	int currentAstPtr = this.astPtr;
+	super.consumeMethodHeaderNameWithTypeParameters(isAnnotationMethod);
+	if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
+		this.sourceEnds.put(this.astStack[this.astPtr], selectorSourceEnd);
 }
 /*
  *
@@ -328,9 +324,23 @@
  */
 protected void consumeMethodInvocationName() {
 	// MethodInvocation ::= Name '(' ArgumentListopt ')'
+	super.consumeMethodInvocationName();
 
 	// when the name is only an identifier...we have a message send to "this" (implicit)
-	super.consumeMethodInvocationName();
+	MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
+	Expression[] args = messageSend.arguments;
+	if (reportReferenceInfo) {
+		requestor.acceptMethodReference(
+			messageSend.selector, 
+			args == null ? 0 : args.length, 
+			(int)(messageSend.nameSourcePosition >>> 32));
+	}
+}
+protected void consumeMethodInvocationNameWithTypeArguments() {
+	// MethodInvocation ::= Name '.' TypeArguments 'Identifier' '(' ArgumentListopt ')'
+	super.consumeMethodInvocationNameWithTypeArguments();
+
+	// when the name is only an identifier...we have a message send to "this" (implicit)
 	MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
 	Expression[] args = messageSend.arguments;
 	if (reportReferenceInfo) {
@@ -359,6 +369,21 @@
  *
  * INTERNAL USE-ONLY
  */
+protected void consumeMethodInvocationPrimaryWithTypeArguments() {
+	super.consumeMethodInvocationPrimaryWithTypeArguments();
+	MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
+	Expression[] args = messageSend.arguments;
+	if (reportReferenceInfo) {
+		requestor.acceptMethodReference(
+			messageSend.selector, 
+			args == null ? 0 : args.length, 
+			(int)(messageSend.nameSourcePosition >>> 32));
+	}
+}
+/*
+ *
+ * INTERNAL USE-ONLY
+ */
 protected void consumeMethodInvocationSuper() {
 	// MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
 	super.consumeMethodInvocationSuper();
@@ -371,6 +396,37 @@
 			(int)(messageSend.nameSourcePosition >>> 32));
 	}
 }
+protected void consumeMethodInvocationSuperWithTypeArguments() {
+	// MethodInvocation ::= 'super' '.' TypeArguments 'Identifier' '(' ArgumentListopt ')'
+	super.consumeMethodInvocationSuperWithTypeArguments();
+	MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
+	Expression[] args = messageSend.arguments;
+	if (reportReferenceInfo) {
+		requestor.acceptMethodReference(
+			messageSend.selector, 
+			args == null ? 0 : args.length, 
+			(int)(messageSend.nameSourcePosition >>> 32));
+	}
+}
+protected void consumeSingleStaticImportDeclarationName() {
+	// SingleTypeImportDeclarationName ::= 'import' 'static' Name
+	super.consumeSingleStaticImportDeclarationName();
+	ImportReference impt = (ImportReference)astStack[astPtr];
+	if (reportReferenceInfo) {
+		// Name for static import is TypeName '.' Identifier
+		// => accept unknown ref on identifier
+		int length = impt.tokens.length-1;
+		int start = (int) (impt.sourcePositions[length] >>> 32);
+		requestor.acceptUnknownReference(impt.tokens[length], start);
+		// accept type name
+		if (length > 0) {
+			char[][] compoundName = new char[length][];
+			System.arraycopy(impt.tokens, 0, compoundName, 0, length);
+			int end = (int) impt.sourcePositions[length-1];
+			requestor.acceptTypeReference(compoundName, impt.sourceStart, end);
+		}
+	}
+}
 protected void consumeSingleTypeImportDeclarationName() {
 	// SingleTypeImportDeclarationName ::= 'import' Name
 	/* push an ImportRef build from the last name 
@@ -382,6 +438,17 @@
 		requestor.acceptTypeReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
 	}
 }
+protected void consumeStaticImportOnDemandDeclarationName() {
+	// TypeImportOnDemandDeclarationName ::= 'import' 'static' Name '.' '*'
+	/* push an ImportRef build from the last name 
+	stored in the identifier stack. */
+
+	super.consumeStaticImportOnDemandDeclarationName();
+	ImportReference impt = (ImportReference)astStack[astPtr];
+	if (reportReferenceInfo) {
+		requestor.acceptTypeReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
+	}
+}
 protected void consumeTypeImportOnDemandDeclarationName() {
 	// TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
 	/* push an ImportRef build from the last name 
@@ -394,34 +461,27 @@
 	}
 }
 public MethodDeclaration convertToMethodDeclaration(ConstructorDeclaration c, CompilationResult compilationResult) {
-	SourceMethodDeclaration m = new SourceMethodDeclaration(compilationResult);
-	m.sourceStart = c.sourceStart;
-	m.sourceEnd = c.sourceEnd;
-	m.bodyStart = c.bodyStart;
-	m.bodyEnd = c.bodyEnd;
-	m.declarationSourceEnd = c.declarationSourceEnd;
-	m.declarationSourceStart = c.declarationSourceStart;
-	m.selector = c.selector;
-	m.statements = c.statements;
-	m.modifiers = c.modifiers;
-	m.arguments = c.arguments;
-	m.thrownExceptions = c.thrownExceptions;
-	m.explicitDeclarations = c.explicitDeclarations;
-	m.returnType = null;
-	if (c instanceof SourceConstructorDeclaration) {
-		m.selectorSourceEnd = ((SourceConstructorDeclaration)c).selectorSourceEnd;
-	}
-	return m;
-}
-protected FieldDeclaration createFieldDeclaration(char[] fieldName, int sourceStart, int sourceEnd) {
-	return new SourceFieldDeclaration(fieldName, sourceStart, sourceEnd);
+	MethodDeclaration methodDeclaration = super.convertToMethodDeclaration(c, compilationResult);
+	int selectorSourceEnd = this.sourceEnds.removeKey(c);
+	if (selectorSourceEnd != -1)
+		this.sourceEnds.put(methodDeclaration, selectorSourceEnd);
+	return methodDeclaration;
 }
 protected CompilationUnitDeclaration endParse(int act) {
 	if (sourceType != null) {
-		if (sourceType.isInterface()) {
-			consumeInterfaceDeclaration();
-		} else {
-			consumeClassDeclaration();
+		switch (sourceType.getKind()) {
+			case IGenericType.CLASS_DECL :
+				consumeClassDeclaration();
+				break;
+			case IGenericType.INTERFACE_DECL :
+				consumeInterfaceDeclaration();
+				break;
+			case IGenericType.ENUM_DECL :
+				consumeEnumDeclaration();
+				break;
+			case IGenericType.ANNOTATION_TYPE_DECL :
+				consumeAnnotationTypeDeclaration();
+				break;
 		}
 	}
 	if (compilationUnit != null) {
@@ -435,45 +495,61 @@
 	/* build a Reference on a variable that may be qualified or not
 	 * This variable is a type reference and dim will be its dimensions
 	 */
-	int length;
-	if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
-		// single variable reference
+	int length = identifierLengthStack[identifierLengthPtr--];
+	if (length < 0) { //flag for precompiled type reference on base types
+		TypeReference ref = TypeReference.baseTypeReference(-length, dim);
+		ref.sourceStart = intStack[intPtr--];
 		if (dim == 0) {
-			SingleTypeReference ref = 
-				new SingleTypeReference(
-					identifierStack[identifierPtr], 
-					identifierPositionStack[identifierPtr--]);
-			if (reportReferenceInfo) {
-				requestor.acceptTypeReference(ref.token, ref.sourceStart);
-			}
-			return ref;
+			ref.sourceEnd = intStack[intPtr--];
 		} else {
-			ArrayTypeReference ref = 
-				new ArrayTypeReference(
-					identifierStack[identifierPtr], 
-					dim, 
-					identifierPositionStack[identifierPtr--]); 
+			intPtr--; // no need to use this position as it is an array
 			ref.sourceEnd = endPosition;
-			if (reportReferenceInfo) {
-				requestor.acceptTypeReference(ref.token, ref.sourceStart);
-			}
-			return ref;
 		}
+		if (reportReferenceInfo){
+				requestor.acceptTypeReference(ref.getParameterizedTypeName(), ref.sourceStart, ref.sourceEnd);
+		}
+		return ref;
 	} else {
-		if (length < 0) { //flag for precompiled type reference on base types
-			TypeReference ref = TypeReference.baseTypeReference(-length, dim);
-			ref.sourceStart = intStack[intPtr--];
-			if (dim == 0) {
-				ref.sourceEnd = intStack[intPtr--];
-			} else {
-				intPtr--; // no need to use this position as it is an array
-				ref.sourceEnd = endPosition;
-			}
-			if (reportReferenceInfo){
-					requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart, ref.sourceEnd);
+		int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr--];
+		if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
+			// generic type
+			TypeReference ref = getTypeReferenceForGenericType(dim, length, numberOfIdentifiers);
+			if (reportReferenceInfo) {
+				if (length == 1 && numberOfIdentifiers == 1) {
+					ParameterizedSingleTypeReference parameterizedSingleTypeReference = (ParameterizedSingleTypeReference) ref;
+					requestor.acceptTypeReference(parameterizedSingleTypeReference.token, parameterizedSingleTypeReference.sourceStart);
+				} else {
+					ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference = (ParameterizedQualifiedTypeReference) ref;
+					requestor.acceptTypeReference(parameterizedQualifiedTypeReference.tokens, parameterizedQualifiedTypeReference.sourceStart, parameterizedQualifiedTypeReference.sourceEnd);
+				}
 			}
 			return ref;
-		} else { //Qualified variable reference
+		} else if (length == 1) {
+			// single variable reference
+			this.genericsLengthPtr--; // pop the 0
+			if (dim == 0) {
+				SingleTypeReference ref = 
+					new SingleTypeReference(
+						identifierStack[identifierPtr], 
+						identifierPositionStack[identifierPtr--]);
+				if (reportReferenceInfo) {
+					requestor.acceptTypeReference(ref.token, ref.sourceStart);
+				}
+				return ref;
+			} else {
+				ArrayTypeReference ref = 
+					new ArrayTypeReference(
+						identifierStack[identifierPtr], 
+						dim, 
+						identifierPositionStack[identifierPtr--]); 
+				ref.sourceEnd = endPosition;
+				if (reportReferenceInfo) {
+					requestor.acceptTypeReference(ref.token, ref.sourceStart);
+				}
+				return ref;
+			}
+		} else {//Qualified variable reference
+			this.genericsLengthPtr--;
 			char[][] tokens = new char[length][];
 			identifierPtr -= length;
 			long[] positions = new long[length];
@@ -551,7 +627,7 @@
 				identifierStack[identifierPtr], 
 				identifierPositionStack[identifierPtr--]); 
 		ref.bits &= ~ASTNode.RestrictiveFlagMASK;
-		ref.bits |= LOCAL | FIELD;
+		ref.bits |= Binding.LOCAL | Binding.FIELD;
 		if (reportReferenceInfo) {
 			this.addUnknownRef(ref);
 		}
@@ -577,7 +653,7 @@
 	// sourceStart
 	 (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
 	ref.bits &= ~ASTNode.RestrictiveFlagMASK;
-	ref.bits |= LOCAL | FIELD;
+	ref.bits |= Binding.LOCAL | Binding.FIELD;
 	if (reportReferenceInfo) {
 		this.addUnknownRef(ref);
 	}
@@ -657,7 +733,7 @@
 					notifySourceElementRequestor(importRef, false);
 				}
 			} else { // instanceof TypeDeclaration
-				notifySourceElementRequestor((TypeDeclaration)node, sourceType == null);
+				notifySourceElementRequestor((TypeDeclaration)node, sourceType == null, null);
 			}
 		}
 	}
@@ -672,8 +748,8 @@
 private void notifyAllUnknownReferences() {
 	for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
 		NameReference nameRef = this.unknownRefs[i];
-		if ((nameRef.bits & BindingIds.VARIABLE) != 0) {
-			if ((nameRef.bits & BindingIds.TYPE) == 0) { 
+		if ((nameRef.bits & Binding.VARIABLE) != 0) {
+			if ((nameRef.bits & Binding.TYPE) == 0) { 
 				// variable but not type
 				if (nameRef instanceof SingleNameReference) { 
 					// local var or field
@@ -697,7 +773,7 @@
 					requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
 				}
 			}
-		} else if ((nameRef.bits & BindingIds.TYPE) != 0) {
+		} else if ((nameRef.bits & Binding.TYPE) != 0) {
 			if (nameRef instanceof SingleNameReference) {
 				requestor.acceptTypeReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
 			} else {
@@ -748,15 +824,17 @@
 	}	
 	char[][] argumentTypes = null;
 	char[][] argumentNames = null;
+	boolean isVarArgs = false;
 	Argument[] arguments = methodDeclaration.arguments;
 	if (arguments != null) {
 		int argumentLength = arguments.length;
 		argumentTypes = new char[argumentLength][];
 		argumentNames = new char[argumentLength][];
 		for (int i = 0; i < argumentLength; i++) {
-			argumentTypes[i] = returnTypeName(arguments[i].type);
+			argumentTypes[i] = CharOperation.concatWith(arguments[i].type.getParameterizedTypeName(), '.');
 			argumentNames[i] = arguments[i].name;
 		}
+		isVarArgs = arguments[argumentLength-1].isVarArgs();
 	}
 	char[][] thrownExceptionTypes = null;
 	TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
@@ -765,26 +843,31 @@
 		thrownExceptionTypes = new char[thrownExceptionLength][];
 		for (int i = 0; i < thrownExceptionLength; i++) {
 			thrownExceptionTypes[i] = 
-				CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.'); 
+				CharOperation.concatWith(thrownExceptions[i].getParameterizedTypeName(), '.'); 
 		}
 	}
 	// by default no selector end position
 	int selectorSourceEnd = -1;
 	if (methodDeclaration.isConstructor()) {
-		if (methodDeclaration instanceof SourceConstructorDeclaration) {
-			selectorSourceEnd = 
-				((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd; 
-		}
+		selectorSourceEnd = this.sourceEnds.get(methodDeclaration);
 		if (isInRange){
-			requestor.enterConstructor(
-				methodDeclaration.declarationSourceStart, 
-				methodDeclaration.modifiers, 
-				methodDeclaration.selector, 
-				methodDeclaration.sourceStart, 
-				selectorSourceEnd, 
-				argumentTypes, 
-				argumentNames, 
-				thrownExceptionTypes);
+			int currentModifiers = methodDeclaration.modifiers;
+			if (isVarArgs)
+				currentModifiers |= AccVarargs;
+			boolean deprecated = (currentModifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
+			ISourceElementRequestor.MethodInfo methodInfo = new ISourceElementRequestor.MethodInfo();
+			methodInfo.isConstructor = true;
+			methodInfo.declarationStart = methodDeclaration.declarationSourceStart;
+			methodInfo.modifiers = deprecated ? (currentModifiers & AccJustFlag) | AccDeprecated : currentModifiers & AccJustFlag;
+			methodInfo.name = methodDeclaration.selector;
+			methodInfo.nameSourceStart = methodDeclaration.sourceStart;
+			methodInfo.nameSourceEnd = selectorSourceEnd;
+			methodInfo.parameterTypes = argumentTypes;
+			methodInfo.parameterNames = argumentNames;
+			methodInfo.exceptionTypes = thrownExceptionTypes;
+			methodInfo.typeParameters = getTypeParameterInfos(methodDeclaration.typeParameters());
+			methodInfo.annotationPositions = collectAnnotationPositions(methodDeclaration.annotations);
+			requestor.enterConstructor(methodInfo);
 		}
 		if (reportReferenceInfo) {
 			ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
@@ -813,89 +896,161 @@
 		}
 		return;
 	}
-	if (methodDeclaration instanceof SourceMethodDeclaration) {
-		selectorSourceEnd = 
-			((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd; 
-	}
+	selectorSourceEnd = this.sourceEnds.get(methodDeclaration);
 	if (isInRange) {
 		int currentModifiers = methodDeclaration.modifiers;
+		if (isVarArgs)
+			currentModifiers |= AccVarargs;
 		boolean deprecated = (currentModifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
-		requestor.enterMethod(
-			methodDeclaration.declarationSourceStart, 
-			deprecated ? (currentModifiers & AccJustFlag) | AccDeprecated : currentModifiers & AccJustFlag, 
-			returnTypeName(((MethodDeclaration) methodDeclaration).returnType), 
-			methodDeclaration.selector, 
-			methodDeclaration.sourceStart, 
-			selectorSourceEnd, 
-			argumentTypes, 
-			argumentNames, 
-			thrownExceptionTypes); 
+		TypeReference returnType = methodDeclaration instanceof MethodDeclaration
+			? ((MethodDeclaration) methodDeclaration).returnType
+			: null;
+		ISourceElementRequestor.MethodInfo methodInfo = new ISourceElementRequestor.MethodInfo();
+		methodInfo.isAnnotation = methodDeclaration instanceof AnnotationMethodDeclaration;
+		methodInfo.declarationStart = methodDeclaration.declarationSourceStart;
+		methodInfo.modifiers = deprecated ? (currentModifiers & AccJustFlag) | AccDeprecated : currentModifiers & AccJustFlag;
+		methodInfo.returnType = returnType == null ? null : CharOperation.concatWith(returnType.getParameterizedTypeName(), '.');
+		methodInfo.name = methodDeclaration.selector;
+		methodInfo.nameSourceStart = methodDeclaration.sourceStart;
+		methodInfo.nameSourceEnd = selectorSourceEnd;
+		methodInfo.parameterTypes = argumentTypes;
+		methodInfo.parameterNames = argumentNames;
+		methodInfo.exceptionTypes = thrownExceptionTypes;
+		methodInfo.typeParameters = getTypeParameterInfos(methodDeclaration.typeParameters());
+		methodInfo.annotationPositions = collectAnnotationPositions(methodDeclaration.annotations);
+		requestor.enterMethod(methodInfo);
 	}		
+		
 	this.visitIfNeeded(methodDeclaration);
 
-	if (isInRange){	
-		requestor.exitMethod(methodDeclaration.declarationSourceEnd);
+	if (isInRange) {
+		if (methodDeclaration instanceof AnnotationMethodDeclaration) {
+			AnnotationMethodDeclaration annotationMethodDeclaration = (AnnotationMethodDeclaration) methodDeclaration;
+			Expression expression = annotationMethodDeclaration.defaultValue;
+			if (expression != null) {
+				requestor.exitMethod(methodDeclaration.declarationSourceEnd, expression.sourceStart, expression.sourceEnd);
+				return;
+			}
+		} 
+		requestor.exitMethod(methodDeclaration.declarationSourceEnd, -1, -1);
 	}
 }
+private ISourceElementRequestor.TypeParameterInfo[] getTypeParameterInfos(TypeParameter[] typeParameters) {
+	if (typeParameters == null) return null;
+	int typeParametersLength = typeParameters.length;
+	ISourceElementRequestor.TypeParameterInfo[] result = new ISourceElementRequestor.TypeParameterInfo[typeParametersLength];
+	for (int i = 0; i < typeParametersLength; i++) {
+		TypeParameter typeParameter = typeParameters[i];
+		TypeReference firstBound = typeParameter.type;
+		TypeReference[] otherBounds = typeParameter.bounds;
+		char[][] typeParameterBounds = null;
+		if (firstBound != null) {
+			if (otherBounds != null) {
+				int otherBoundsLength = otherBounds.length;
+				char[][] boundNames = new char[otherBoundsLength+1][];
+				boundNames[0] = CharOperation.concatWith(firstBound.getParameterizedTypeName(), '.');
+				for (int j = 0; j < otherBoundsLength; j++) {
+					boundNames[j+1] = 
+						CharOperation.concatWith(otherBounds[j].getParameterizedTypeName(), '.'); 
+				}
+				typeParameterBounds = boundNames;
+			} else {
+				typeParameterBounds = new char[][] { CharOperation.concatWith(firstBound.getParameterizedTypeName(), '.')};
+			}
+		} else {
+			typeParameterBounds = CharOperation.NO_CHAR_CHAR;
+		}
+		ISourceElementRequestor.TypeParameterInfo typeParameterInfo = new ISourceElementRequestor.TypeParameterInfo();
+		typeParameterInfo.declarationStart = typeParameter.declarationSourceStart;
+		typeParameterInfo.declarationEnd = typeParameter.declarationSourceEnd;
+		typeParameterInfo.name = typeParameter.name;
+		typeParameterInfo.nameSourceStart = typeParameter.sourceStart;
+		typeParameterInfo.nameSourceEnd = typeParameter.sourceEnd;
+		typeParameterInfo.bounds = typeParameterBounds;
+		result[i] = typeParameterInfo;
+	}
+	return result;
+}
+
 /*
 * Update the bodyStart of the corresponding parse node
 */
-public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
+public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration, TypeDeclaration declaringType) {
 	
 	// range check
 	boolean isInRange = 
 				scanner.initialPosition <= fieldDeclaration.declarationSourceStart
 				&& scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
 
-	if (fieldDeclaration.isField()) {
-		int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
-		if (fieldDeclaration instanceof SourceFieldDeclaration) {
-			fieldEndPosition = ((SourceFieldDeclaration) fieldDeclaration).fieldEndPosition;
-			if (fieldEndPosition == 0) {
+	switch(fieldDeclaration.getKind()) {
+		case AbstractVariableDeclaration.ENUM_CONSTANT:
+			// accept constructor reference for enum constant
+			if (fieldDeclaration.initialization instanceof AllocationExpression) {
+				AllocationExpression alloc = (AllocationExpression) fieldDeclaration.initialization;
+				requestor.acceptConstructorReference(
+					declaringType.name,
+					alloc.arguments == null ? 0 : alloc.arguments.length, 
+					alloc.sourceStart);
+			}
+			// fall through next case
+		case AbstractVariableDeclaration.FIELD:
+			int fieldEndPosition = this.sourceEnds.get(fieldDeclaration);
+			if (fieldEndPosition == -1) {
 				// use the declaration source end by default
 				fieldEndPosition = fieldDeclaration.declarationSourceEnd;
 			}
-		}
-		if (isInRange) {
-			int currentModifiers = fieldDeclaration.modifiers;
-			boolean deprecated = (currentModifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
-			requestor.enterField(
-				fieldDeclaration.declarationSourceStart, 
-				deprecated ? (currentModifiers & AccJustFlag) | AccDeprecated : currentModifiers & AccJustFlag, 
-				returnTypeName(fieldDeclaration.type), 
-				fieldDeclaration.name, 
-				fieldDeclaration.sourceStart, 
-				fieldDeclaration.sourceEnd); 
-		}
-		this.visitIfNeeded(fieldDeclaration);
-		if (isInRange){
-			requestor.exitField(
-				// filter out initializations that are not a constant (simple check)
-				(fieldDeclaration.initialization == null 
-						|| fieldDeclaration.initialization instanceof ArrayInitializer
-						|| fieldDeclaration.initialization instanceof AllocationExpression
-						|| fieldDeclaration.initialization instanceof ArrayAllocationExpression
-						|| fieldDeclaration.initialization instanceof Assignment
-						|| fieldDeclaration.initialization instanceof ClassLiteralAccess
-						|| fieldDeclaration.initialization instanceof MessageSend
-						|| fieldDeclaration.initialization instanceof ArrayReference
-						|| fieldDeclaration.initialization instanceof ThisReference) ? 
-					-1 :  
-					fieldDeclaration.initialization.sourceStart, 
-				fieldEndPosition,
-				fieldDeclaration.declarationSourceEnd);
-		}
-
-	} else {
-		if (isInRange){
-			requestor.enterInitializer(
-				fieldDeclaration.declarationSourceStart,
-				fieldDeclaration.modifiers); 
-		}
-		this.visitIfNeeded((Initializer)fieldDeclaration);
-		if (isInRange){
-			requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
-		}
+			if (isInRange) {
+				int currentModifiers = fieldDeclaration.modifiers;
+				boolean deprecated = (currentModifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
+				char[] typeName = null;
+				if (fieldDeclaration.type == null) {
+					// enum constant
+					typeName = declaringType.name;
+					currentModifiers |= AccEnum;
+				} else {
+					// regular field
+					typeName = CharOperation.concatWith(fieldDeclaration.type.getParameterizedTypeName(), '.');
+				}
+				ISourceElementRequestor.FieldInfo fieldInfo = new ISourceElementRequestor.FieldInfo();
+				fieldInfo.declarationStart = fieldDeclaration.declarationSourceStart;
+				fieldInfo.name = fieldDeclaration.name;
+				fieldInfo.modifiers = deprecated ? (currentModifiers & AccJustFlag) | AccDeprecated : currentModifiers & AccJustFlag;
+				fieldInfo.type = typeName;
+				fieldInfo.nameSourceStart = fieldDeclaration.sourceStart;
+				fieldInfo.nameSourceEnd = fieldDeclaration.sourceEnd;
+				fieldInfo.annotationPositions = collectAnnotationPositions(fieldDeclaration.annotations);
+				requestor.enterField(fieldInfo);
+			}
+			this.visitIfNeeded(fieldDeclaration, declaringType);
+			if (isInRange){
+				requestor.exitField(
+					// filter out initializations that are not a constant (simple check)
+					(fieldDeclaration.initialization == null 
+							|| fieldDeclaration.initialization instanceof ArrayInitializer
+							|| fieldDeclaration.initialization instanceof AllocationExpression
+							|| fieldDeclaration.initialization instanceof ArrayAllocationExpression
+							|| fieldDeclaration.initialization instanceof Assignment
+							|| fieldDeclaration.initialization instanceof ClassLiteralAccess
+							|| fieldDeclaration.initialization instanceof MessageSend
+							|| fieldDeclaration.initialization instanceof ArrayReference
+							|| fieldDeclaration.initialization instanceof ThisReference) ? 
+						-1 :  
+						fieldDeclaration.initialization.sourceStart, 
+					fieldEndPosition,
+					fieldDeclaration.declarationSourceEnd);
+			}
+			break;
+		case AbstractVariableDeclaration.INITIALIZER:
+			if (isInRange){
+				requestor.enterInitializer(
+					fieldDeclaration.declarationSourceStart,
+					fieldDeclaration.modifiers); 
+			}
+			this.visitIfNeeded((Initializer)fieldDeclaration);
+			if (isInRange){
+				requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
+			}
+			break;
 	}
 }
 public void notifySourceElementRequestor(
@@ -915,12 +1070,12 @@
 			importReference.modifiers); 
 	}
 }
-public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
+public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence, TypeDeclaration declaringType) {
 	
 	// range check
 	boolean isInRange = 
-				scanner.initialPosition <= typeDeclaration.declarationSourceStart
-				&& scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
+		scanner.initialPosition <= typeDeclaration.declarationSourceStart
+		&& scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
 	
 	FieldDeclaration[] fields = typeDeclaration.fields;
 	AbstractMethodDeclaration[] methods = typeDeclaration.methods;
@@ -931,8 +1086,7 @@
 	int fieldIndex = 0;
 	int methodIndex = 0;
 	int memberTypeIndex = 0;
-	boolean isInterface = typeDeclaration.isInterface();
-
+	
 	if (notifyTypePresence){
 		char[][] interfaceNames = null;
 		int superInterfacesLength = 0;
@@ -945,7 +1099,7 @@
 				// see PR 3442
 				QualifiedAllocationExpression alloc = typeDeclaration.allocation;
 				if (alloc != null && alloc.type != null) {
-					superInterfaces = new TypeReference[] { typeDeclaration.allocation.type};
+					superInterfaces = new TypeReference[] { alloc.type};
 					superInterfacesLength = 1;
 					interfaceNames = new char[1][];
 				}
@@ -954,69 +1108,66 @@
 		if (superInterfaces != null) {
 			for (int i = 0; i < superInterfacesLength; i++) {
 				interfaceNames[i] = 
-					CharOperation.concatWith(superInterfaces[i].getTypeName(), '.'); 
+					CharOperation.concatWith(superInterfaces[i].getParameterizedTypeName(), '.'); 
 			}
 		}
-		if (isInterface) {
-			if (isInRange){
-				int currentModifiers = typeDeclaration.modifiers;
-				boolean deprecated = (currentModifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
-				requestor.enterInterface(
-					typeDeclaration.declarationSourceStart, 
-					deprecated ? (currentModifiers & AccJustFlag) | AccDeprecated : currentModifiers & AccJustFlag, 
-					typeDeclaration.name, 
-					typeDeclaration.sourceStart, 
-					sourceEnd(typeDeclaration), 
-					interfaceNames);
-			}
-			if (nestedTypeIndex == typeNames.length) {
-				// need a resize
-				System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
-				System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
-			}
-			typeNames[nestedTypeIndex] = typeDeclaration.name;
-			superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
-		} else {
-			TypeReference superclass = typeDeclaration.superclass;
-			if (superclass == null) {
-				if (isInRange){
-					requestor.enterClass(
-						typeDeclaration.declarationSourceStart, 
-						typeDeclaration.modifiers, 
-						typeDeclaration.name, 
-						typeDeclaration.sourceStart, 
-						sourceEnd(typeDeclaration), 
-						null, 
-						interfaceNames); 
-				}
+		int kind = typeDeclaration.kind();
+		char[] implicitSuperclassName = TypeConstants.CharArray_JAVA_LANG_OBJECT;
+		if (isInRange) {
+			int currentModifiers = typeDeclaration.modifiers;
+			boolean deprecated = (currentModifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
+			boolean isEnumInit = typeDeclaration.allocation != null && typeDeclaration.allocation.enumConstant != null;
+			char[] superclassName;
+			if (isEnumInit) {
+				currentModifiers |= AccEnum;
+				superclassName = declaringType.name;
 			} else {
-				if (isInRange){
-					requestor.enterClass(
-						typeDeclaration.declarationSourceStart, 
-						typeDeclaration.modifiers, 
-						typeDeclaration.name, 
-						typeDeclaration.sourceStart, 
-						sourceEnd(typeDeclaration), 
-						CharOperation.concatWith(superclass.getTypeName(), '.'), 
-						interfaceNames); 
-				}
+				TypeReference superclass = typeDeclaration.superclass;
+				superclassName = superclass != null ? CharOperation.concatWith(superclass.getParameterizedTypeName(), '.') : null;
 			}
-			if (nestedTypeIndex == typeNames.length) {
-				// need a resize
-				System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
-				System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+			ISourceElementRequestor.TypeInfo typeInfo = new ISourceElementRequestor.TypeInfo();
+			typeInfo.kind = kind;
+			typeInfo.declarationStart = typeDeclaration.declarationSourceStart;
+			typeInfo.modifiers = deprecated ? (currentModifiers & AccJustFlag) | AccDeprecated : currentModifiers & AccJustFlag;
+			typeInfo.name = typeDeclaration.name;
+			typeInfo.nameSourceStart = typeDeclaration.sourceStart;
+			typeInfo.nameSourceEnd = sourceEnd(typeDeclaration);
+			typeInfo.superclass = superclassName;
+			typeInfo.superinterfaces = interfaceNames;
+			typeInfo.typeParameters = getTypeParameterInfos(typeDeclaration.typeParameters);
+			typeInfo.annotationPositions = collectAnnotationPositions(typeDeclaration.annotations);
+			requestor.enterType(typeInfo);
+			switch (kind) {
+				case IGenericType.CLASS_DECL :
+					if (superclassName != null)
+						implicitSuperclassName = superclassName;
+					break;
+				case IGenericType.INTERFACE_DECL :
+					implicitSuperclassName = TypeConstants.CharArray_JAVA_LANG_OBJECT;
+					break;
+				case IGenericType.ENUM_DECL :
+					implicitSuperclassName = TypeConstants.CharArray_JAVA_LANG_ENUM;
+					break;
+				case IGenericType.ANNOTATION_TYPE_DECL :
+					implicitSuperclassName = TypeConstants.CharArray_JAVA_LANG_ANNOTATION_ANNOTATION;
+					break;
 			}
-			typeNames[nestedTypeIndex] = typeDeclaration.name;
-			superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass.getTypeName(), '.');
 		}
+		if (this.nestedTypeIndex == this.typeNames.length) {
+			// need a resize
+			System.arraycopy(this.typeNames, 0, (this.typeNames = new char[this.nestedTypeIndex * 2][]), 0, this.nestedTypeIndex);
+			System.arraycopy(this.superTypeNames, 0, (this.superTypeNames = new char[this.nestedTypeIndex * 2][]), 0, this.nestedTypeIndex);
+		}
+		this.typeNames[this.nestedTypeIndex] = typeDeclaration.name;
+		this.superTypeNames[this.nestedTypeIndex++] = implicitSuperclassName;
 	}
 	while ((fieldIndex < fieldCounter)
-		|| (memberTypeIndex < memberTypeCounter)
-		|| (methodIndex < methodCounter)) {
+			|| (memberTypeIndex < memberTypeCounter)
+			|| (methodIndex < methodCounter)) {
 		FieldDeclaration nextFieldDeclaration = null;
 		AbstractMethodDeclaration nextMethodDeclaration = null;
 		TypeDeclaration nextMemberDeclaration = null;
-
+		
 		int position = Integer.MAX_VALUE;
 		int nextDeclarationType = -1;
 		if (fieldIndex < fieldCounter) {
@@ -1043,7 +1194,7 @@
 		switch (nextDeclarationType) {
 			case 0 :
 				fieldIndex++;
-				notifySourceElementRequestor(nextFieldDeclaration);
+				notifySourceElementRequestor(nextFieldDeclaration, typeDeclaration);
 				break;
 			case 1 :
 				methodIndex++;
@@ -1051,23 +1202,22 @@
 				break;
 			case 2 :
 				memberTypeIndex++;
-				notifySourceElementRequestor(nextMemberDeclaration, true);
+				notifySourceElementRequestor(nextMemberDeclaration, true, null);
 		}
 	}
 	if (notifyTypePresence){
 		if (isInRange){
-			if (isInterface) {
-				requestor.exitInterface(typeDeclaration.declarationSourceEnd);
-			} else {
-				requestor.exitClass(typeDeclaration.declarationSourceEnd);
-			}
+			requestor.exitType(typeDeclaration.declarationSourceEnd);
 		}
 		nestedTypeIndex--;
 	}
 }
 private int sourceEnd(TypeDeclaration typeDeclaration) {
 	if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
-		return typeDeclaration.allocation.type.sourceEnd;
+		QualifiedAllocationExpression allocation = typeDeclaration.allocation;
+		if (allocation.type == null) // case of enum constant body
+			return typeDeclaration.sourceEnd;
+		return allocation.type.sourceEnd;
 	} else {
 		return typeDeclaration.sourceEnd;
 	}
@@ -1259,30 +1409,6 @@
 		quickSort(sortedCollection, left, original_right);
 	}
 }
-/*
- * Answer a char array representation of the type name formatted like:
- * - type name + dimensions
- * Example:
- * "A[][]".toCharArray()
- * "java.lang.String".toCharArray()
- */
-private char[] returnTypeName(TypeReference type) {
-	if (type == null)
-		return null;
-	int dimension = type.dimensions();
-	if (dimension != 0) {
-		char[] dimensionsArray = new char[dimension * 2];
-		for (int i = 0; i < dimension; i++) {
-			dimensionsArray[i * 2] = '[';
-			dimensionsArray[(i * 2) + 1] = ']';
-		}
-		return CharOperation.concat(
-			CharOperation.concatWith(type.getTypeName(), '.'), 
-			dimensionsArray); 
-	}
-	return CharOperation.concatWith(type.getTypeName(), '.');
-}
-
 public void addUnknownRef(NameReference nameRef) {
 	if (this.unknownRefs.length == this.unknownRefsCounter) {
 		// resize
@@ -1299,6 +1425,12 @@
 private void visitIfNeeded(AbstractMethodDeclaration method) {
 	if (this.localDeclarationVisitor != null 
 		&& (method.bits & ASTNode.HasLocalTypeMASK) != 0) {
+			if (method instanceof ConstructorDeclaration) {
+				ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) method;
+				if (constructorDeclaration.constructorCall != null) {
+					constructorDeclaration.constructorCall.traverse(this.localDeclarationVisitor, method.scope);
+				}
+			}
 			if (method.statements != null) {
 				int statementsLength = method.statements.length;
 				for (int i = 0; i < statementsLength; i++)
@@ -1307,11 +1439,16 @@
 	}
 }
 
-private void visitIfNeeded(FieldDeclaration field) {
+private void visitIfNeeded(FieldDeclaration field, TypeDeclaration declaringType) {
 	if (this.localDeclarationVisitor != null 
 		&& (field.bits & ASTNode.HasLocalTypeMASK) != 0) {
 			if (field.initialization != null) {
-				field.initialization.traverse(this.localDeclarationVisitor, null);
+				try {
+					this.localDeclarationVisitor.pushDeclaringType(declaringType);
+					field.initialization.traverse(this.localDeclarationVisitor, (MethodScope) null);
+				} finally {
+					this.localDeclarationVisitor.popDeclaringType();
+				}
 			}
 	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java
index 90b43ef..839d904 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java
@@ -112,54 +112,23 @@
 	}
 
 	/**
-	 * @see ISourceElementRequestor#enterClass(int, int, char[], int, int, char[], char[][])
-	 */
-	public void enterClass(
-		int declarationStart,
-		int modifiers,
-		char[] name,
-		int nameSourceStart,
-		int nameSourceEnd,
-		char[] superclass,
-		char[][] superinterfaces) {
-		// default implementation: do nothing
-	}
-
-	/**
 	 * @see ISourceElementRequestor#enterCompilationUnit()
 	 */
 	public void enterCompilationUnit() {
 		// default implementation: do nothing
 	}
 
-	/**
-	 * @see ISourceElementRequestor#enterConstructor(int, int, char[], int, int, char[][], char[][], char[][])
-	 */
-	public void enterConstructor(
-		int declarationStart,
-		int modifiers,
-		char[] name,
-		int nameSourceStart,
-		int nameSourceEnd,
-		char[][] parameterTypes,
-		char[][] parameterNames,
-		char[][] exceptionTypes) {
+	public void enterConstructor(MethodInfo methodInfo) {
 		// default implementation: do nothing
 	}
-
+	
 	/**
-	 * @see ISourceElementRequestor#enterField(int, int, char[], char[], int, int)
+	 * @see ISourceElementRequestor#enterField(FieldInfo)
 	 */
-	public void enterField(
-		int declarationStart,
-		int modifiers,
-		char[] type,
-		char[] name,
-		int nameSourceStart,
-		int nameSourceEnd) {
+	public void enterField(FieldInfo fieldInfo) {
 		// default implementation: do nothing
 	}
-
+	
 	/**
 	 * @see ISourceElementRequestor#enterInitializer(int, int)
 	 */
@@ -167,42 +136,14 @@
 		// default implementation: do nothing
 	}
 
-	/**
-	 * @see ISourceElementRequestor#enterInterface(int, int, char[], int, int, char[][])
-	 */
-	public void enterInterface(
-		int declarationStart,
-		int modifiers,
-		char[] name,
-		int nameSourceStart,
-		int nameSourceEnd,
-		char[][] superinterfaces) {
+	public void enterMethod(MethodInfo methodInfo) {
 		// default implementation: do nothing
 	}
-
-	/**
-	 * @see ISourceElementRequestor#enterMethod(int, int, char[], char[], int, int, char[][], char[][], char[][])
-	 */
-	public void enterMethod(
-		int declarationStart,
-		int modifiers,
-		char[] returnType,
-		char[] name,
-		int nameSourceStart,
-		int nameSourceEnd,
-		char[][] parameterTypes,
-		char[][] parameterNames,
-		char[][] exceptionTypes) {
+	
+	public void enterType(TypeInfo typeInfo) {
 		// default implementation: do nothing
 	}
-
-	/**
-	 * @see ISourceElementRequestor#exitClass(int)
-	 */
-	public void exitClass(int declarationEnd) {
-		// default implementation: do nothing
-	}
-
+	
 	/**
 	 * @see ISourceElementRequestor#exitCompilationUnit(int)
 	 */
@@ -218,7 +159,7 @@
 	}
 
 	/**
-	 * @see ISourceElementRequestor#exitField(int)
+	 * @see ISourceElementRequestor#exitField(int, int, int)
 	 */
 	public void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd) {
 		// default implementation: do nothing
@@ -232,17 +173,18 @@
 	}
 
 	/**
-	 * @see ISourceElementRequestor#exitInterface(int)
+	 * @see ISourceElementRequestor#exitMethod(int, int, int)
 	 */
-	public void exitInterface(int declarationEnd) {
+	public void exitMethod(int declarationEnd, int defaultValueStart, int defaultValueEnd) {
+		// default implementation: do nothing
+	}
+	
+	/**
+	 * @see ISourceElementRequestor#exitType(int)
+	 */
+	public void exitType(int declarationEnd) {
 		// default implementation: do nothing
 	}
 
-	/**
-	 * @see ISourceElementRequestor#exitMethod(int)
-	 */
-	public void exitMethod(int declarationEnd) {
-		// default implementation: do nothing
-	}
 }
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceConstructorDeclaration.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceConstructorDeclaration.java
deleted file mode 100644
index c57cee9..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceConstructorDeclaration.java
+++ /dev/null
@@ -1,22 +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 Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.compiler.parser;
-
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
-
-public class SourceConstructorDeclaration extends ConstructorDeclaration {
-	public int selectorSourceEnd;
-
-	public SourceConstructorDeclaration(CompilationResult compilationResult){
-		super(compilationResult);
-	}
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceFieldDeclaration.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceFieldDeclaration.java
deleted file mode 100644
index c1e2c37..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceFieldDeclaration.java
+++ /dev/null
@@ -1,23 +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 Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.compiler.parser;
-
-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-
-public class SourceFieldDeclaration extends FieldDeclaration {
-	public int fieldEndPosition;
-public SourceFieldDeclaration(
-	char[] name, 
-	int sourceStart, 
-	int sourceEnd) {
-	super(name, sourceStart, sourceEnd);
-}
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceMethodDeclaration.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceMethodDeclaration.java
deleted file mode 100644
index 3ea92a7..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceMethodDeclaration.java
+++ /dev/null
@@ -1,23 +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 Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.compiler.parser;
-
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
-
-public class SourceMethodDeclaration extends MethodDeclaration {
-	public int selectorSourceEnd;
-	
-	public SourceMethodDeclaration(CompilationResult compilationResult){
-		super(compilationResult);
-	}
-	
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
index c3ccb87..f375804 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
@@ -23,8 +23,15 @@
  *
  */
 
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.ast.*;
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Argument;
@@ -35,17 +42,25 @@
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.eclipse.jdt.internal.compiler.env.ISourceField;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+import org.eclipse.jdt.internal.compiler.env.*;
 import org.eclipse.jdt.internal.compiler.env.ISourceImport;
-import org.eclipse.jdt.internal.compiler.env.ISourceMethod;
 import org.eclipse.jdt.internal.compiler.env.ISourceType;
 
 import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.jdt.internal.core.*;
+import org.eclipse.jdt.internal.core.JavaElement;
+import org.eclipse.jdt.internal.core.SourceFieldElementInfo;
+import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
 
 public class SourceTypeConverter implements CompilerModifiers {
 	
@@ -55,12 +70,18 @@
 	public static final int MEMBER_TYPE = 0x08;
 	public static final int FIELD_INITIALIZATION = 0x10;
 	public static final int FIELD_AND_METHOD = FIELD | CONSTRUCTOR | METHOD;
+	public static final int LOCAL_TYPE = 0x20;
 	public static final int NONE = 0;
 	
 	private int flags;
 	private CompilationUnitDeclaration unit;
 	private Parser parser;
 	private ProblemReporter problemReporter;
+	private ICompilationUnit cu;
+	private char[] source;
+	private HashMap annotationPositions;
+	
+	int namePos;
 	
 	private SourceTypeConverter(int flags, ProblemReporter problemReporter) {
 		this.flags = flags;
@@ -79,8 +100,15 @@
 		ProblemReporter problemReporter,
 		CompilationResult compilationResult) {
 			
-		return 
-			new SourceTypeConverter(flags, problemReporter).convert(sourceTypes, compilationResult);
+//		long start = System.currentTimeMillis();
+		SourceTypeConverter converter = new SourceTypeConverter(flags, problemReporter);
+		try {
+			return converter.convert(sourceTypes, compilationResult);
+		} catch (JavaModelException e) {
+			return null;
+/*		} finally {
+			System.out.println("Spent " + (System.currentTimeMillis() - start) + "ms to convert " + ((JavaElement) converter.cu).toStringWithAncestors());
+*/		}
 	}
 
 	/*
@@ -88,28 +116,32 @@
 	 * The argument types are then all grouped in the same unit. The argument types must 
 	 * at least contain one type.
 	 */
-	private CompilationUnitDeclaration convert(ISourceType[] sourceTypes, CompilationResult compilationResult) {
+	private CompilationUnitDeclaration convert(ISourceType[] sourceTypes, CompilationResult compilationResult) throws JavaModelException {
 		this.unit = new CompilationUnitDeclaration(this.problemReporter, compilationResult, 0);
 		// not filled at this point
 
 		if (sourceTypes.length == 0) return this.unit;
-		ISourceType sourceType = sourceTypes[0];
-		if (sourceType.getName() == null)
-		    // TODO (jerome) investigate when this can happen : if this can happen, fix clients to protect themselves
-			return null; // do a basic test that the sourceType is valid
+		SourceTypeElementInfo topLevelTypeInfo = (SourceTypeElementInfo) sourceTypes[0];
+		this.cu = (ICompilationUnit) topLevelTypeInfo.getHandle().getCompilationUnit();
+		this.annotationPositions = ((CompilationUnitElementInfo) ((JavaElement) this.cu).getElementInfo()).annotationPositions;
+
+		if (this.annotationPositions != null && this.annotationPositions.size() > 10) { // experimental value
+			// if more than 10 annotations, diet parse as this is faster
+			return new Parser(this.problemReporter, true).dietParse(this.cu, compilationResult);
+		}
 
 		/* only positions available */
-		int start = sourceType.getNameSourceStart();
-		int end = sourceType.getNameSourceEnd();
+		int start = topLevelTypeInfo.getNameSourceStart();
+		int end = topLevelTypeInfo.getNameSourceEnd();
 
 		/* convert package and imports */
-		if (sourceType.getPackageName() != null
-			&& sourceType.getPackageName().length > 0)
+		if (topLevelTypeInfo.getPackageName() != null
+			&& topLevelTypeInfo.getPackageName().length > 0)
 			// if its null then it is defined in the default package
 			this.unit.currentPackage =
-				createImportReference(sourceType.getPackageName(), start, end, false, AccDefault);
-		ISourceImport[]  sourceImports = sourceType.getImports();
-		int importCount = sourceImports == null ? 0 : sourceImports.length;
+				createImportReference(topLevelTypeInfo.getPackageName(), start, end, false, AccDefault);
+		ISourceImport[]  sourceImports = topLevelTypeInfo.getImports();
+		int importCount = sourceImports.length;
 		this.unit.imports = new ImportReference[importCount];
 		for (int i = 0; i < importCount; i++) {
 			ISourceImport sourceImport = sourceImports[i];
@@ -124,33 +156,84 @@
 		int typeCount = sourceTypes.length;
 		this.unit.types = new TypeDeclaration[typeCount];
 		for (int i = 0; i < typeCount; i++) {
+			SourceTypeElementInfo typeInfo = (SourceTypeElementInfo) sourceTypes[i];
 			this.unit.types[i] =
-				convert(sourceTypes[i], compilationResult);
+				convert((SourceType) typeInfo.getHandle(), compilationResult);
 		}
 		return this.unit;
 	}
 	
 	/*
+	 * Convert an initializerinfo into a parsed initializer declaration
+	 */
+	private Initializer convert(InitializerElementInfo initializerInfo, CompilationResult compilationResult) throws JavaModelException {
+
+		Block block = new Block(0);
+		Initializer initializer = new Initializer(block, IConstants.AccDefault);
+
+		int start = initializerInfo.getDeclarationSourceStart();
+		int end = initializerInfo.getDeclarationSourceEnd();
+
+		initializer.sourceStart = initializer.declarationSourceStart = start;
+		initializer.sourceEnd = initializer.declarationSourceEnd = end;
+		initializer.modifiers = initializerInfo.getModifiers();
+
+		/* convert local and anonymous types */
+		IJavaElement[] children = initializerInfo.getChildren();
+		int typesLength = children.length;
+		if (typesLength > 0) {
+			Statement[] statements = new Statement[typesLength];
+			for (int i = 0; i < typesLength; i++) {
+				SourceType type = (SourceType) children[i];
+				TypeDeclaration localType = convert(type, compilationResult);
+				if ((localType.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+					QualifiedAllocationExpression expression = new QualifiedAllocationExpression(localType);
+					expression.type = localType.superclass;
+					localType.superclass = null;
+					localType.superInterfaces = null;
+					localType.allocation = expression;
+					statements[i] = expression;
+				} else {
+					statements[i] = localType;
+				}
+			}
+			block.statements = statements;
+		}
+		
+		return initializer;
+	}
+
+	/*
 	 * Convert a field source element into a parsed field declaration
 	 */
-	private FieldDeclaration convert(ISourceField sourceField, TypeDeclaration type) {
+	private FieldDeclaration convert(SourceField fieldHandle, TypeDeclaration type, CompilationResult compilationResult) throws JavaModelException {
 
+		SourceFieldElementInfo fieldInfo = (SourceFieldElementInfo) fieldHandle.getElementInfo();
 		FieldDeclaration field = new FieldDeclaration();
 
-		int start = sourceField.getNameSourceStart();
-		int end = sourceField.getNameSourceEnd();
+		int start = fieldInfo.getNameSourceStart();
+		int end = fieldInfo.getNameSourceEnd();
 
-		field.name = sourceField.getName();
+		field.name = fieldInfo.getName();
 		field.sourceStart = start;
 		field.sourceEnd = end;
-		field.type = createTypeReference(sourceField.getTypeName(), start, end);
-		field.declarationSourceStart = sourceField.getDeclarationSourceStart();
-		field.declarationSourceEnd = sourceField.getDeclarationSourceEnd();
-		field.modifiers = sourceField.getModifiers();
+		field.declarationSourceStart = fieldInfo.getDeclarationSourceStart();
+		field.declarationSourceEnd = fieldInfo.getDeclarationSourceEnd();
+		int modifiers = fieldInfo.getModifiers();
+		boolean isEnumConstant = (modifiers & AccEnum) != 0;
+		if (isEnumConstant) {
+			field.modifiers = modifiers & ~Flags.AccEnum; // clear AccEnum bit onto AST (binding will add it)
+		} else {
+			field.modifiers = modifiers;
+			field.type = createTypeReference(fieldInfo.getTypeName(), start, end);
+		}
 
+		/* convert annotations */
+		field.annotations = convertAnnotations(fieldHandle);
+
+		/* conversion of field constant */
 		if ((this.flags & FIELD_INITIALIZATION) != 0) {
-			/* conversion of field constant */
-			char[] initializationSource = sourceField.getInitializationSource();
+			char[] initializationSource = fieldInfo.getInitializationSource();
 			if (initializationSource != null) {
 				if (this.parser == null) {
 					this.parser = new Parser(this.problemReporter, true);
@@ -159,111 +242,249 @@
 			}
 		}
 		
+		/* conversion of local and anonymous types */
+		if ((this.flags & LOCAL_TYPE) != 0) {
+			IJavaElement[] children = fieldInfo.getChildren();
+			int childrenLength = children.length;
+			if (childrenLength > 0) {
+				ArrayInitializer initializer = new ArrayInitializer();
+				field.initialization = initializer;
+				Expression[] expressions = new Expression[childrenLength];
+				initializer.expressions = expressions;
+				for (int i = 0; i < childrenLength; i++) {
+					IJavaElement localType = children[i];
+					TypeDeclaration anonymousLocalTypeDeclaration = convert((SourceType) localType, compilationResult);
+					QualifiedAllocationExpression expression = new QualifiedAllocationExpression(anonymousLocalTypeDeclaration);
+					expression.type = anonymousLocalTypeDeclaration.superclass;
+					anonymousLocalTypeDeclaration.superclass = null;
+					anonymousLocalTypeDeclaration.superInterfaces = null;
+					anonymousLocalTypeDeclaration.allocation = expression;
+					anonymousLocalTypeDeclaration.modifiers &= ~AccEnum; // remove tag in case this is the init of an enum constant
+					expressions[i] = expression;
+				}
+			}
+		}
 		return field;
 	}
 
 	/*
 	 * Convert a method source element into a parsed method/constructor declaration 
 	 */
-	private AbstractMethodDeclaration convert(ISourceMethod sourceMethod, CompilationResult compilationResult) {
+	private AbstractMethodDeclaration convert(SourceMethod methodHandle, CompilationResult compilationResult) throws JavaModelException {
 
+		SourceMethodElementInfo methodInfo = (SourceMethodElementInfo) methodHandle.getElementInfo();
 		AbstractMethodDeclaration method;
 
 		/* only source positions available */
-		int start = sourceMethod.getNameSourceStart();
-		int end = sourceMethod.getNameSourceEnd();
+		int start = methodInfo.getNameSourceStart();
+		int end = methodInfo.getNameSourceEnd();
 
-		if (sourceMethod.isConstructor()) {
+		/* convert type parameters */
+		char[][] typeParameterNames = methodInfo.getTypeParameterNames();
+		TypeParameter[] typeParams = null;
+		if (typeParameterNames != null) {
+			int parameterCount = typeParameterNames.length;
+			if (parameterCount > 0) { // method's type parameters must be null if no type parameter
+				char[][][] typeParameterBounds = methodInfo.getTypeParameterBounds();
+				typeParams = new TypeParameter[parameterCount];
+				for (int i = 0; i < parameterCount; i++) {
+					typeParams[i] = createTypeParameter(typeParameterNames[i], typeParameterBounds[i], start, end);
+				}
+			}
+		}
+		
+		int modifiers = methodInfo.getModifiers();
+		if (methodInfo.isConstructor()) {
 			ConstructorDeclaration decl = new ConstructorDeclaration(compilationResult);
 			decl.isDefaultConstructor = false;
 			method = decl;
+			decl.typeParameters = typeParams;
 		} else {
-			MethodDeclaration decl = new MethodDeclaration(compilationResult);
-			/* convert return type */
-			decl.returnType =
-				createTypeReference(sourceMethod.getReturnTypeName(), start, end);
+			MethodDeclaration decl;
+			if (methodInfo.isAnnotationMethod()) {
+				AnnotationMethodDeclaration annotationMethodDeclaration = new AnnotationMethodDeclaration(compilationResult);
+
+				/* conversion of default value */
+				if ((this.flags & FIELD_INITIALIZATION) != 0) {
+					char[] defaultValueSource = ((SourceAnnotationMethodInfo) methodInfo).getDefaultValueSource(getSource());
+					if (defaultValueSource != null) {
+						Expression expression =  parseMemberValue(defaultValueSource);
+						if (expression != null) {
+							annotationMethodDeclaration.defaultValue = expression;
+							modifiers |= AccAnnotationDefault;
+						}
+					}
+				}
+				decl = annotationMethodDeclaration;
+			} else {
+				decl = new MethodDeclaration(compilationResult);
+			}
+			
+			// convert return type
+			decl.returnType = createTypeReference(methodInfo.getReturnTypeName(), start, end);
+			
+			// type parameters
+			decl.typeParameters = typeParams;
+			
 			method = decl;
 		}
-		method.selector = sourceMethod.getSelector();
-		method.modifiers = sourceMethod.getModifiers();
+		method.selector = methodInfo.getSelector();
+		boolean isVarargs = (modifiers & AccVarargs) != 0;
+		method.modifiers = modifiers & ~AccVarargs;
 		method.sourceStart = start;
 		method.sourceEnd = end;
-		method.declarationSourceStart = sourceMethod.getDeclarationSourceStart();
-		method.declarationSourceEnd = sourceMethod.getDeclarationSourceEnd();
+		method.declarationSourceStart = methodInfo.getDeclarationSourceStart();
+		method.declarationSourceEnd = methodInfo.getDeclarationSourceEnd();
+
+		/* convert annotations */
+		method.annotations = convertAnnotations(methodHandle);
 
 		/* convert arguments */
-		char[][] argumentTypeNames = sourceMethod.getArgumentTypeNames();
-		char[][] argumentNames = sourceMethod.getArgumentNames();
+		char[][] argumentTypeNames = methodInfo.getArgumentTypeNames();
+		char[][] argumentNames = methodInfo.getArgumentNames();
 		int argumentCount = argumentTypeNames == null ? 0 : argumentTypeNames.length;
-		long position = (long) start << 32 + end;
+		long position = ((long) start << 32) + end;
 		method.arguments = new Argument[argumentCount];
 		for (int i = 0; i < argumentCount; i++) {
+			TypeReference typeReference = createTypeReference(argumentTypeNames[i], start, end);
+			if (isVarargs && i == argumentCount-1) {
+				typeReference.bits |= ASTNode.IsVarArgs;
+			}
 			method.arguments[i] =
 				new Argument(
 					argumentNames[i],
 					position,
-					createTypeReference(argumentTypeNames[i], start, end),
+					typeReference,
 					AccDefault);
 			// do not care whether was final or not
 		}
 
 		/* convert thrown exceptions */
-		char[][] exceptionTypeNames = sourceMethod.getExceptionTypeNames();
+		char[][] exceptionTypeNames = methodInfo.getExceptionTypeNames();
 		int exceptionCount = exceptionTypeNames == null ? 0 : exceptionTypeNames.length;
 		method.thrownExceptions = new TypeReference[exceptionCount];
 		for (int i = 0; i < exceptionCount; i++) {
 			method.thrownExceptions[i] =
 				createTypeReference(exceptionTypeNames[i], start, end);
 		}
+		
+		/* convert local and anonymous types */
+		if ((this.flags & LOCAL_TYPE) != 0) {
+			IJavaElement[] children = methodInfo.getChildren();
+			int typesLength = children.length;
+			if (typesLength != 0) {
+				Statement[] statements = new Statement[typesLength];
+				for (int i = 0; i < typesLength; i++) {
+					SourceType type = (SourceType) children[i];
+					TypeDeclaration localType = convert(type, compilationResult);
+					if ((localType.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+						QualifiedAllocationExpression expression = new QualifiedAllocationExpression(localType);
+						expression.type = localType.superclass;
+						localType.superclass = null;
+						localType.superInterfaces = null;
+						localType.allocation = expression;
+						statements[i] = expression;
+					} else {
+						statements[i] = localType;
+					}
+				}
+				method.statements = statements;
+			}
+		}
+		
 		return method;
 	}
 
 	/*
 	 * Convert a source element type into a parsed type declaration
 	 */
-	private TypeDeclaration convert(ISourceType sourceType, CompilationResult compilationResult) {
+	private TypeDeclaration convert(SourceType typeHandle, CompilationResult compilationResult) throws JavaModelException {
+		SourceTypeElementInfo typeInfo = (SourceTypeElementInfo) typeHandle.getElementInfo();
 		/* create type declaration - can be member type */
 		TypeDeclaration type = new TypeDeclaration(compilationResult);
-		if (sourceType.getEnclosingType() != null) {
+		if (typeInfo.getEnclosingType() == null) {
+			if (typeHandle.isAnonymous()) {
+				type.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
+				type.bits |= ASTNode.AnonymousAndLocalMask;
+			} else {
+				if (typeHandle.isLocal()) {
+					type.bits |= ASTNode.IsLocalTypeMASK;
+				}
+			}
+		}  else {
 			type.bits |= ASTNode.IsMemberTypeMASK;
 		}
-		type.name = sourceType.getName();
+		if ((type.bits & ASTNode.IsAnonymousTypeMASK) == 0) {
+			type.name = typeInfo.getName();
+		}
+		type.name = typeInfo.getName();
 		int start, end; // only positions available
-		type.sourceStart = start = sourceType.getNameSourceStart();
-		type.sourceEnd = end = sourceType.getNameSourceEnd();
-		type.modifiers = sourceType.getModifiers();
-		type.declarationSourceStart = sourceType.getDeclarationSourceStart();
-		type.declarationSourceEnd = sourceType.getDeclarationSourceEnd();
+		type.sourceStart = start = typeInfo.getNameSourceStart();
+		type.sourceEnd = end = typeInfo.getNameSourceEnd();
+		type.modifiers = typeInfo.getModifiers();
+		type.declarationSourceStart = typeInfo.getDeclarationSourceStart();
+		type.declarationSourceEnd = typeInfo.getDeclarationSourceEnd();
 		type.bodyEnd = type.declarationSourceEnd;
+		
+		/* convert annotations */
+		type.annotations = convertAnnotations(typeHandle);
 
+		/* convert type parameters */
+		char[][] typeParameterNames = typeInfo.getTypeParameterNames();
+		if (typeParameterNames.length > 0) {
+			int parameterCount = typeParameterNames.length;
+			char[][][] typeParameterBounds = typeInfo.getTypeParameterBounds();
+			type.typeParameters = new TypeParameter[parameterCount];
+			for (int i = 0; i < parameterCount; i++) {
+				type.typeParameters[i] = createTypeParameter(typeParameterNames[i], typeParameterBounds[i], start, end);
+			}
+		}
 		/* set superclass and superinterfaces */
-		if (sourceType.getSuperclassName() != null)
-			type.superclass =
-				createTypeReference(sourceType.getSuperclassName(), start, end);
-		char[][] interfaceNames = sourceType.getInterfaceNames();
+		if (typeInfo.getSuperclassName() != null) {
+			type.superclass = createTypeReference(typeInfo.getSuperclassName(), start, end);
+			type.superclass.bits |= ASTNode.IsSuperType;
+		}
+		char[][] interfaceNames = typeInfo.getInterfaceNames();
 		int interfaceCount = interfaceNames == null ? 0 : interfaceNames.length;
-		type.superInterfaces = new TypeReference[interfaceCount];
-		for (int i = 0; i < interfaceCount; i++) {
-			type.superInterfaces[i] = createTypeReference(interfaceNames[i], start, end);
+		if (interfaceCount > 0) {
+			type.superInterfaces = new TypeReference[interfaceCount];
+			for (int i = 0; i < interfaceCount; i++) {
+				type.superInterfaces[i] = createTypeReference(interfaceNames[i], start, end);
+				type.superInterfaces[i].bits |= ASTNode.IsSuperType;
+			}
 		}
 		/* convert member types */
 		if ((this.flags & MEMBER_TYPE) != 0) {
-			ISourceType[] sourceMemberTypes = sourceType.getMemberTypes();
-			int sourceMemberTypeCount =
-				sourceMemberTypes == null ? 0 : sourceMemberTypes.length;
+			SourceType[] sourceMemberTypes = typeInfo.getMemberTypeHandles();
+			int sourceMemberTypeCount = sourceMemberTypes.length;
 			type.memberTypes = new TypeDeclaration[sourceMemberTypeCount];
 			for (int i = 0; i < sourceMemberTypeCount; i++) {
 				type.memberTypes[i] = convert(sourceMemberTypes[i], compilationResult);
 			}
 		}
 
-		/* convert fields */
+		/* convert intializers and fields*/
+		InitializerElementInfo[] initializers = null;
+		int initializerCount = 0;
+		if ((this.flags & LOCAL_TYPE) != 0) {
+			initializers = typeInfo.getInitializers();
+			initializerCount = initializers.length;
+		}
+		SourceField[] sourceFields = null;
+		int sourceFieldCount = 0;
 		if ((this.flags & FIELD) != 0) {
-			ISourceField[] sourceFields = sourceType.getFields();
-			int sourceFieldCount = sourceFields == null ? 0 : sourceFields.length;
-			type.fields = new FieldDeclaration[sourceFieldCount];
-			for (int i = 0; i < sourceFieldCount; i++) {
-				type.fields[i] = convert(sourceFields[i], type);
+			sourceFields = typeInfo.getFieldHandles();
+			sourceFieldCount = sourceFields.length;
+		}
+		int length = initializerCount + sourceFieldCount;
+		if (length > 0) {
+			type.fields = new FieldDeclaration[length];
+			for (int i = 0; i < initializerCount; i++) {
+				type.fields[i] = convert(initializers[i], compilationResult);
+			}
+			int index = 0;
+			for (int i = initializerCount; i < length; i++) {
+				type.fields[i] = convert(sourceFields[index++], type, compilationResult);
 			}
 		}
 
@@ -272,15 +493,16 @@
 		boolean needMethod = (this.flags & METHOD) != 0;
 		if (needConstructor || needMethod) {
 			
-			ISourceMethod[] sourceMethods = sourceType.getMethods();
-			int sourceMethodCount = sourceMethods == null ? 0 : sourceMethods.length;
+			SourceMethod[] sourceMethods = typeInfo.getMethodHandles();
+			int sourceMethodCount = sourceMethods.length;
 	
 			/* source type has a constructor ?           */
 			/* by default, we assume that one is needed. */
 			int extraConstructor = 0;
 			int methodCount = 0;
-			boolean isInterface = type.isInterface();
-			if (!isInterface) {
+			int kind = type.kind();
+			boolean isAbstract = kind == IGenericType.INTERFACE_DECL || kind == IGenericType.ANNOTATION_TYPE_DECL;
+			if (!isAbstract) {
 				extraConstructor = needConstructor ? 1 : 0;
 				for (int i = 0; i < sourceMethodCount; i++) {
 					if (sourceMethods[i].isConstructor()) {
@@ -297,24 +519,47 @@
 			}
 			type.methods = new AbstractMethodDeclaration[methodCount + extraConstructor];
 			if (extraConstructor != 0) { // add default constructor in first position
-				type.methods[0] = type.createsInternalConstructor(false, false);
+				type.methods[0] = type.createDefaultConstructor(false, false);
 			}
 			int index = 0;
+			boolean hasAbstractMethods = false;
 			for (int i = 0; i < sourceMethodCount; i++) {
-				ISourceMethod sourceMethod = sourceMethods[i];
+				SourceMethod sourceMethod = sourceMethods[i];
 				boolean isConstructor = sourceMethod.isConstructor();
+				if ((sourceMethod.getFlags() & Flags.AccAbstract) != 0) {
+					hasAbstractMethods = true;
+				}
 				if ((isConstructor && needConstructor) || (!isConstructor && needMethod)) {
-					AbstractMethodDeclaration method =convert(sourceMethod, compilationResult);
-					if (isInterface || method.isAbstract()) { // fix-up flag 
+					AbstractMethodDeclaration method = convert(sourceMethod, compilationResult);
+					if (isAbstract || method.isAbstract()) { // fix-up flag 
 						method.modifiers |= AccSemicolonBody;
 					}
 					type.methods[extraConstructor + index++] = method;
 				}
 			}
+			if (hasAbstractMethods) type.bits |= ASTNode.HasAbstractMethods;
 		}
 		
 		return type;
 	}
+	
+	private Annotation[] convertAnnotations(JavaElement element) {
+		if (this.annotationPositions == null) return null;
+		char[] cuSource = getSource();
+		long[] positions = (long[]) this.annotationPositions.get(element);
+		if (positions == null) return null;
+		int length = positions.length;
+		Annotation[] annotations = new Annotation[length];
+		for (int i = 0; i < length; i++) {
+			long position = positions[i];
+			int start = (int) (position >>> 32);
+			int end = (int) position;
+			char[] annotationSource = CharOperation.subarray(cuSource, start, end+1);
+			Expression expression = parseMemberValue(annotationSource);
+			annotations[i] = (Annotation) expression;
+		}
+		return annotations;
+	}
 
 	/*
 	 * Build an import reference from an import name, e.g. java.lang.*
@@ -328,7 +573,7 @@
 	
 		char[][] qImportName = CharOperation.splitOn('.', importName);
 		long[] positions = new long[qImportName.length];
-		long position = (long) start << 32 + end;
+		long position = ((long) start << 32) + end;
 		for (int i = 0; i < qImportName.length; i++) {
 			positions[i] = position; // dummy positions
 		}
@@ -339,53 +584,225 @@
 			modifiers);
 	}
 
+	private TypeParameter createTypeParameter(char[] typeParameterName, char[][] typeParameterBounds, int start, int end) {
+
+		TypeParameter parameter = new TypeParameter();
+		parameter.name = typeParameterName;
+		parameter.sourceStart = start;
+		parameter.sourceEnd = end;
+		if (typeParameterBounds != null) {
+			int length = typeParameterBounds.length;
+			if (length > 0) {
+				parameter.type = createTypeReference(typeParameterBounds[0], start, end);
+				if (length > 1) {
+					parameter.bounds = new TypeReference[length-1];
+					for (int i = 1; i < length; i++) {
+						TypeReference bound = createTypeReference(typeParameterBounds[i], start, end);
+						bound.bits |= ASTNode.IsSuperType;
+						parameter.bounds[i-1] = bound;
+					}
+				}
+			}
+		}
+		return parameter;
+	}
+	
 	/*
 	 * Build a type reference from a readable name, e.g. java.lang.Object[][]
 	 */
 	private TypeReference createTypeReference(
-		char[] typeSignature,
+		char[] typeName,
 		int start,
 		int end) {
 
-		/* count identifiers and dimensions */
-		int max = typeSignature.length;
-		int dimStart = max;
-		int dim = 0;
+		int length = typeName.length;
+		this.namePos = 0;
+		TypeReference type = decodeType(typeName, length, start, end);
+		return type;
+	}
+	private TypeReference decodeType(char[] typeName, int length, int start, int end) {
 		int identCount = 1;
-		for (int i = 0; i < max; i++) {
-			switch (typeSignature[i]) {
+		int dim = 0;
+		int nameFragmentStart = this.namePos, nameFragmentEnd = -1;
+		ArrayList fragments = null;
+		typeLoop: while (this.namePos < length) {
+			char currentChar = typeName[this.namePos];
+			switch (currentChar) {
+				case '?' :
+					this.namePos++; // skip '?'
+					while (typeName[this.namePos] == ' ') this.namePos++;
+					switch(typeName[this.namePos]) {
+						case 's' :
+							checkSuper: {
+								int max = TypeConstants.WILDCARD_SUPER.length-1;
+								for (int ahead = 1; ahead < max; ahead++) {
+									if (typeName[this.namePos+ahead] != TypeConstants.WILDCARD_SUPER[ahead+1]) {
+										break checkSuper;
+									}
+								}
+								this.namePos += max;
+								Wildcard result = new Wildcard(Wildcard.SUPER);
+								result.bound = decodeType(typeName, length, start, end);
+								result.sourceStart = start;
+								result.sourceEnd = end;
+								return result;
+							}
+							break;
+						case 'e' :
+							checkExtends: {
+								int max = TypeConstants.WILDCARD_EXTENDS.length-1;
+								for (int ahead = 1; ahead < max; ahead++) {
+									if (typeName[this.namePos+ahead] != TypeConstants.WILDCARD_EXTENDS[ahead+1]) {
+										break checkExtends;
+									}
+								}
+								this.namePos += max;
+								Wildcard result = new Wildcard(Wildcard.EXTENDS);
+								result.bound = decodeType(typeName, length, start, end);
+								result.sourceStart = start;
+								result.sourceEnd = end;
+								return result;
+							}
+							break;
+					}
+					Wildcard result = new Wildcard(Wildcard.UNBOUND);
+					result.sourceStart = start;
+					result.sourceEnd = end;
+					return result;
 				case '[' :
-					if (dim == 0)
-						dimStart = i;
+					if (dim == 0) nameFragmentEnd = this.namePos-1;
 					dim++;
 					break;
-				case '.' :
-					identCount++;
+				case ']' :
 					break;
+				case '>' :
+				case ',' :
+					break typeLoop;
+				case '.' :
+					if (nameFragmentStart < 0) nameFragmentStart = this.namePos+1; // member type name
+					identCount ++;
+					break;
+				case '<' :
+					if (fragments == null) fragments = new ArrayList(2);
+					nameFragmentEnd = this.namePos-1;
+					char[][] identifiers = CharOperation.splitOn('.', typeName, nameFragmentStart, this.namePos);
+					fragments.add(identifiers);
+					this.namePos++; // skip '<'
+					TypeReference[] arguments = decodeTypeArguments(typeName, length, start, end); // positionned on '>' at end
+					fragments.add(arguments);
+					identCount = 0;
+					nameFragmentStart = -1;
+					nameFragmentEnd = -1;
+					// next increment will skip '>'
 			}
+			this.namePos++;
 		}
-		/* rebuild identifiers and dimensions */
-		if (identCount == 1) { // simple type reference
-			if (dim == 0) {
-				return new SingleTypeReference(typeSignature, (((long) start )<< 32) + end);
-			} else {
-				char[] identifier = new char[dimStart];
-				System.arraycopy(typeSignature, 0, identifier, 0, dimStart);
-				return new ArrayTypeReference(identifier, dim, (((long) start) << 32) + end);
+		if (nameFragmentEnd < 0) nameFragmentEnd = this.namePos-1;
+		if (fragments == null) { // non parameterized 
+			/* rebuild identifiers and dimensions */
+			if (identCount == 1) { // simple type reference
+				if (dim == 0) {
+					char[] nameFragment;
+					if (nameFragmentStart != 0 || nameFragmentEnd >= 0) {
+						int nameFragmentLength = nameFragmentEnd - nameFragmentStart + 1;
+						System.arraycopy(typeName, nameFragmentStart, nameFragment = new char[nameFragmentLength], 0, nameFragmentLength);						
+					} else {
+						nameFragment = typeName;
+					}
+					return new SingleTypeReference(nameFragment, ((long) start << 32) + end);
+				} else {
+					int nameFragmentLength = nameFragmentEnd - nameFragmentStart + 1;
+					char[] nameFragment = new char[nameFragmentLength];
+					System.arraycopy(typeName, nameFragmentStart, nameFragment, 0, nameFragmentLength);
+					return new ArrayTypeReference(nameFragment, dim, ((long) start << 32) + end);
+				}
+			} else { // qualified type reference
+				long[] positions = new long[identCount];
+				long pos = ((long) start << 32) + end;
+				for (int i = 0; i < identCount; i++) {
+					positions[i] = pos;
+				}
+				char[][] identifiers = CharOperation.splitOn('.', typeName, nameFragmentStart, nameFragmentEnd+1);
+				if (dim == 0) {
+					return new QualifiedTypeReference(identifiers, positions);
+				} else {
+					return new ArrayQualifiedTypeReference(identifiers, dim, positions);
+				}
 			}
-		} else { // qualified type reference
+		} else { // parameterized
+			// rebuild type reference from available fragments: char[][], arguments, char[][], arguments...
+			// check trailing qualified name
+			if (nameFragmentStart > 0 && nameFragmentStart < length) {
+				char[][] identifiers = CharOperation.splitOn('.', typeName, nameFragmentStart, nameFragmentEnd+1);
+				fragments.add(identifiers);
+			}
+			int fragmentLength = fragments.size();
+			if (fragmentLength == 2) {
+				char[][] firstFragment = (char[][]) fragments.get(0);
+				if (firstFragment.length == 1) {
+					// parameterized single type
+					return new ParameterizedSingleTypeReference(firstFragment[0], (TypeReference[]) fragments.get(1), dim, ((long) start << 32) + end);
+				}
+			}
+			// parameterized qualified type
+			identCount = 0;
+			for (int i = 0; i < fragmentLength; i ++) {
+				Object element = fragments.get(i);
+				if (element instanceof char[][]) {
+					identCount += ((char[][])element).length;
+				}
+			}
+			char[][] tokens = new char[identCount][];
+			TypeReference[][] arguments = new TypeReference[identCount][];
+			int index = 0;
+			for (int i = 0; i < fragmentLength; i ++) {
+				Object element = fragments.get(i);
+				if (element instanceof char[][]) {
+					char[][] fragmentTokens = (char[][]) element;
+					int fragmentTokenLength = fragmentTokens.length;
+					System.arraycopy(fragmentTokens, 0, tokens, index, fragmentTokenLength);
+					index += fragmentTokenLength;
+				} else {
+					arguments[index-1] = (TypeReference[]) element;
+				}
+			}
 			long[] positions = new long[identCount];
-			long pos = (((long) start) << 32) + end;
+			long pos = ((long) start << 32) + end;
 			for (int i = 0; i < identCount; i++) {
 				positions[i] = pos;
 			}
-			char[][] identifiers =
-				CharOperation.splitOn('.', typeSignature, 0, dimStart);
-			if (dim == 0) {
-				return new QualifiedTypeReference(identifiers, positions);
-			} else {
-				return new ArrayQualifiedTypeReference(identifiers, dim, positions);
-			}
+			return new ParameterizedQualifiedTypeReference(tokens, arguments, dim, positions);
 		}
 	}
+	
+	private TypeReference[] decodeTypeArguments(char[] typeName, int length, int start, int end) {
+		ArrayList argumentList = new ArrayList(1);
+		int count = 0;
+		argumentsLoop: while (this.namePos < length) {
+			TypeReference argument = decodeType(typeName, length, start, end);
+			count++;
+			argumentList.add(argument);
+			if (this.namePos >= length) break argumentsLoop;
+			if (typeName[this.namePos] == '>') {
+				break argumentsLoop;
+			}
+			this.namePos++; // skip ','
+		}
+		TypeReference[] typeArguments = new TypeReference[count];
+		argumentList.toArray(typeArguments);
+		return typeArguments;
+	}
+	
+	private char[] getSource() {
+		if (this.source == null)
+			this.source = this.cu.getContents();
+		return this.source;
+	}
+	
+	private Expression parseMemberValue(char[] memberValue) {
+		if (this.parser == null) {
+			this.parser = new Parser(this.problemReporter, true);
+		}
+		return this.parser.parseMemberValue(memberValue, 0, memberValue.length, this.unit);
+	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Assert.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Assert.java
index 0d8fef3..412438c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Assert.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Assert.java
@@ -91,6 +91,7 @@
 }
 
 	public static class AssertionFailedException extends RuntimeException {
+		private static final long serialVersionUID = -3179320974982211564L; // backward compatible
 		public AssertionFailedException(String detail) {
 			super(detail);
 		}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java
index 215025c..1238430 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java
@@ -108,6 +108,9 @@
 	}
 	return CharOperation.NO_CHAR;
 }
+/**
+ * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
+ */
 public char[] getFileName() {
 	return this.fileName;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMember.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMember.java
index 9b20412..e03384e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMember.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMember.java
@@ -21,7 +21,7 @@
 /**
  * Common functionality for Binary member handles.
  */
-public abstract class BinaryMember extends Member {
+public abstract class BinaryMember extends NamedMember {
 /*
  * Constructs a binary member.
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java
index 1c16666..9d7eac6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java
@@ -10,11 +10,13 @@
  *******************************************************************************/
 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.SourceElementRequestorAdapter;
 import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
 import org.eclipse.jdt.internal.core.util.Util;
@@ -28,39 +30,22 @@
 	class DecodeParametersNames extends SourceElementRequestorAdapter {
 			String[] parametersNames;
 		
-			public void enterMethod(
-				int declarationStart,
-				int modifiers,
-				char[] returnTypeName,
-				char[] selector,
-				int nameSourceStart,
-				int nameSourceEnd,
-				char[][] paramTypes,
-				char[][] paramNames,
-				char[][] exceptions) {
-					if (paramNames != null) {
-						int length = paramNames.length;
+			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(paramNames[i]);
+							this.parametersNames[i] = new String(methodInfo.parameterNames[i]);
 						}
 					}
 				}
 				
-			public void enterConstructor(
-				int declarationStart,
-				int modifiers,
-				char[] selector,
-				int nameSourceStart,
-				int nameSourceEnd,
-				char[][] paramTypes,
-				char[][] paramNames,
-				char[][] exceptions) {
-					if (paramNames != null) {
-						int length = paramNames.length;
+			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(paramNames[i]);
+							this.parametersNames[i] = new String(methodInfo.parameterNames[i]);
 						}
 					}
 				}
@@ -106,20 +91,27 @@
 public String[] getExceptionTypes() throws JavaModelException {
 	if (this.exceptionTypes == null) {
 		IBinaryMethod info = (IBinaryMethod) getElementInfo();
-		char[][] eTypeNames = info.getExceptionTypeNames();
-		if (eTypeNames == null || eTypeNames.length == 0) {
-			this.exceptionTypes = NO_TYPES;
-		} else {
-			eTypeNames = ClassFile.translatedNames(eTypeNames);
-			this.exceptionTypes = new String[eTypeNames.length];
-			for (int j = 0, length = eTypeNames.length; j < length; j++) {
-				// 1G01HRY: ITPJCORE:WINNT - method.getExceptionType not in correct format
-				int nameLength = eTypeNames[j].length;
-				char[] convertedName = new char[nameLength + 2];
-				System.arraycopy(eTypeNames[j], 0, convertedName, 1, nameLength);
-				convertedName[0] = 'L';
-				convertedName[nameLength + 1] = ';';
-				this.exceptionTypes[j] = new String(convertedName);
+		char[] genericSignature = info.getGenericSignature();
+		if (genericSignature != null) {
+			char[] dotBasedSignature = CharOperation.replaceOnCopy(genericSignature, '/', '.');
+			this.exceptionTypes = Signature.getThrownExceptionTypes(new String(dotBasedSignature));
+		}
+		if (this.exceptionTypes == null || this.exceptionTypes.length == 0) {
+			char[][] eTypeNames = info.getExceptionTypeNames();
+			if (eTypeNames == null || eTypeNames.length == 0) {
+				this.exceptionTypes = NO_TYPES;
+			} else {
+				eTypeNames = ClassFile.translatedNames(eTypeNames);
+				this.exceptionTypes = new String[eTypeNames.length];
+				for (int j = 0, length = eTypeNames.length; j < length; j++) {
+					// 1G01HRY: ITPJCORE:WINNT - method.getExceptionType not in correct format
+					int nameLength = eTypeNames[j].length;
+					char[] convertedName = new char[nameLength + 2];
+					System.arraycopy(eTypeNames[j], 0, convertedName, 1, nameLength);
+					convertedName[0] = 'L';
+					convertedName[nameLength + 1] = ';';
+					this.exceptionTypes[j] = new String(convertedName);
+				}
 			}
 		}
 	}
@@ -139,22 +131,21 @@
 	return info.getModifiers();
 }
 /*
- * @see JavaElement#getHandleMemento()
+ * @see JavaElement#getHandleMemento(StringBuffer)
  */
-public String getHandleMemento() {
-	StringBuffer buff = new StringBuffer(((JavaElement) getParent()).getHandleMemento());
+protected void getHandleMemento(StringBuffer buff) {
+	((JavaElement) getParent()).getHandleMemento(buff);
 	char delimiter = getHandleMementoDelimiter();
 	buff.append(delimiter);
 	escapeMementoName(buff, getElementName());
 	for (int i = 0; i < this.parameterTypes.length; i++) {
 		buff.append(delimiter);
-		buff.append(this.parameterTypes[i]);
+		escapeMementoName(buff, this.parameterTypes[i]);
 	}
 	if (this.occurrenceCount > 1) {
 		buff.append(JEM_COUNT);
 		buff.append(this.occurrenceCount);
 	}
-	return buff.toString();
 }
 /*
  * @see JavaElement#getHandleMemento()
@@ -217,26 +208,54 @@
 	return this.parameterTypes;
 }
 
+public ITypeParameter getTypeParameter(String typeParameterName) {
+	return new TypeParameter(this, typeParameterName);
+}
+
+public ITypeParameter[] getTypeParameters() throws JavaModelException {
+	String[] typeParameterSignatures = getTypeParameterSignatures();
+	int length = typeParameterSignatures.length;
+	if (length == 0) return TypeParameter.NO_TYPE_PARAMETERS;
+	ITypeParameter[] typeParameters = new ITypeParameter[length];
+	for (int i = 0; i < typeParameterSignatures.length; i++) {
+		String typeParameterName = Signature.getTypeVariable(typeParameterSignatures[i]);
+		typeParameters[i] = new TypeParameter(this, typeParameterName);
+	}
+	return typeParameters;
+}
+
 /**
  * @see IMethod#getTypeParameterSignatures()
  * @since 3.0
+ * @deprecated
  */
 public String[] getTypeParameterSignatures() throws JavaModelException {
-	// TODO (jerome) - missing implementation
-	return new String[0];
+	IBinaryMethod info = (IBinaryMethod) getElementInfo();
+	char[] genericSignature = info.getGenericSignature();
+	if (genericSignature == null) 
+		return CharOperation.NO_STRINGS;
+	char[] dotBasedSignature = CharOperation.replaceOnCopy(genericSignature, '/', '.');
+	char[][] typeParams = Signature.getTypeParameters(dotBasedSignature);
+	return CharOperation.toStrings(typeParams);
 }
 
 /*
  * @see IMethod
  */
 public String getReturnType() throws JavaModelException {
-	IBinaryMethod info = (IBinaryMethod) getElementInfo();
 	if (this.returnType == null) {
-		String returnTypeName= Signature.getReturnType(new String(info.getMethodDescriptor()));
-		this.returnType= new String(ClassFile.translatedName(returnTypeName.toCharArray()));
+		IBinaryMethod info = (IBinaryMethod) getElementInfo();
+		this.returnType = getReturnType(info);
 	}
 	return this.returnType;
 }
+private String getReturnType(IBinaryMethod info) {
+	char[] genericSignature = info.getGenericSignature();
+	char[] signature = genericSignature == null ? info.getMethodDescriptor() : genericSignature;
+	char[] dotBasedSignature = CharOperation.replaceOnCopy(signature, '/', '.');
+	String returnTypeName= Signature.getReturnType(new String(dotBasedSignature));
+	return new String(ClassFile.translatedName(returnTypeName.toCharArray()));
+}
 /*
  * @see IMethod
  */
@@ -273,7 +292,7 @@
  */
 public boolean isSimilar(IMethod method) {
 	return 
-		this.areSimilarMethods(
+		areSimilarMethods(
 			this.getElementName(), this.getParameterTypes(),
 			method.getElementName(), method.getParameterTypes(),
 			null);
@@ -300,37 +319,52 @@
  * @private Debugging purposes
  */
 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
-	buffer.append(this.tabString(tab));
+	buffer.append(tabString(tab));
 	if (info == null) {
 		toStringName(buffer);
 		buffer.append(" (not open)"); //$NON-NLS-1$
 	} else if (info == NO_INFO) {
 		toStringName(buffer);
 	} else {
-		try {
-			if (Flags.isStatic(this.getFlags())) {
-				buffer.append("static "); //$NON-NLS-1$
-			}
-			if (!this.isConstructor()) {
-				buffer.append(Signature.toString(this.getReturnType()));
-				buffer.append(' ');
-			}
-			toStringName(buffer);
-		} catch (JavaModelException e) {
-			buffer.append("<JavaModelException in toString of " + getElementName()); //$NON-NLS-1$
+		IBinaryMethod methodInfo = (IBinaryMethod) info;
+		int flags = methodInfo.getModifiers();
+		if (Flags.isStatic(flags)) {
+			buffer.append("static "); //$NON-NLS-1$
 		}
+		if (!methodInfo.isConstructor()) {
+			buffer.append(Signature.toString(getReturnType(methodInfo)));
+			buffer.append(' ');
+		}
+		toStringName(buffer, flags);
 	}
 }
 protected void toStringName(StringBuffer buffer) {
+	toStringName(buffer, 0);
+}
+protected void toStringName(StringBuffer buffer, int flags) {
 	buffer.append(getElementName());
 	buffer.append('(');
-	String[] parameters = this.getParameterTypes();
+	String[] parameters = getParameterTypes();
 	int length;
 	if (parameters != null && (length = parameters.length) > 0) {
+		boolean isVarargs = Flags.isVarargs(flags);
 		for (int i = 0; i < length; i++) {
-			buffer.append(Signature.toString(parameters[i]));
-			if (i < length - 1) {
-				buffer.append(", "); //$NON-NLS-1$
+			try {
+				if (i < length - 1) {
+					buffer.append(Signature.toString(parameters[i]));
+					buffer.append(", "); //$NON-NLS-1$
+				} else if (isVarargs) {
+					// remove array from signature
+					String parameter = parameters[i].substring(1);
+					buffer.append(Signature.toString(parameter));
+					buffer.append(" ..."); //$NON-NLS-1$
+				} else {
+					buffer.append(Signature.toString(parameters[i]));
+				}
+			} catch (IllegalArgumentException e) {
+				// parameter signature is malformed
+				buffer.append("*** invalid signature: "); //$NON-NLS-1$
+				buffer.append(parameters[i]);
 			}
 		}
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
index 6ec52aa..fc3dc29 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
@@ -20,6 +20,7 @@
 import org.eclipse.jdt.core.search.SearchEngine;
 import org.eclipse.jdt.internal.codeassist.CompletionEngine;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
 import org.eclipse.jdt.internal.core.util.MementoTokenizer;
@@ -51,25 +52,41 @@
 	cfi.removeBinaryChildren();
 }
 
+/**
+ * @see IType#codeComplete(char[], int, int, char[][], char[][], int[], boolean, ICompletionRequestor)
+ * @deprecated
+ */
+public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,ICompletionRequestor requestor) throws JavaModelException {
+	codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, requestor, DefaultWorkingCopyOwner.PRIMARY);
+}
+
+/**
+ * @see IType#codeComplete(char[], int, int, char[][], char[][], int[], boolean, ICompletionRequestor, WorkingCopyOwner)
+ * @deprecated
+ */
+public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,ICompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
+	if (requestor == null) {
+		throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$
+	}
+	codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, new org.eclipse.jdt.internal.codeassist.CompletionRequestorWrapper(requestor), owner);
+}
 /*
  * @see IType#codeComplete(char[], int, int, char[][], char[][], int[], boolean, ICompletionRequestor)
  */
-public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,ICompletionRequestor requestor) throws JavaModelException {
+public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,CompletionRequestor requestor) throws JavaModelException {
 	codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, requestor, DefaultWorkingCopyOwner.PRIMARY);
 }
 
 /*
  * @see IType#codeComplete(char[], int, int, char[][], char[][], int[], boolean, ICompletionRequestor, WorkingCopyOwner)
  */
-public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,ICompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
+public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,CompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
 	if (requestor == null) {
 		throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$
 	}
 	JavaProject project = (JavaProject) getJavaProject();
-	SearchableEnvironment environment = (SearchableEnvironment) project.newSearchableNameEnvironment(owner);
-	CompletionRequestorWrapper requestorWrapper = new CompletionRequestorWrapper(requestor, environment.nameLookup);
-	CompletionEngine engine = new CompletionEngine(environment, requestorWrapper, project.getOptions(true), project);
-	requestorWrapper.completionEngine = engine;
+	SearchableEnvironment environment = project.newSearchableNameEnvironment(owner);
+	CompletionEngine engine = new CompletionEngine(environment, requestor, project.getOptions(true), project);
 
 	String source = getClassFile().getSource();
 	if (source != null && insertion > -1 && insertion < source.length()) {
@@ -90,6 +107,8 @@
 	} else {
 		engine.complete(this, snippet, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic);
 	}
+	if (NameLookup.VERBOSE)
+		System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
 }
 
 /*
@@ -125,7 +144,7 @@
  */
 public IMethod[] findMethods(IMethod method) {
 	try {
-		return this.findMethods(method, this.getMethods());
+		return findMethods(method, getMethods());
 	} catch (JavaModelException e) {
 		// if type doesn't exist, no matching method can exist
 		return null;
@@ -211,7 +230,7 @@
 			return 
 				new BinaryType(
 					(JavaElement)this.getPackageFragment().getClassFile(enclosingClassFileName),
-					enclosingName.substring(enclosingName.lastIndexOf('$')+1));
+					Util.localTypeName(enclosingName, enclosingName.lastIndexOf('$'), enclosingName.length()));
 		}
 	}
 }
@@ -258,12 +277,21 @@
  * @see IType#getFullyQualifiedName(char enclosingTypeSeparator)
  */
 public String getFullyQualifiedName(char enclosingTypeSeparator) {
-	String packageName = getPackageFragment().getElementName();
-	if (packageName.equals(IPackageFragment.DEFAULT_PACKAGE_NAME)) {
-		return getTypeQualifiedName(enclosingTypeSeparator);
+	try {
+		return getFullyQualifiedName(enclosingTypeSeparator, false/*don't show parameters*/);
+	} catch (JavaModelException e) {
+		// exception thrown only when showing parameters
+		return null;
 	}
-	return packageName + '.' + getTypeQualifiedName(enclosingTypeSeparator);
 }
+
+/*
+ * @see IType#getFullyQualifiedParameterizedName()
+ */
+public String getFullyQualifiedParameterizedName() throws JavaModelException {
+	return getFullyQualifiedName('.', true/*show parameters*/);
+}
+
 /*
  * @see JavaElement
  */
@@ -272,26 +300,32 @@
 		case JEM_COUNT:
 			return getHandleUpdatingCountFromMemento(memento, workingCopyOwner);
 		case JEM_FIELD:
+			if (!memento.hasMoreTokens()) return this;
 			String fieldName = memento.nextToken();
 			JavaElement field = (JavaElement)getField(fieldName);
 			return field.getHandleFromMemento(memento, workingCopyOwner);
 		case JEM_INITIALIZER:
+			if (!memento.hasMoreTokens()) return this;
 			String count = memento.nextToken();
 			JavaElement initializer = (JavaElement)getInitializer(Integer.parseInt(count));
 			return initializer.getHandleFromMemento(memento, workingCopyOwner);
 		case JEM_METHOD:
+			if (!memento.hasMoreTokens()) return this;
 			String selector = memento.nextToken();
 			ArrayList params = new ArrayList();
 			nextParam: while (memento.hasMoreTokens()) {
 				token = memento.nextToken();
 				switch (token.charAt(0)) {
 					case JEM_TYPE:
+					case JEM_TYPE_PARAMETER:
 						break nextParam;
 					case JEM_METHOD:
+						if (!memento.hasMoreTokens()) return this;
 						String param = memento.nextToken();
 						StringBuffer buffer = new StringBuffer();
-						while (Signature.C_ARRAY == param.charAt(0)) {
+						while (param.length() == 1 && Signature.C_ARRAY == param.charAt(0)) { // backward compatible with 3.0 mementos
 							buffer.append(Signature.C_ARRAY);
+							if (!memento.hasMoreTokens()) return this;
 							param = memento.nextToken();
 						}
 						params.add(buffer.toString() + param);
@@ -306,6 +340,7 @@
 			if (token != null) {
 				switch (token.charAt(0)) {
 					case JEM_TYPE:
+					case JEM_TYPE_PARAMETER:
 					case JEM_LOCALVARIABLE:
 						return method.getHandleFromMemento(token, memento, workingCopyOwner);
 					default:
@@ -335,6 +370,11 @@
 			} else {
 				return type.getHandleFromMemento(token, memento, workingCopyOwner);
 			}
+		case JEM_TYPE_PARAMETER:
+			if (!memento.hasMoreTokens()) return this;
+			String typeParameterName = memento.nextToken();
+			JavaElement typeParameter = new TypeParameter(this, typeParameterName);
+			return typeParameter.getHandleFromMemento(memento, workingCopyOwner);
 	}
 	return null;
 }
@@ -448,13 +488,44 @@
 	return strings;
 }
 
+public ITypeParameter[] getTypeParameters() throws JavaModelException {
+	String[] typeParameterSignatures = getTypeParameterSignatures();
+	int length = typeParameterSignatures.length;
+	if (length == 0) return TypeParameter.NO_TYPE_PARAMETERS;
+	ITypeParameter[] typeParameters = new ITypeParameter[length];
+	for (int i = 0; i < typeParameterSignatures.length; i++) {
+		String typeParameterName = Signature.getTypeVariable(typeParameterSignatures[i]);
+		typeParameters[i] = new TypeParameter(this, typeParameterName);
+	}
+	return typeParameters;
+}
+
+// Get type parameter names
+// TODO (frederic) see if this method needs to be added to API
+public char[][] getTypeParameterNames() throws JavaModelException {
+	String[] typeParameterSignatures = getTypeParameterSignatures();
+	int length = typeParameterSignatures.length;
+	char[][] names = new char[length][];
+	for (int i = 0; i < length; i++) {
+		names[i] = Signature.getTypeVariable(typeParameterSignatures[i]).toCharArray();
+	}
+	return names;
+}
+
 /**
  * @see IType#getTypeParameterSignatures()
  * @since 3.0
+ * @deprecated
  */
 public String[] getTypeParameterSignatures() throws JavaModelException {
-	// TODO (jerome) - missing implementation
-	return new String[0];
+	IBinaryType info = (IBinaryType) getElementInfo();
+	char[] genericSignature = info.getGenericSignature();
+	if (genericSignature == null) 
+		return CharOperation.NO_STRINGS;
+	
+	char[] dotBaseSignature = CharOperation.replaceOnCopy(genericSignature, '/', '.');
+	char[][] typeParams = Signature.getTypeParameters(dotBaseSignature);
+	return CharOperation.toStrings(typeParams);
 }
 
 /*
@@ -464,6 +535,9 @@
 	IClassFile classFile= getPackageFragment().getClassFile(getTypeQualifiedName() + "$" + typeName + SUFFIX_STRING_class); //$NON-NLS-1$
 	return new BinaryType((JavaElement)classFile, typeName);
 }
+public ITypeParameter getTypeParameter(String typeParameterName) {
+	return new TypeParameter(this, typeParameterName);
+}
 /*
  * @see IType#getTypeQualifiedName()
  */
@@ -474,21 +548,11 @@
  * @see IType#getTypeQualifiedName(char)
  */
 public String getTypeQualifiedName(char enclosingTypeSeparator) {
-	IType declaringType = this.getDeclaringType();
-	if (declaringType == null) {
-		String classFileName = this.getClassFile().getElementName();
-		if (classFileName.indexOf('$') == -1) {
-			// top level class file: name of type is same as name of class file
-			return this.name;
-		} else {
-			// anonymous or local class file
-			return classFileName.substring(0, classFileName.lastIndexOf('.')); // remove .class
-		}
-	} else {
-		return 
-			declaringType.getTypeQualifiedName(enclosingTypeSeparator)
-			+ enclosingTypeSeparator
-			+ this.name;
+	try {
+		return getTypeQualifiedName(enclosingTypeSeparator, false/*don't show parameters*/);
+	} catch (JavaModelException e) {
+		// exception thrown only when showing parameters
+		return null;
 	}
 }
 /*
@@ -517,8 +581,9 @@
  * @see IType#isClass()
  */
 public boolean isClass() throws JavaModelException {
-	// TODO (jerome) - isClass should only return true for classes other than enum classes
-	return !isInterface();
+	IBinaryType info = (IBinaryType) getElementInfo();
+	return info.getKind() == IGenericType.CLASS_DECL;
+
 }
 
 /**
@@ -526,8 +591,8 @@
  * @since 3.0
  */
 public boolean isEnum() throws JavaModelException {
-	// TODO (jerome) - missing implementation - should only return true for enum classes
-	return false;
+	IBinaryType info = (IBinaryType) getElementInfo();
+	return info.getKind() == IGenericType.ENUM_DECL;
 }
 
 /*
@@ -535,8 +600,7 @@
  */
 public boolean isInterface() throws JavaModelException {
 	IBinaryType info = (IBinaryType) getElementInfo();
-	// TODO (jerome) - isInterface should not return true for annotation types
-	return info.isInterface();
+	return info.getKind() == IGenericType.INTERFACE_DECL;
 }
 
 /**
@@ -544,8 +608,8 @@
  * @since 3.0
  */
 public boolean isAnnotation() throws JavaModelException {
-	// TODO (jerome) - missing implementation - should only return true for annotation types
-	return false;
+	IBinaryType info = (IBinaryType) getElementInfo();
+	return info.getKind() == IGenericType.ANNOTATION_TYPE_DECL;
 }
 
 /*
@@ -736,6 +800,40 @@
 	return null;
 }
 /*
+ * Returns the source file name as defined in the given info.
+ * If not present in the info, infers it from this type.
+ */
+public String sourceFileName(IBinaryType info) {
+	char[] sourceFileName = info.sourceFileName();
+	if (sourceFileName == null) {
+		/*
+		 * We assume that this type has been compiled from a file with its name
+		 * For example, A.class comes from A.java and p.A.class comes from a file A.java
+		 * in the folder p.
+		 */
+		if (info.isMember()) {
+			IType enclosingType = getDeclaringType();
+			if (enclosingType == null) return null; // play it safe
+			while (enclosingType.getDeclaringType() != null) {
+				enclosingType = enclosingType.getDeclaringType();
+			}
+			return enclosingType.getElementName() + Util.defaultJavaExtension();
+		} else if (info.isLocal() || info.isAnonymous()){
+			String typeQualifiedName = getTypeQualifiedName();
+			int dollar = typeQualifiedName.indexOf('$');
+			if (dollar == -1) {
+				// malformed inner type: name doesn't contain a dollar
+				return getElementName() + Util.defaultJavaExtension();
+			}
+			return typeQualifiedName.substring(0, dollar) + Util.defaultJavaExtension();
+		} else {
+			return getElementName() + Util.defaultJavaExtension();
+		}
+	} else {
+		return  new String(sourceFileName);
+	}
+}
+/*
  * @private Debugging purposes
  */
 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
@@ -758,4 +856,10 @@
 		}
 	}
 }
+protected void toStringName(StringBuffer buffer) {
+	if (getElementName().length() > 0)
+		super.toStringName(buffer);
+	else
+		buffer.append("<anonymous>"); //$NON-NLS-1$
+}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeConverter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryTypeConverter.java
similarity index 80%
rename from org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeConverter.java
rename to org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryTypeConverter.java
index b6b2344..daa08c1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeConverter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryTypeConverter.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import org.eclipse.jdt.core.Flags;
 import org.eclipse.jdt.core.IField;
 import org.eclipse.jdt.core.IMethod;
 import org.eclipse.jdt.core.IType;
@@ -19,6 +20,7 @@
 import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Argument;
 import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
@@ -32,20 +34,22 @@
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
 import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
- * Converter from a type to an AST type declaration.
+ * Converter from a binary type to an AST type declaration.
  */
-public class TypeConverter {
+public class BinaryTypeConverter {
 	
 	/**
-	 * Convert a type into an AST type declaration and put it in the given compilation unit.
+	 * Convert a binary type into an AST type declaration and put it in the given compilation unit.
 	 */
 	public static TypeDeclaration buildTypeDeclaration(IType type, CompilationUnitDeclaration compilationUnit, CompilationResult compilationResult)  throws JavaModelException {
-		char[] packageName = type.getPackageFragment().getElementName().toCharArray();
+		PackageFragment pkg = (PackageFragment) type.getPackageFragment();
+		char[][] packageName = Util.toCharArrays(pkg.names);
 		
-		if (packageName != null && packageName.length > 0) { 
-			compilationUnit.currentPackage = new ImportReference(CharOperation.splitOn('.', packageName), new long[]{0}, false, CompilerModifiers.AccDefault);
+		if (packageName.length > 0) { 
+			compilationUnit.currentPackage = new ImportReference(packageName, new long[]{0}, false, CompilerModifiers.AccDefault);
 		}
 	
 		/* convert type */
@@ -72,7 +76,7 @@
 		FieldDeclaration fieldDeclaration = new FieldDeclaration();
 
 		fieldDeclaration.name = field.getElementName().toCharArray();
-		fieldDeclaration.type = createTypeReference(Signature.toString(field.getTypeSignature()).toCharArray(), type);
+		fieldDeclaration.type = createTypeReference(Signature.toString(field.getTypeSignature()).toCharArray());
 		fieldDeclaration.modifiers = field.getFlags();
 
 		return fieldDeclaration;
@@ -87,13 +91,15 @@
 			decl.isDefaultConstructor = false;
 			methodDeclaration = decl;
 		} else {
-			MethodDeclaration decl = new MethodDeclaration(compilationResult);
+			MethodDeclaration decl = type.isAnnotation() ? new AnnotationMethodDeclaration(compilationResult) : new MethodDeclaration(compilationResult);
 			/* convert return type */
-			decl.returnType = createTypeReference(Signature.toString(method.getReturnType()).toCharArray(), type);
+			decl.returnType = createTypeReference(Signature.toString(method.getReturnType()).toCharArray());
 			methodDeclaration = decl;
 		}
 		methodDeclaration.selector = method.getElementName().toCharArray();
-		methodDeclaration.modifiers = method.getFlags();
+		int flags = method.getFlags();
+		boolean isVarargs = Flags.isVarargs(flags);
+		methodDeclaration.modifiers = flags & ~Flags.AccVarargs;
 
 		/* convert arguments */
 		String[] argumentTypeNames = method.getParameterTypes();
@@ -101,10 +107,15 @@
 		int argumentCount = argumentTypeNames == null ? 0 : argumentTypeNames.length;
 		methodDeclaration.arguments = new Argument[argumentCount];
 		for (int i = 0; i < argumentCount; i++) {
+			String argumentTypeName = argumentTypeNames[i];
+			TypeReference typeReference = createTypeReference(Signature.toString(argumentTypeName).toCharArray());
+			if (isVarargs && i == argumentCount-1) {
+				typeReference.bits |= ASTNode.IsVarArgs;
+			}
 			methodDeclaration.arguments[i] = new Argument(
 				argumentNames[i].toCharArray(),
 				0,
-				createTypeReference(Signature.toString(argumentTypeNames[i]).toCharArray(), type),
+				typeReference,
 				CompilerModifiers.AccDefault);
 			// do not care whether was final or not
 		}
@@ -116,7 +127,7 @@
 			methodDeclaration.thrownExceptions = new TypeReference[exceptionCount];
 			for (int i = 0; i < exceptionCount; i++) {
 				methodDeclaration.thrownExceptions[i] =
-					createTypeReference(Signature.toString(exceptionTypeNames[i]).toCharArray(), type);
+					createTypeReference(Signature.toString(exceptionTypeNames[i]).toCharArray());
 			}
 		}
 		return methodDeclaration;
@@ -135,13 +146,15 @@
 
 		/* set superclass and superinterfaces */
 		if (type.getSuperclassName() != null) {
-			typeDeclaration.superclass = createTypeReference(type.getSuperclassName().toCharArray(), type);
+			typeDeclaration.superclass = createTypeReference(type.getSuperclassName().toCharArray());
+			typeDeclaration.superclass.bits |= ASTNode.IsSuperType;
 		}
 		String[] interfaceNames = type.getSuperInterfaceNames();
 		int interfaceCount = interfaceNames == null ? 0 : interfaceNames.length;
 		typeDeclaration.superInterfaces = new TypeReference[interfaceCount];
 		for (int i = 0; i < interfaceCount; i++) {
-			typeDeclaration.superInterfaces[i] = createTypeReference(interfaceNames[i].toCharArray(), type);
+			typeDeclaration.superInterfaces[i] = createTypeReference(interfaceNames[i].toCharArray());
+			typeDeclaration.superInterfaces[i].bits |= ASTNode.IsSuperType;
 		}
 		
 		/* convert member types */
@@ -179,31 +192,31 @@
 			}
 		}
 		boolean isInterface = type.isInterface();
+		boolean isAnnotation = type.isAnnotation();
 		neededCount = isInterface ? 0 : neededCount;
 		typeDeclaration.methods = new AbstractMethodDeclaration[methodCount + neededCount];
 		if (neededCount != 0) { // add default constructor in first position
-			typeDeclaration.methods[0] = typeDeclaration.createsInternalConstructor(false, false);
+			typeDeclaration.methods[0] = typeDeclaration.createDefaultConstructor(false, false);
 		}
+		boolean hasAbstractMethods = false;
 		for (int i = 0; i < methodCount; i++) {
 			AbstractMethodDeclaration method =convert(methods[i], type, compilationResult);
-			if (isInterface || method.isAbstract()) { // fix-up flag 
+			boolean isAbstract;
+			if ((isAbstract = method.isAbstract()) || isInterface || isAnnotation) { // fix-up flag 
 				method.modifiers |= CompilerModifiers.AccSemicolonBody;
 			}
+			if (isAbstract) {
+				hasAbstractMethods = true;
+			}
 			typeDeclaration.methods[neededCount + i] = method;
 		}
+		if (hasAbstractMethods) {
+			typeDeclaration.bits |= ASTNode.HasAbstractMethods;
+		}
 		return typeDeclaration;
 	}
 	
-	private static TypeReference createTypeReference(char[] type, IType contextType) {
-		try {
-			String[][] resolvedName = contextType.resolveType(new String(type));
-			if(resolvedName != null && resolvedName.length == 1) {
-				type= CharOperation.concat(resolvedName[0][0].toCharArray(), resolvedName[0][1].toCharArray(), '.');
-			}
-		} catch (JavaModelException e) {
-			// ignore
-		}
-		
+	private static TypeReference createTypeReference(char[] type) {
 		/* count identifiers and dimensions */
 		int max = type.length;
 		int dimStart = max;
@@ -233,9 +246,9 @@
 		} else { // qualified type reference
 			char[][] identifiers =	CharOperation.splitOn('.', type, 0, dimStart);
 			if (dim == 0) {
-				return new QualifiedTypeReference(identifiers, new long[]{0});
+				return new QualifiedTypeReference(identifiers, new long[identifiers.length]);
 			} else {
-				return new ArrayQualifiedTypeReference(identifiers, dim, new long[]{0});
+				return new ArrayQualifiedTypeReference(identifiers, dim, new long[identifiers.length]);
 			}
 		}
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Buffer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Buffer.java
index aeb8e49..7f60509 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Buffer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Buffer.java
@@ -54,7 +54,7 @@
 /**
  * @see IBuffer
  */
-public void addBufferChangedListener(IBufferChangedListener listener) {
+public synchronized void addBufferChangedListener(IBufferChangedListener listener) {
 	if (this.changeListeners == null) {
 		this.changeListeners = new ArrayList(5);
 	}
@@ -249,9 +249,10 @@
  * To avoid deadlock, this should not be called in a synchronized block.
  */
 protected void notifyChanged(final BufferChangedEvent event) {
-	if (this.changeListeners != null) {
-		for (int i = 0, size = this.changeListeners.size(); i < size; ++i) {
-			final IBufferChangedListener listener = (IBufferChangedListener) this.changeListeners.get(i);
+	ArrayList listeners = this.changeListeners;
+	if (listeners != null) {
+		for (int i = 0, size = listeners.size(); i < size; ++i) {
+			final IBufferChangedListener listener = (IBufferChangedListener) listeners.get(i);
 			Platform.run(new ISafeRunnable() {
 				public void handleException(Throwable exception) {
 					Util.log(exception, "Exception occurred in listener of buffer change notification"); //$NON-NLS-1$
@@ -267,7 +268,7 @@
 /**
  * @see IBuffer
  */
-public void removeBufferChangedListener(IBufferChangedListener listener) {
+public synchronized void removeBufferChangedListener(IBufferChangedListener listener) {
 	if (this.changeListeners != null) {
 		this.changeListeners.remove(listener);
 		if (this.changeListeners.size() == 0) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java
new file mode 100644
index 0000000..377371e
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.WorkingCopyOwner;
+import org.eclipse.jdt.internal.codeassist.ISearchRequestor;
+import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+
+
+public class CancelableNameEnvironment extends SearchableEnvironment {
+	public IProgressMonitor monitor;
+
+	public CancelableNameEnvironment(JavaProject project, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException {
+		super(project, owner);
+		this.monitor = monitor;
+	}
+
+	private void checkCanceled() {
+		if (this.monitor != null && this.monitor.isCanceled()) {
+			if (NameLookup.VERBOSE)
+				System.out.println(Thread.currentThread() + " CANCELLING LOOKUP "); //$NON-NLS-1$
+			throw new AbortCompilation(true/*silent*/, new OperationCanceledException());
+		}
+	}
+
+	public void findPackages(char[] prefix, ISearchRequestor requestor) {
+		checkCanceled();
+		super.findPackages(prefix, requestor);
+	}
+
+	public NameEnvironmentAnswer findType(char[] name, char[][] packageName) {
+		checkCanceled();
+		return super.findType(name, packageName);
+	}
+
+	public NameEnvironmentAnswer findType(char[][] compoundTypeName) {
+		checkCanceled();
+		return super.findType(compoundTypeName);
+	}
+
+	public void findTypes(char[] prefix, ISearchRequestor storage) {
+		checkCanceled();
+		super.findTypes(prefix, storage);
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableProblemFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableProblemFactory.java
new file mode 100644
index 0000000..a67e431
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableProblemFactory.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
+
+
+public class CancelableProblemFactory extends DefaultProblemFactory {
+	public IProgressMonitor monitor;
+
+	public CancelableProblemFactory(IProgressMonitor monitor) {
+		super();
+		this.monitor = monitor;
+	}
+
+	public IProblem createProblem(char[] originatingFileName, int problemId, String[] problemArguments, String[] messageArguments, int severity, int startPosition, int endPosition, int lineNumber) {
+		if (this.monitor != null && this.monitor.isCanceled()) 
+			throw new AbortCompilation(true/*silent*/, new OperationCanceledException());
+		return super.createProblem(originatingFileName, problemId, problemArguments, messageArguments, severity, startPosition, endPosition, lineNumber);
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
index c44f9ed..2fb4280 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
@@ -15,35 +15,34 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
+import org.eclipse.core.resources.*;
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IWorkspace;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.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.ICompletionRequestor;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaModelMarker;
 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.ISourceRange;
 import org.eclipse.jdt.core.IType;
-//import org.eclipse.jdt.core.JavaCore;
 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;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.IDependent;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.util.MementoTokenizer;
 import org.eclipse.jdt.internal.core.util.Util;
@@ -53,13 +52,16 @@
  */
 
 public class ClassFile extends Openable implements IClassFile, SuffixConstants {
+
+	protected String name;
 	protected BinaryType binaryType = null;
 	private boolean checkAutomaticSourceMapping;
 /*
  * Creates a handle to a class file.
  */
 protected ClassFile(PackageFragment parent, String name) {
-	super(parent, name);
+	super(parent);
+	this.name = name;
 	this.checkAutomaticSourceMapping = false;
 }
 
@@ -73,7 +75,8 @@
  */
 protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
 	// check whether the class file can be opened
-	if (!isValidClassFile()) throw newNotPresentException();
+	IStatus status = validateClassFile();
+	if (!status.isOK()) throw newJavaModelException(status);
 	if (underlyingResource != null && !underlyingResource.isAccessible()) throw newNotPresentException();
 
 	IBinaryType typeInfo = getBinaryTypeInfo((IFile) underlyingResource);
@@ -85,48 +88,51 @@
 	}
 
 	// Make the type
-	IType type = new BinaryType(this, new String(simpleName(typeInfo.getName())));
+	IType type = new BinaryType(this, simpleName(typeInfo.getName()));
 	info.addChild(type);
 	newElements.put(type, typeInfo);
 	return true;
 }
 /**
  * @see ICodeAssist#codeComplete(int, ICompletionRequestor)
+ * @deprecated
  */
 public void codeComplete(int offset, ICompletionRequestor requestor) throws JavaModelException {
 	codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY);
 }
 /**
  * @see ICodeAssist#codeComplete(int, ICompletionRequestor, WorkingCopyOwner)
+ * @deprecated
  */
 public void codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
-	String source = getSource();
-	if (source != null) {
-		String elementName = getElementName();
-		BasicCompilationUnit cu = 
-			new BasicCompilationUnit(
-				getSource().toCharArray(), 
-				null,
-				elementName.substring(0, elementName.length()-SUFFIX_STRING_class.length()) + SUFFIX_STRING_java,
-				getJavaProject()); // use project to retrieve corresponding .java IFile
-		codeComplete(cu, cu, offset, requestor, owner);
+	if (requestor == null) {
+		throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$
 	}
+	codeComplete(offset, new org.eclipse.jdt.internal.codeassist.CompletionRequestorWrapper(requestor), owner);
 }
 
 /* (non-Javadoc)
  * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor)
  */
 public void codeComplete(int offset, CompletionRequestor requestor) throws JavaModelException {
-	// TODO (jerome) - Missing implementation
-	throw new RuntimeException("Not implemented yet");  //$NON-NLS-1$
+	codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY);
 }
 
 /* (non-Javadoc)
  * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor, org.eclipse.jdt.core.WorkingCopyOwner)
  */
-public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner wcowner) throws JavaModelException {
-	// TODO (jerome) - Missing implementation
-	throw new RuntimeException("Not implemented yet");  //$NON-NLS-1$
+public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
+	String source = getSource();
+	if (source != null) {
+		BinaryType type = (BinaryType) getType();
+		BasicCompilationUnit cu = 
+			new BasicCompilationUnit(
+				getSource().toCharArray(), 
+				null,
+				type.sourceFileName((IBinaryType) type.getElementInfo()),
+				getJavaProject()); // use project to retrieve corresponding .java IFile
+		codeComplete(cu, cu, offset, requestor, owner);
+	}
 }
 
 /**
@@ -142,8 +148,8 @@
 	IBuffer buffer = getBuffer();
 	char[] contents;
 	if (buffer != null && (contents = buffer.getCharacters()) != null) {
-	    String topLevelTypeName = getTopLevelTypeName();
-		BasicCompilationUnit cu = new BasicCompilationUnit(contents, null, topLevelTypeName + SUFFIX_STRING_java);
+	    BinaryType type = (BinaryType) getType();
+		BasicCompilationUnit cu = new BasicCompilationUnit(contents, null, type.sourceFileName((IBinaryType) type.getElementInfo()));
 		return super.codeSelect(cu, offset, length, owner);
 	} else {
 		//has no associated souce
@@ -161,7 +167,7 @@
 	return super.equals(o);
 }
 public boolean exists() {
-	return super.exists() && isValidClassFile();
+	return super.exists() && validateClassFile().isOK();
 }
 
 /**
@@ -211,14 +217,14 @@
 			ZipFile zip = null;
 			try {
 				zip = root.getJar();
-				String entryName = getParent().getElementName();
-				entryName = entryName.replace('.', '/');
-				if (entryName.equals("")) { //$NON-NLS-1$
-					entryName += getElementName();
-				} else {
-					entryName += '/' + getElementName();
+				PackageFragment pkg = (PackageFragment) le;
+				String entryName = Util.concatWith(pkg.names, getElementName(), '/');
+				ZipEntry ze = zip.getEntry(entryName);
+				if (ze != null) {
+					byte contents[] = org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip);
+					String fileName = root.getHandleIdentifier() + IDependent.JAR_FILE_ENTRY_SEPARATOR + entryName;
+					info = new ClassFileReader(contents, fileName.toCharArray());
 				}
-				info = ClassFileReader.read(zip, entryName, true);
 			} finally {
 				JavaModelManager.getJavaModelManager().closeZipFile(zip);
 			}
@@ -244,7 +250,7 @@
 	} else {
 		byte[] contents = Util.getResourceContentsAsByteArray(file);
 		try {
-			return new ClassFileReader(contents, getElementName().toCharArray());
+			return new ClassFileReader(contents, file.getFullPath().toString().toCharArray());
 		} catch (ClassFormatException cfe) {
 			//the structure remains unknown
 			return null;
@@ -252,7 +258,7 @@
 	}
 }
 public IBuffer getBuffer() throws JavaModelException {
-	if (isValidClassFile()) {
+	if (validateClassFile().isOK()) {
 		return super.getBuffer();
 	} else {
 		// .class file not on classpath, create a new buffer to be nice (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=41444)
@@ -299,6 +305,64 @@
 		return findElement(type, position, mapper);
 	}
 }
+public IJavaElement getElementAtConsideringSibling(int position) throws JavaModelException {
+	IPackageFragment fragment = (IPackageFragment)getParent();
+	PackageFragmentRoot root = (PackageFragmentRoot) fragment.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+	SourceMapper mapper = root.getSourceMapper();
+	if (mapper == null) {
+		return null;
+	} else {		
+		String prefix = null;
+		int index = name.indexOf('$');
+		if (index > -1) {
+			prefix = name.substring(0, index);
+		} else {
+			prefix = name.substring(0, name.indexOf('.'));
+		}
+		
+		
+		IType type = null;
+		int start = -1;
+		int end = Integer.MAX_VALUE;
+		IJavaElement[] children = fragment.getChildren();
+		for (int i = 0; i < children.length; i++) {
+			String childName = children[i].getElementName();
+			
+			String childPrefix = null;
+			int childIndex = childName.indexOf('$');
+			if (childIndex > -1) {
+				childPrefix = childName.substring(0, childIndex);
+			} else {
+				childPrefix = childName.substring(0, childName.indexOf('.'));
+			}
+			
+			if(prefix.equals(childPrefix)) {
+				IClassFile classFile = (IClassFile) children[i];
+				
+				// ensure this class file's buffer is open so that source ranges are computed
+				classFile.getBuffer();
+				
+				SourceRange range = mapper.getSourceRange(classFile.getType());
+				if (range == SourceMapper.fgUnknownRange) continue; 
+				int newStart = range.offset;
+				int newEnd = newStart + range.length - 1;
+				if(newStart > start && newEnd < end
+						&& newStart <= position && newEnd >= position) {
+					type = classFile.getType();
+					start = newStart;
+					end = newEnd;
+				}
+			}
+		}
+		if(type != null) {
+			return findElement(type, position, mapper);
+		}
+		return null;
+	}
+}
+public String getElementName() {
+	return this.name;
+}
 /**
  * @see IJavaElement
  */
@@ -310,9 +374,8 @@
  */
 public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner owner) {
 	switch (token.charAt(0)) {
-		case JEM_COUNT:
-			return getHandleUpdatingCountFromMemento(memento, owner);
 		case JEM_TYPE:
+			if (!memento.hasMoreTokens()) return this;
 			String typeName = memento.nextToken();
 			JavaElement type = new BinaryType(this, typeName);
 			return type.getHandleFromMemento(memento, owner);
@@ -394,9 +457,7 @@
 		typeName = typeName.substring(typeName.lastIndexOf('.') + 1);
 		int index = typeName.lastIndexOf('$');
 		if (index > -1) {
-			if (typeName.length() > (index + 1) && !Character.isDigit(typeName.charAt(index + 1))) {
-				typeName = typeName.substring(index + 1);
-			}
+			typeName = Util.localTypeName(typeName, index, typeName.length());
 		}
 		this.binaryType = new BinaryType(this, typeName);
 	}
@@ -457,15 +518,15 @@
 public boolean isReadOnly() {
 	return true;
 }
-private boolean isValidClassFile() {
+private IStatus validateClassFile() {
 	IPackageFragmentRoot root = getPackageFragmentRoot();
 	try {
-		if (root.getKind() != IPackageFragmentRoot.K_BINARY) return false;
+		if (root.getKind() != IPackageFragmentRoot.K_BINARY) 
+			return new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, root);
 	} catch (JavaModelException e) {
-		return false;
+		return e.getJavaModelStatus();
 	}
-	if (!Util.isValidClassFileName(getElementName())) return false;
-	return true;
+	return JavaConventions.validateClassFileName(getElementName());
 }
 /**
  * Opens and returns buffer on the source code associated with this class file.
@@ -489,26 +550,29 @@
 		if (root.isArchive()) {
 			// root is a jar file or a zip file
 			String elementName = getElementName();
-			StringBuffer sourceFileName = new StringBuffer(elementName.substring(0, elementName.lastIndexOf('.')));
-			sourceFileName.append(SuffixConstants.SUFFIX_java);
+			String sourceFileWithoutExtension = elementName.substring(0, elementName.lastIndexOf('.'));
 			JarPackageFragmentRoot jarPackageFragmentRoot = (JarPackageFragmentRoot) root;
 			ZipFile jar = null;
 			try {
 				jar = jarPackageFragmentRoot.getJar();
-				IPackageFragment packageFragment = (IPackageFragment) getParent();
-				ZipEntry zipEntry = null;
-				if (packageFragment.isDefaultPackage()) {
-					zipEntry = jar.getEntry(sourceFileName.toString());
-				} else {
-					zipEntry = jar.getEntry(getParent().getElementName() + '/' + sourceFileName.toString());
-				}
-				if (zipEntry != null) {
-					// found a source file
-					this.checkAutomaticSourceMapping = true;
-					root.attachSource(root.getPath(), null, null);
-					SourceMapper sourceMapper = getSourceMapper();
-					if (sourceMapper != null) {
-						return mapSource(sourceMapper);
+				String[] pkgName = ((PackageFragment) getParent()).names;
+				for (int i = 0, length = Util.JAVA_LIKE_EXTENSIONS.length; i < length; i++) {
+					StringBuffer entryName = new StringBuffer();
+					for (int j = 0, pkgNameLength = pkgName.length; j < pkgNameLength; j++) {
+						entryName.append(pkgName[j]);
+						entryName.append('/');
+					}
+					entryName.append(sourceFileWithoutExtension);
+					entryName.append(Util.JAVA_LIKE_EXTENSIONS[i]);
+					ZipEntry zipEntry = jar.getEntry(entryName.toString());
+					if (zipEntry != null) {
+						// found a source file
+						this.checkAutomaticSourceMapping = true;
+						root.attachSource(root.getPath(), null, null);
+						SourceMapper sourceMapper = getSourceMapper();
+						if (sourceMapper != null) {
+							return mapSource(sourceMapper);
+						}
 					}
 				}
 			} catch (CoreException e) {
@@ -526,16 +590,26 @@
 				return cu.getBuffer();
 			} else	{
 				// root is a class folder
-				IPath sourceFilePath = getPath().removeFileExtension().addFileExtension(EXTENSION_java);
-				IWorkspace workspace = ResourcesPlugin.getWorkspace();
-				if (workspace == null) {
-					this.checkAutomaticSourceMapping = true; // we don't want to check again
-					return null; // workaround for http://bugs.eclipse.org/bugs/show_bug.cgi?id=34069
+				
+				IFolder pkgFolder = (IFolder) getParent().getResource();
+				IResource[] files = null;
+				try {
+					files = pkgFolder.members();
+				} catch (CoreException e) {
+					throw new JavaModelException(e);
 				}
-				if (JavaModel.getTarget(
-						workspace.getRoot(),
-						sourceFilePath.makeRelative(), // ensure path is relative (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
-						true) != null) {
+				IResource sourceFile = null;
+				String classFileName = getElementName();
+				String simpleName = classFileName.substring(0, classFileName.lastIndexOf('.'));
+				for (int i = 0, length = files.length; i < length; i++) {
+					IResource resource = files[i];
+					if (resource.getType() == IResource.FILE 
+							&& Util.equalsIgnoreJavaLikeExtension(resource.getName(), simpleName)) {
+						sourceFile = resource;
+						break;
+					}
+				}
+				if (sourceFile != null) {
 							
 					// found a source file
 					 // we don't need to check again. The source will be attached.
@@ -575,24 +649,15 @@
 	}
 	return null;
 }
-/* package */ static char[] simpleName(char[] className) {
+/* package */ static String simpleName(char[] className) {
 	if (className == null)
 		return null;
-	className = unqualifiedName(className);
-	int count = 0;
-	int lastPosition = className.length - 1;
-	for (int i = lastPosition; i > -1; i--) {
-		if (className[i] == '$' && (i != lastPosition)) {
-			char[] name = new char[count];
-			System.arraycopy(className, i + 1, name, 0, count);
-			if (Character.isDigit(name[0])) {
-				break;
-			}
-			return name;
-		}
-		count++;
-	}
-	return className;
+	String simpleName = new String(unqualifiedName(className));
+	int lastDollar = simpleName.lastIndexOf('$');
+	if (lastDollar != -1) 
+		return Util.localTypeName(simpleName, lastDollar, simpleName.length());
+	else
+		return simpleName;
 }
 /**
  * Returns the Java Model representation of the given name
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java
index 33458c5..769511b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java
@@ -14,14 +14,15 @@
 import java.util.HashMap;
 
 import org.eclipse.core.resources.IFile;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IClassFile;
 import org.eclipse.jdt.core.IField;
 import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IMethod;
 import org.eclipse.jdt.core.IPackageFragment;
 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.env.IBinaryField;
 import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
 import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
@@ -43,6 +44,10 @@
 	 * <code>BinaryType.getChildren()</code>. 
 	 */
 	protected JavaElement[] binaryChildren = null;
+	/*
+	 * The type parameters in this class file.
+	 */
+	protected ITypeParameter[] typeParameters;
 	/**
 	 * Back-pointer to the IClassFile to allow lazy initialization.
 	 */
@@ -84,7 +89,7 @@
 		for (int i = 0, typeCount = innerTypes.length; i < typeCount; i++) {
 			IBinaryNestedType binaryType = innerTypes[i];
 			IClassFile parentClassFile= ((IPackageFragment)this.classFile.getParent()).getClassFile(new String(ClassFile.unqualifiedName(binaryType.getName())) + SUFFIX_STRING_class);
-			IType innerType = new BinaryType((JavaElement)parentClassFile, new String(ClassFile.simpleName(binaryType.getName())));
+			IType innerType = new BinaryType((JavaElement)parentClassFile, ClassFile.simpleName(binaryType.getName()));
 			childrenHandles.add(innerType);
 		}
 	}
@@ -93,7 +98,7 @@
  * Creates the handles and infos for the methods of the given binary type.
  * Adds new handles to the given vector.
  */
-private void generateMethodInfos(IType type, IBinaryType typeInfo, HashMap newElements, ArrayList childrenHandles) {
+private void generateMethodInfos(IType type, IBinaryType typeInfo, HashMap newElements, ArrayList childrenHandles, ArrayList typeParameterHandles) {
 	IBinaryMethod[] methods = typeInfo.getMethods();
 	if (methods == null) {
 		return;
@@ -103,7 +108,16 @@
 		// TODO (jerome) filter out synthetic members
 		//                        indexer should not index them as well
 		// if ((methodInfo.getModifiers() & IConstants.AccSynthetic) != 0) continue; // skip synthetic
-		String[] pNames= Signature.getParameterTypes(new String(methodInfo.getMethodDescriptor()));
+		char[] signature = methodInfo.getGenericSignature();
+		if (signature == null) signature = methodInfo.getMethodDescriptor();
+		String[] pNames = null;
+		try {
+			pNames = Signature.getParameterTypes(new String(signature));
+		} catch (IllegalArgumentException e) {
+			// protect against malformed .class file (e.g. com/sun/crypto/provider/SunJCE_b.class has a 'a' generic signature)
+			signature = methodInfo.getMethodDescriptor();
+			pNames = Signature.getParameterTypes(new String(signature));
+		}
 		char[][] paramNames= new char[pNames.length][];
 		for (int j= 0; j < pNames.length; j++) {
 			paramNames[j]= pNames[j].toCharArray();
@@ -116,9 +130,47 @@
 		for (int j= 0; j < pNames.length; j++) {
 			pNames[j]= new String(parameterTypes[j]);
 		}
-		IMethod method = new BinaryMethod((JavaElement)type, selector, pNames);
+		BinaryMethod method = new BinaryMethod((JavaElement)type, selector, pNames);
 		childrenHandles.add(method);
+		
+		// ensure that 2 binary methods with the same signature but with different return types have different occurence counts.
+		// (case of bridge methods in 1.5)
+		while (newElements.containsKey(method))
+			method.occurrenceCount++;
+		
 		newElements.put(method, methodInfo);
+		
+		generateTypeParameterInfos(method, signature, newElements, typeParameterHandles);
+	}
+}
+/**
+ * Creates the handles and infos for the type parameter of the given binary member.
+ * Adds new handles to the given vector.
+ */
+private void generateTypeParameterInfos(BinaryMember parent, char[] signature, HashMap newElements, ArrayList typeParameterHandles) {
+	if (signature == null) return;
+	char[][] typeParameterSignatures = Signature.getTypeParameters(signature);
+	for (int i = 0, typeParameterCount = typeParameterSignatures.length; i < typeParameterCount; i++) {
+		char[] typeParameterSignature = typeParameterSignatures[i];
+		char[] typeParameterName = Signature.getTypeVariable(typeParameterSignature);
+		char[][] typeParameterBoundSignatures = Signature.getTypeParameterBounds(typeParameterSignature);
+		int boundLength = typeParameterBoundSignatures.length;
+		char[][] typeParameterBounds = new char[boundLength][];
+		for (int j = 0; j < boundLength; j++) {
+			typeParameterBounds[j] = Signature.toCharArray(typeParameterBoundSignatures[j]);
+			CharOperation.replace(typeParameterBounds[j], '/', '.');
+		}
+		TypeParameter typeParameter = new TypeParameter(parent, new String(typeParameterName));
+		TypeParameterElementInfo info = new TypeParameterElementInfo();
+		info.bounds = typeParameterBounds;
+		typeParameterHandles.add(typeParameter);
+		
+		// ensure that 2 binary methods with the same signature but with different return types have different occurence counts.
+		// (case of bridge methods in 1.5)
+		while (newElements.containsKey(typeParameter))
+			typeParameter.occurrenceCount++;
+		
+		newElements.put(typeParameter, info);	
 	}
 }
 /**
@@ -158,14 +210,23 @@
 	} catch (JavaModelException npe) {
 		return;
 	}
+	ArrayList typeParameterHandles = new ArrayList();
 	if (typeInfo != null) { //may not be a valid class file
+		generateTypeParameterInfos(type, typeInfo.getGenericSignature(), newElements, typeParameterHandles);
 		generateFieldInfos(type, typeInfo, newElements, childrenHandles);
-		generateMethodInfos(type, typeInfo, newElements, childrenHandles);
+		generateMethodInfos(type, typeInfo, newElements, childrenHandles, typeParameterHandles);
 		generateInnerClassHandles(type, typeInfo, childrenHandles); // Note inner class are separate openables that are not opened here: no need to pass in newElements
 	}
 	
 	this.binaryChildren = new JavaElement[childrenHandles.size()];
 	childrenHandles.toArray(this.binaryChildren);
+	int typeParameterHandleSize = typeParameterHandles.size();
+	if (typeParameterHandleSize == 0) {
+		this.typeParameters = TypeParameter.NO_TYPE_PARAMETERS;
+	} else {
+		this.typeParameters = new ITypeParameter[typeParameterHandleSize];
+		typeParameterHandles.toArray(this.typeParameters);
+	}
 }
 /**
  * Removes the binary children handles and remove their infos from
@@ -184,5 +245,13 @@
 		}
 		this.binaryChildren = JavaElement.NO_ELEMENTS;
 	}
+	if (this.typeParameters != null) {
+		JavaModelManager manager = JavaModelManager.getJavaModelManager();
+		for (int i = 0; i <this.typeParameters.length; i++) {
+			TypeParameter typeParameter = (TypeParameter) this.typeParameters[i];
+			manager.removeInfoAndChildren(typeParameter);
+		}
+		this.typeParameters = TypeParameter.NO_TYPE_PARAMETERS;
+	}
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java
index 9676fae..8118d00 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java
@@ -18,7 +18,6 @@
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IBuffer;
 import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.ICompletionRequestor;
 import org.eclipse.jdt.core.IImportContainer;
 import org.eclipse.jdt.core.IImportDeclaration;
 import org.eclipse.jdt.core.IJavaElement;
@@ -591,6 +590,7 @@
 
 	/**
 	 * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, ICompletionRequestor)
+	 * @deprecated
 	 */
 	public void codeComplete(int offset, ICompletionRequestor requestor)
 		throws JavaModelException {
@@ -599,6 +599,7 @@
 
 	/**
 	 * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, ICompletionRequestor, WorkingCopyOwner)
+	 * @deprecated
 	 */
 	public void codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner owner)
 		throws JavaModelException {
@@ -634,16 +635,14 @@
 	 * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor)
 	 */
 	public void codeComplete(int offset, CompletionRequestor requestor) throws JavaModelException {
-		// TODO (jerome) - Missing implementation
-		throw new RuntimeException("Not implemented yet");  //$NON-NLS-1$
+		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
 	}
 
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor, org.eclipse.jdt.core.WorkingCopyOwner)
 	 */
 	public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner wcowner) throws JavaModelException {
-		// TODO (jerome) - Missing implementation
-		throw new RuntimeException("Not implemented yet");  //$NON-NLS-1$
+		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
index 41ef429..548cc0d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
@@ -13,6 +13,7 @@
 import java.io.File;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
@@ -30,6 +31,7 @@
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.core.util.Util;
 import org.w3c.dom.Element;
@@ -39,6 +41,17 @@
  */
 public class ClasspathEntry implements IClasspathEntry {
 
+	public static final String TAG_CLASSPATH = "classpath"; //$NON-NLS-1$
+	public static final String TAG_CLASSPATHENTRY = "classpathentry"; //$NON-NLS-1$
+	public static final String TAG_OUTPUT = "output"; //$NON-NLS-1$
+	public static final String TAG_KIND = "kind"; //$NON-NLS-1$
+	public static final String TAG_PATH = "path"; //$NON-NLS-1$
+	public static final String TAG_SOURCEPATH = "sourcepath"; //$NON-NLS-1$
+	public static final String TAG_ROOTPATH = "rootpath"; //$NON-NLS-1$
+	public static final String TAG_EXPORTED = "exported"; //$NON-NLS-1$
+	public static final String TAG_INCLUDING = "including"; //$NON-NLS-1$
+	public static final String TAG_EXCLUDING = "excluding"; //$NON-NLS-1$
+	
 	/**
 	 * Describes the kind of classpath entry - one of 
 	 * CPE_PROJECT, CPE_LIBRARY, CPE_SOURCE, CPE_VARIABLE or CPE_CONTAINER
@@ -77,13 +90,15 @@
 	/**
 	 * Patterns allowing to include/exclude portions of the resource tree denoted by this entry path.
 	 */
-	public IPath[] inclusionPatterns;
-	private char[][] fullCharInclusionPatterns;
-	public IPath[] exclusionPatterns;
-	private char[][] fullCharExclusionPatterns;
+	private IPath[] inclusionPatterns;
+	private char[][] fullInclusionPatternChars;
+	private IPath[] exclusionPatterns;
+	private char[][] fullExclusionPatternChars;
 	private final static char[][] UNINIT_PATTERNS = new char[][] { "Non-initialized yet".toCharArray() }; //$NON-NLS-1$
-
+	
 	private String rootID;
+	private AccessRestriction importRestriction;
+	private final static AccessRestriction UNINIT_RESTRICTION = new AccessRestriction(null, null, null, null);
 	
 	/*
 	 * Default inclusion pattern set
@@ -150,16 +165,15 @@
 		this.entryKind = entryKind;
 		this.path = path;
 		this.inclusionPatterns = inclusionPatterns;
-	    if (inclusionPatterns != INCLUDE_ALL && inclusionPatterns.length > 0) {
-			this.fullCharInclusionPatterns = UNINIT_PATTERNS;
-	    } else {
-			this.fullCharInclusionPatterns = null; // empty inclusion pattern means everything is included
-	    }
 		this.exclusionPatterns = exclusionPatterns;
+		
+	    if (inclusionPatterns != INCLUDE_ALL && inclusionPatterns.length > 0) {
+			this.fullInclusionPatternChars = UNINIT_PATTERNS;
+			this.importRestriction = UNINIT_RESTRICTION;
+	    }
 	    if (exclusionPatterns.length > 0) {
-			this.fullCharExclusionPatterns = UNINIT_PATTERNS;
-	    } else {
-			this.fullCharExclusionPatterns = null; // empty exclusion pattern means nothing is excluded
+			this.fullExclusionPatternChars = UNINIT_PATTERNS;
+			this.importRestriction = UNINIT_RESTRICTION;
 	    }
 		this.sourceAttachmentPath = sourceAttachmentPath;
 		this.sourceAttachmentRootPath = sourceAttachmentRootPath;
@@ -167,21 +181,72 @@
 		this.isExported = isExported;
 	}
 	
+	/**
+	 * Used to perform export/restriction propagation across referring projects/containers
+	 */
+	public ClasspathEntry combineWith(IClasspathEntry referringEntry) {
+		if (referringEntry == null) return this;
+		if (referringEntry.isExported() 
+				|| referringEntry.getInclusionPatterns().length > 0 
+				|| referringEntry.getExclusionPatterns().length > 0) {
+			return new ClasspathEntry(
+								this.getContentKind(), this.getEntryKind(), this.getPath(),
+								ClasspathEntry.concatPatterns(referringEntry.getInclusionPatterns(), this.getInclusionPatterns()), 
+								ClasspathEntry.concatPatterns(referringEntry.getExclusionPatterns(), this.getExclusionPatterns()), 
+								this.getSourceAttachmentPath(), this.getSourceAttachmentRootPath(), this.getOutputLocation(), 
+								referringEntry.isExported()|| this.isExported); // duplicate container entry for tagging it as exported
+		}
+		// no need to clone
+		return this;
+	}
+
+	/**
+	 * Concatenate two pattern lists
+	 */
+	public static IPath[] concatPatterns(IPath[] patternList1, IPath[] patternList2) {
+		int length1 = patternList1.length;
+		if (length1 == 0) return patternList2;
+		int length2 = patternList2.length;
+		if (length2 == 0) return patternList1;
+		IPath[] result = new IPath[length1+length2];
+		System.arraycopy(patternList1, 0, result, 0, length1);
+		System.arraycopy(patternList2, 0, result, length1, length2);
+		return result;
+	}
+	
+	/**
+	 * Decode some element tag containing a sequence of patterns into IPath[]
+	 */
+	private static IPath[] decodePatterns(Element element, String tag) {
+		String sequence = element.getAttribute(tag);
+		if (!sequence.equals("")) { //$NON-NLS-1$ 
+			char[][] patterns = CharOperation.splitOn('|', sequence.toCharArray());
+			int patternCount;
+			if ((patternCount  = patterns.length) > 0) {
+				IPath[] paths = new IPath[patternCount];
+				for (int j = 0; j < patterns.length; j++){
+					paths[j] = new Path(new String(patterns[j]));
+				}
+				return paths;
+			}
+		}
+		return null;
+	}
 	/*
 	 * Returns a char based representation of the exclusions patterns full path.
 	 */
 	public char[][] fullExclusionPatternChars() {
 
-		if (this.fullCharExclusionPatterns == UNINIT_PATTERNS) {
+		if (this.fullExclusionPatternChars == UNINIT_PATTERNS) {
 			int length = this.exclusionPatterns.length;
-			this.fullCharExclusionPatterns = new char[length][];
+			this.fullExclusionPatternChars = new char[length][];
 			IPath prefixPath = this.path.removeTrailingSeparator();
 			for (int i = 0; i < length; i++) {
-				this.fullCharExclusionPatterns[i] = 
+				this.fullExclusionPatternChars[i] = 
 					prefixPath.append(this.exclusionPatterns[i]).toString().toCharArray();
 			}
 		}
-		return this.fullCharExclusionPatterns;
+		return this.fullExclusionPatternChars;
 	}
 	
 	/*
@@ -189,16 +254,16 @@
 	 */
 	public char[][] fullInclusionPatternChars() {
 
-		if (this.fullCharInclusionPatterns == UNINIT_PATTERNS) {
+		if (this.fullInclusionPatternChars == UNINIT_PATTERNS) {
 			int length = this.inclusionPatterns.length;
-			this.fullCharInclusionPatterns = new char[length][];
+			this.fullInclusionPatternChars = new char[length][];
 			IPath prefixPath = this.path.removeTrailingSeparator();
 			for (int i = 0; i < length; i++) {
-				this.fullCharInclusionPatterns[i] = 
+				this.fullInclusionPatternChars[i] = 
 					prefixPath.append(this.inclusionPatterns[i]).toString().toCharArray();
 			}
 		}
-		return this.fullCharInclusionPatterns;
+		return this.fullInclusionPatternChars;
 	}
 
 	/**
@@ -207,7 +272,7 @@
 	public void elementEncode(XMLWriter writer, IPath projectPath, boolean indent, boolean newLine) {
 		HashMap parameters = new HashMap();
 		
-		parameters.put("kind", ClasspathEntry.kindToString(this.entryKind));//$NON-NLS-1$
+		parameters.put(TAG_KIND, ClasspathEntry.kindToString(this.entryKind));
 		
 		IPath xmlPath = this.path;
 		if (this.entryKind != IClasspathEntry.CPE_VARIABLE && this.entryKind != IClasspathEntry.CPE_CONTAINER) {
@@ -223,7 +288,7 @@
 				}
 			}
 		}
-		parameters.put("path", String.valueOf(xmlPath));//$NON-NLS-1$
+		parameters.put(TAG_PATH, String.valueOf(xmlPath));
 		
 		if (this.sourceAttachmentPath != null) {
 			xmlPath = this.sourceAttachmentPath;
@@ -234,45 +299,31 @@
 					xmlPath = xmlPath.makeRelative();
 				}
 			}
-			parameters.put("sourcepath", String.valueOf(xmlPath));//$NON-NLS-1$
+			parameters.put(TAG_SOURCEPATH, String.valueOf(xmlPath));
 		}
 		if (this.sourceAttachmentRootPath != null) {
-			parameters.put("rootpath", String.valueOf(this.sourceAttachmentRootPath));//$NON-NLS-1$
+			parameters.put(TAG_ROOTPATH, String.valueOf(this.sourceAttachmentRootPath));
 		}
 		if (this.isExported) {
-			parameters.put("exported", "true");//$NON-NLS-1$//$NON-NLS-2$
+			parameters.put(TAG_EXPORTED, "true");//$NON-NLS-1$
 		}
-		if (this.inclusionPatterns != null && this.inclusionPatterns.length > 0) {
-			StringBuffer includeRule = new StringBuffer(10);
-			for (int i = 0, max = this.inclusionPatterns.length; i < max; i++){
-				if (i > 0) includeRule.append('|');
-				includeRule.append(this.inclusionPatterns[i]);
-			}
-			parameters.put("including", String.valueOf(includeRule));//$NON-NLS-1$
-		}
-		if (this.exclusionPatterns != null && this.exclusionPatterns.length > 0) {
-			StringBuffer excludeRule = new StringBuffer(10);
-			for (int i = 0, max = this.exclusionPatterns.length; i < max; i++){
-				if (i > 0) excludeRule.append('|');
-				excludeRule.append(this.exclusionPatterns[i]);
-			}
-			parameters.put("excluding", String.valueOf(excludeRule));//$NON-NLS-1$
-		}
+		encodePatterns(this.inclusionPatterns, TAG_INCLUDING, parameters);
+		encodePatterns(this.exclusionPatterns, TAG_EXCLUDING, parameters);
 		
 		if (this.specificOutputLocation != null) {
 			IPath outputLocation = this.specificOutputLocation.removeFirstSegments(1);
 			outputLocation = outputLocation.makeRelative();
-			parameters.put("output", String.valueOf(outputLocation));//$NON-NLS-1$
+			parameters.put(TAG_OUTPUT, String.valueOf(outputLocation));
 		}
 
-		writer.printTag("classpathentry", parameters, indent, newLine, true);//$NON-NLS-1$
+		writer.printTag(TAG_CLASSPATHENTRY, parameters, indent, newLine, true);
 	}
 	
 	public static IClasspathEntry elementDecode(Element element, IJavaProject project) {
 	
 		IPath projectPath = project.getProject().getFullPath();
-		String kindAttr = element.getAttribute("kind"); //$NON-NLS-1$
-		String pathAttr = element.getAttribute("path"); //$NON-NLS-1$
+		String kindAttr = element.getAttribute(TAG_KIND);
+		String pathAttr = element.getAttribute(TAG_PATH);
 
 		// ensure path is absolute
 		IPath path = new Path(pathAttr); 		
@@ -282,62 +333,48 @@
 		}
 		// source attachment info (optional)
 		IPath sourceAttachmentPath = 
-			element.hasAttribute("sourcepath")	//$NON-NLS-1$
-			? new Path(element.getAttribute("sourcepath")) //$NON-NLS-1$
+			element.hasAttribute(TAG_SOURCEPATH)	
+			? new Path(element.getAttribute(TAG_SOURCEPATH))
 			: null;
 		if (kind != IClasspathEntry.CPE_VARIABLE && sourceAttachmentPath != null && !sourceAttachmentPath.isAbsolute()) {
 			sourceAttachmentPath = projectPath.append(sourceAttachmentPath);
 		}
 		IPath sourceAttachmentRootPath = 
-			element.hasAttribute("rootpath") //$NON-NLS-1$
-			? new Path(element.getAttribute("rootpath")) //$NON-NLS-1$
+			element.hasAttribute(TAG_ROOTPATH)
+			? new Path(element.getAttribute(TAG_ROOTPATH))
 			: null;
 		
 		// exported flag (optional)
-		boolean isExported = element.getAttribute("exported").equals("true"); //$NON-NLS-1$ //$NON-NLS-2$
+		boolean isExported = element.getAttribute(TAG_EXPORTED).equals("true"); //$NON-NLS-1$
 
 		// inclusion patterns (optional)
-		String inclusion = element.getAttribute("including"); //$NON-NLS-1$ 
-		IPath[] inclusionPatterns = INCLUDE_ALL;
-		if (!inclusion.equals("")) { //$NON-NLS-1$ 
-			char[][] patterns = CharOperation.splitOn('|', inclusion.toCharArray());
-			int patternCount;
-			if ((patternCount  = patterns.length) > 0) {
-				inclusionPatterns = new IPath[patternCount];
-				for (int j = 0; j < patterns.length; j++){
-					inclusionPatterns[j] = new Path(new String(patterns[j]));
-				}
-			}
-		}
-
+		IPath[] inclusionPatterns = decodePatterns(element, TAG_INCLUDING);
+		if (inclusionPatterns == null) inclusionPatterns = INCLUDE_ALL;
+		
 		// exclusion patterns (optional)
-		String exclusion = element.getAttribute("excluding"); //$NON-NLS-1$ 
-		IPath[] exclusionPatterns = EXCLUDE_NONE;
-		if (!exclusion.equals("")) { //$NON-NLS-1$ 
-			char[][] patterns = CharOperation.splitOn('|', exclusion.toCharArray());
-			int patternCount;
-			if ((patternCount  = patterns.length) > 0) {
-				exclusionPatterns = new IPath[patternCount];
-				for (int j = 0; j < patterns.length; j++){
-					exclusionPatterns[j] = new Path(new String(patterns[j]));
-				}
-			}
-		}
-
+		IPath[] exclusionPatterns = decodePatterns(element, TAG_EXCLUDING);
+		if (exclusionPatterns == null) exclusionPatterns = EXCLUDE_NONE;
+		
 		// custom output location
-		IPath outputLocation = element.hasAttribute("output") ? projectPath.append(element.getAttribute("output")) : null; //$NON-NLS-1$ //$NON-NLS-2$
+		IPath outputLocation = element.hasAttribute(TAG_OUTPUT) ? projectPath.append(element.getAttribute(TAG_OUTPUT)) : null;
 		
 		// recreate the CP entry
 		switch (kind) {
 
 			case IClasspathEntry.CPE_PROJECT :
-				return JavaCore.newProjectEntry(path, isExported);
+				return JavaCore.newProjectEntry(
+												path, 
+												inclusionPatterns,
+												exclusionPatterns,
+												isExported);
 				
 			case IClasspathEntry.CPE_LIBRARY :
 				return JavaCore.newLibraryEntry(
 												path,
 												sourceAttachmentPath,
 												sourceAttachmentRootPath,
+												inclusionPatterns,
+												exclusionPatterns,
 												isExported);
 				
 			case IClasspathEntry.CPE_SOURCE :
@@ -345,8 +382,18 @@
 				String projSegment = path.segment(0);
 				if (projSegment != null && projSegment.equals(project.getElementName())) { // this project
 					return JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation);
-				} else { // another project
-					return JavaCore.newProjectEntry(path, isExported);
+				} else { 
+					if (path.segmentCount() == 1) {
+						// another project
+						return JavaCore.newProjectEntry(
+												path, 
+												inclusionPatterns,
+												exclusionPatterns,
+												isExported);
+					} else {
+						// an invalid source folder
+						return JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation);
+					}
 				}
 
 			case IClasspathEntry.CPE_VARIABLE :
@@ -354,11 +401,15 @@
 						path,
 						sourceAttachmentPath,
 						sourceAttachmentRootPath, 
+						inclusionPatterns,
+						exclusionPatterns,
 						isExported);
 				
 			case IClasspathEntry.CPE_CONTAINER :
 				return JavaCore.newContainerEntry(
 						path,
+						inclusionPatterns,
+						exclusionPatterns,
 						isExported);
 
 			case ClasspathEntry.K_OUTPUT :
@@ -367,8 +418,8 @@
 						ClasspathEntry.K_OUTPUT,
 						IClasspathEntry.CPE_LIBRARY,
 						path,
-						ClasspathEntry.INCLUDE_ALL, 
-						ClasspathEntry.EXCLUDE_NONE, 
+						INCLUDE_ALL, 
+						EXCLUDE_NONE, 
 						null, // source attachment
 						null, // source attachment root
 						null, // custom output location
@@ -379,6 +430,20 @@
 	}
 
 	/**
+	 * Encode some patterns into XML parameter tag
+	 */
+	private static void encodePatterns(IPath[] patterns, String tag, Map parameters) {
+		if (patterns != null && patterns.length > 0) {
+			StringBuffer rule = new StringBuffer(10);
+			for (int i = 0, max = patterns.length; i < max; i++){
+				if (i > 0) rule.append('|');
+				rule.append(patterns[i]);
+			}
+			parameters.put(tag, String.valueOf(rule));
+		}
+	}
+
+	/**
 	 * Returns true if the given object is a classpath entry
 	 * with equivalent attributes.
 	 */
@@ -418,34 +483,10 @@
 					return false;
 			}
 
-			IPath[] otherIncludes = otherEntry.getInclusionPatterns();
-			if (this.inclusionPatterns != otherIncludes){
-			    if (this.inclusionPatterns == null) return false;
-				int includeLength = this.inclusionPatterns.length;
-				if (otherIncludes == null || otherIncludes.length != includeLength) 
-					return false;
-				for (int i = 0; i < includeLength; i++) {
-					// compare toStrings instead of IPaths 
-					// since IPath.equals is specified to ignore trailing separators
-					if (!this.inclusionPatterns[i].toString().equals(otherIncludes[i].toString()))
-						return false;
-				}
-			}
-
-			IPath[] otherExcludes = otherEntry.getExclusionPatterns();
-			if (this.exclusionPatterns != otherExcludes){
-			    if (this.exclusionPatterns == null) return false;
-				int excludeLength = this.exclusionPatterns.length;
-				if (otherExcludes == null || otherExcludes.length != excludeLength) 
-					return false;
-				for (int i = 0; i < excludeLength; i++) {
-					// compare toStrings instead of IPaths 
-					// since IPath.equals is specified to ignore trailing separators
-					if (!this.exclusionPatterns[i].toString().equals(otherExcludes[i].toString()))
-						return false;
-				}
-			}
-			
+			if (!equalPatterns(this.inclusionPatterns, otherEntry.getInclusionPatterns()))
+				return false;
+			if (!equalPatterns(this.exclusionPatterns, otherEntry.getExclusionPatterns()))
+				return false;
 			otherPath = otherEntry.getOutputLocation();
 			if (this.specificOutputLocation == null) {
 				if (otherPath != null)
@@ -460,6 +501,22 @@
 		}
 	}
 
+	private static boolean equalPatterns(IPath[] firstPatterns, IPath[] secondPatterns) {
+		if (firstPatterns != secondPatterns){
+		    if (firstPatterns == null) return false;
+			int length = firstPatterns.length;
+			if (secondPatterns == null || secondPatterns.length != length) 
+				return false;
+			for (int i = 0; i < length; i++) {
+				// compare toStrings instead of IPaths 
+				// since IPath.equals is specified to ignore trailing separators
+				if (!firstPatterns[i].toString().equals(secondPatterns[i].toString()))
+					return false;
+			}
+		}
+		return true;
+	}
+	
 	/**
 	 * @see IClasspathEntry
 	 */
@@ -489,6 +546,40 @@
 	}
 
 	/**
+	 * Defines access restriction rules for project import
+	 */	
+	public AccessRestriction getImportRestriction() {
+		
+		if (this.importRestriction == UNINIT_RESTRICTION) {
+			char[][] importIncludes = getAccessRestrictionPatterns(this.inclusionPatterns);
+			char[][] importExcludes = getAccessRestrictionPatterns(this.exclusionPatterns);
+			if (importIncludes == null && importExcludes == null) {
+				this.importRestriction = null;
+			} else {
+				this.importRestriction = new AccessRestriction(
+									(this.entryKind == CPE_PROJECT || this.entryKind == CPE_SOURCE) // can be remote source entry when reconciling
+										? org.eclipse.jdt.internal.core.util.Util.bind("restrictedAccess.project", null, getPath().segment(0)) //$NON-NLS-1$
+										: org.eclipse.jdt.internal.core.util.Util.bind("restrictedAccess.library", null, getPath().makeRelative().toOSString()), //$NON-NLS-1$
+									importIncludes, 
+									importExcludes,
+									null /* no further restriction */);
+			}
+		}
+		return this.importRestriction;
+	}
+	
+	public static char[][] getAccessRestrictionPatterns(IPath[] patternSequence) {
+		if (patternSequence == null) return null;
+		int length = patternSequence.length;
+		if (length == 0) return null;
+		char[][] patternChars = new char[length][];
+		for (int i = 0; i < length; i++) {
+			patternChars[i] = patternSequence[i].toString().toCharArray();
+		}
+		return patternChars;
+	}		
+
+	/**
 	 * @see IClasspathEntry#getOutputLocation()
 	 */
 	public IPath getOutputLocation() {
@@ -772,15 +863,15 @@
 		
 		for (int i = 0 ; i < length; i++) {
 			IClasspathEntry resolvedEntry = classpath[i];
+			if (disableExclusionPatterns &&
+			        ((resolvedEntry.getInclusionPatterns() != null && resolvedEntry.getInclusionPatterns().length > 0) 
+			        || (resolvedEntry.getExclusionPatterns() != null && resolvedEntry.getExclusionPatterns().length > 0))) {
+				return new JavaModelStatus(IJavaModelStatusConstants.DISABLED_CP_EXCLUSION_PATTERNS, javaProject, resolvedEntry.getPath());
+			}
 			switch(resolvedEntry.getEntryKind()){
 				case IClasspathEntry.CPE_SOURCE :
 					sourceEntryCount++;
 
-					if (disableExclusionPatterns &&
-					        ((resolvedEntry.getInclusionPatterns() != null && resolvedEntry.getInclusionPatterns().length > 0) 
-					        || (resolvedEntry.getExclusionPatterns() != null && resolvedEntry.getExclusionPatterns().length > 0))) {
-						return new JavaModelStatus(IJavaModelStatusConstants.DISABLED_CP_EXCLUSION_PATTERNS, javaProject, resolvedEntry.getPath());
-					}
 					IPath customOutput; 
 					if ((customOutput = resolvedEntry.getOutputLocation()) != null) {
 
@@ -863,7 +954,7 @@
 			int kind = entry.getEntryKind();
 			
 			// Build some common strings for status message
-			boolean isProjectRelative = entryPath.segment(0).toString().equals(projectName);
+			boolean isProjectRelative = projectName.equals(entryPath.segment(0));
 			String entryPathMsg = isProjectRelative ? entryPath.removeFirstSegments(1).toString() : entryPath.makeRelative().toString();
 	
 			// complain if duplicate path
@@ -946,7 +1037,7 @@
 			int kind = entry.getEntryKind();
 
 			// Build some common strings for status message
-			boolean isProjectRelative = entryPath.segment(0).toString().equals(projectName);
+			boolean isProjectRelative = projectName.equals(entryPath.segment(0));
 			String entryPathMsg = isProjectRelative ? entryPath.removeFirstSegments(1).toString() : entryPath.makeRelative().toString();
 	
 			if (kind == IClasspathEntry.CPE_SOURCE) {
@@ -958,7 +1049,7 @@
 					if (otherEntry == entry) continue;
 
 					// Build some common strings for status message
-					boolean opStartsWithProject = otherEntry.getPath().segment(0).toString().equals(projectName);
+					boolean opStartsWithProject = projectName.equals(otherEntry.getPath().segment(0));
 					String otherPathMsg = opStartsWithProject ? otherEntry.getPath().removeFirstSegments(1).toString() : otherEntry.getPath().makeRelative().toString();
 	
 					switch (otherEntry.getEntryKind()) {
@@ -996,8 +1087,8 @@
 	
 		// Build some common strings for status message
 		String projectName = project.getElementName();
-		boolean pathStartsWithProject = path.segment(0).toString().equals(projectName);
-		String entryPathMsg = pathStartsWithProject ? path.removeFirstSegments(1).toString() : path.makeRelative().toString();
+		boolean pathStartsWithProject = projectName.equals(path.segment(0));
+		String entryPathMsg = pathStartsWithProject ? path.removeFirstSegments(1).makeRelative().toString() : path.toString();
 	
 		switch(entry.getEntryKind()){
 	
@@ -1057,7 +1148,7 @@
 					}
 					return validateClasspathEntry(project, entry, checkSourceAttachment, recurseInContainers);
 				} else {
-					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalVariablePath", path.makeRelative().toString(), projectName));					 //$NON-NLS-1$
+					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalVariablePath", entryPathMsg, projectName));					 //$NON-NLS-1$
 				}
 	
 			// library entry check
@@ -1081,7 +1172,7 @@
 										&& sourceAttachment != null
 										&& !sourceAttachment.isEmpty()
 										&& JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){
-										return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundSourceAttachment", new String [] {sourceAttachment.makeRelative().toString(), path.makeRelative().toString(), projectName})); //$NON-NLS-1$
+										return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundSourceAttachment", new String [] {sourceAttachment.toString(), path.toString(), projectName})); //$NON-NLS-1$
 									}
 								} else {
 									return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalLibraryArchive", entryPathMsg, projectName)); //$NON-NLS-1$
@@ -1092,7 +1183,7 @@
 									&& sourceAttachment != null 
 									&& !sourceAttachment.isEmpty()
 									&& JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){
-									return  new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundSourceAttachment", new String [] {sourceAttachment.makeRelative().toString(), path.makeRelative().toString(), projectName})); //$NON-NLS-1$
+									return  new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundSourceAttachment", new String [] {sourceAttachment.toString(), path.toString(), projectName})); //$NON-NLS-1$
 								}
 						}
 					} else if (target instanceof File){
@@ -1105,13 +1196,18 @@
 								&& sourceAttachment != null 
 								&& !sourceAttachment.isEmpty()
 								&& JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){
-								return  new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundSourceAttachment", new String [] {sourceAttachment.toString(), path.makeRelative().toString(), projectName})); //$NON-NLS-1$
+								return  new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundSourceAttachment", new String [] {sourceAttachment.toString(), path.toOSString(), projectName})); //$NON-NLS-1$
 					    }
 					} else {
-						return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundLibrary", path.makeRelative().toString(), projectName)); //$NON-NLS-1$
+						boolean isExternal = path.getDevice() != null || !workspaceRoot.getProject(path.segment(0)).exists();
+						if (isExternal) {
+							return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundLibrary", path.toOSString(), projectName)); //$NON-NLS-1$
+						} else {
+							return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundLibrary", entryPathMsg, projectName)); //$NON-NLS-1$
+						}
 					}
 				} else {
-					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalLibraryPath", path.makeRelative().toString(), projectName)); //$NON-NLS-1$
+					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalLibraryPath", entryPathMsg, projectName)); //$NON-NLS-1$
 				}
 				break;
 	
@@ -1122,10 +1218,10 @@
 					IJavaProject prereqProject = JavaCore.create(prereqProjectRsc);
 					try {
 						if (!prereqProjectRsc.exists() || !prereqProjectRsc.hasNature(JavaCore.NATURE_ID)){
-							return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundProject", path.makeRelative().segment(0).toString(), projectName)); //$NON-NLS-1$
+							return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundProject", path.segment(0), projectName)); //$NON-NLS-1$
 						}
 						if (!prereqProjectRsc.isOpen()){
-							return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.closedProject", path.segment(0).toString())); //$NON-NLS-1$
+							return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.closedProject", path.segment(0))); //$NON-NLS-1$
 						}
 						if (project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true) != JavaCore.IGNORE) {
 							long projectTargetJDK = CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true));
@@ -1135,10 +1231,10 @@
 							}
 						}
 					} catch (CoreException e){
-						return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundProject", path.segment(0).toString(), projectName)); //$NON-NLS-1$
+						return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundProject", path.segment(0), projectName)); //$NON-NLS-1$
 					}
 				} else {
-					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalProjectPath", path.segment(0).toString(), projectName)); //$NON-NLS-1$
+					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalProjectPath", path.segment(0), projectName)); //$NON-NLS-1$
 				}
 				break;
 	
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CommitWorkingCopyOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CommitWorkingCopyOperation.java
index 2d98c3a..b15ad33 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CommitWorkingCopyOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CommitWorkingCopyOperation.java
@@ -75,7 +75,7 @@
 			JavaElementDeltaBuilder deltaBuilder = null;
 			PackageFragmentRoot root = (PackageFragmentRoot)workingCopy.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
 			boolean isIncluded = !Util.isExcluded(workingCopy);
-			if (isPrimary || (root.isOnClasspath() && isIncluded && resource.isAccessible() && Util.isValidCompilationUnitName(workingCopy.getElementName()))) {
+			if (isPrimary || (root.validateOnClasspath().isOK() && isIncluded && resource.isAccessible() && Util.isValidCompilationUnitName(workingCopy.getElementName()))) {
 				
 				// force opening so that the delta builder can get the old info
 				if (!isPrimary && !primary.isOpen()) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java
index 1e13c5e..b3c8c02 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java
@@ -34,17 +34,16 @@
  */
 public class CompilationUnit extends Openable implements ICompilationUnit, org.eclipse.jdt.internal.compiler.env.ICompilationUnit, SuffixConstants {
 	
+	protected String name;
 	public WorkingCopyOwner owner;
 
 /**
  * Constructs a handle to a compilation unit with the given name in the
  * specified package for the specified owner
- *
- * @exception IllegalArgumentException if the name of the compilation unit
- * does not end with ".java"
  */
 protected CompilationUnit(PackageFragment parent, String name, WorkingCopyOwner owner) {
-	super(parent, name);
+	super(parent);
+	this.name = name;
 	this.owner = owner;
 }
 /**
@@ -82,11 +81,8 @@
 
 	// check if this compilation unit can be opened
 	if (!isWorkingCopy()) { // no check is done on root kind or exclusion pattern for working copies
-		if (((IPackageFragment)getParent()).getKind() == IPackageFragmentRoot.K_BINARY
-				|| !isValidCompilationUnit()
-				|| !underlyingResource.isAccessible()) {
-			throw newNotPresentException();
-		}
+		IStatus status = validateCompilationUnit(underlyingResource);
+		if (!status.isOK()) throw newJavaModelException(status);
 	}
 	
 	// prevents reopening of non-primary working copies (they are closed when they are discarded and should not be reopened)
@@ -143,13 +139,13 @@
 	try {
 		if (computeProblems){
 			perWorkingCopyInfo.beginReporting();
-			compilationUnitDeclaration = CompilationUnitProblemFinder.process(unit, this, contents, parser, this.owner, perWorkingCopyInfo, problemFactory, false/*don't cleanup cu*/, pm);
+			compilationUnitDeclaration = CompilationUnitProblemFinder.process(unit, this, contents, parser, this.owner, perWorkingCopyInfo, false/*don't cleanup cu*/, pm);
 			perWorkingCopyInfo.endReporting();
 		}
 		
 		if (info instanceof ASTHolderCUInfo) {
 			int astLevel = ((ASTHolderCUInfo) info).astLevel;
-			org.eclipse.jdt.core.dom.CompilationUnit cu = AST.convertCompilationUnit(astLevel, unit, contents, options, computeProblems, pm);
+			org.eclipse.jdt.core.dom.CompilationUnit cu = AST.convertCompilationUnit(astLevel, unit, contents, options, computeProblems, this.owner, pm);
 			((ASTHolderCUInfo) info).ast = cu;
 		}
 	} finally {
@@ -190,15 +186,20 @@
 }
 /**
  * @see ICodeAssist#codeComplete(int, ICompletionRequestor)
+ * @deprecated
  */
 public void codeComplete(int offset, ICompletionRequestor requestor) throws JavaModelException {
 	codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY);
 }
 /**
  * @see ICodeAssist#codeComplete(int, ICompletionRequestor, WorkingCopyOwner)
+ * @deprecated
  */
 public void codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner workingCopyOwner) throws JavaModelException {
-	codeComplete(this, isWorkingCopy() ? (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) getOriginalElement() : this, offset, requestor, workingCopyOwner);
+	if (requestor == null) {
+		throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$
+	}
+	codeComplete(offset, new org.eclipse.jdt.internal.codeassist.CompletionRequestorWrapper(requestor), workingCopyOwner);
 }
 /**
  * @see ICodeAssist#codeComplete(int, ICodeCompletionRequestor)
@@ -276,16 +277,14 @@
  * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor)
  */
 public void codeComplete(int offset, CompletionRequestor requestor) throws JavaModelException {
-	// TODO (jerome) - Missing implementation
-	throw new RuntimeException("Not implemented yet");  //$NON-NLS-1$
+	codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY);
 }
 
 /* (non-Javadoc)
  * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor, org.eclipse.jdt.core.WorkingCopyOwner)
  */
-public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner wcowner) throws JavaModelException {
-	// TODO (jerome) - Missing implementation
-	throw new RuntimeException("Not implemented yet");  //$NON-NLS-1$
+public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner workingCopyOwner) throws JavaModelException {
+	codeComplete(this, isWorkingCopy() ? (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) getOriginalElement() : this, offset, requestor, workingCopyOwner);
 }
 
 /**
@@ -373,7 +372,7 @@
 		//autogenerate this compilation unit
 		IPackageFragment pkg = (IPackageFragment) getParent();
 		String source = ""; //$NON-NLS-1$
-		if (pkg.getElementName().length() > 0) {
+		if (!pkg.isDefaultPackage()) {
 			//not the default package...add the package declaration
 			source = "package " + pkg.getElementName() + ";"  + org.eclipse.jdt.internal.compiler.util.Util.LINE_SEPARATOR + org.eclipse.jdt.internal.compiler.util.Util.LINE_SEPARATOR; //$NON-NLS-1$ //$NON-NLS-2$
 		}
@@ -402,7 +401,8 @@
 	try {
 		discardWorkingCopy();
 	} catch (JavaModelException e) {
-		e.printStackTrace();
+		if (JavaModelManager.VERBOSE)
+			e.printStackTrace();
 	}
 }
 /*
@@ -440,7 +440,7 @@
 			try {
 				// iterate through all the types inside the receiver and see if one of them can fit
 				IType[] types = getTypes();
-				String typeNodeName = nodeName.substring(0, nodeName.indexOf(SUFFIX_STRING_java));
+				String typeNodeName = nodeName.substring(0, nodeName.lastIndexOf('.'));
 				for (int i = 0, max = types.length; i < max; i++) {
 					if (types[i].getElementName().equals(typeNodeName)) {
 						return true;
@@ -458,7 +458,7 @@
 	if (getPerWorkingCopyInfo() != null) return true;	
 	
 	// if not a working copy, it exists only if it is a primary compilation unit
-	return isPrimary() && super.exists() && isValidCompilationUnit();
+	return isPrimary() && validateCompilationUnit(getResource()).isOK();
 }
 /**
  * @see ICompilationUnit#findElements(IJavaElement)
@@ -472,7 +472,7 @@
 	if (element == null) return null;
 	IJavaElement currentElement = this;
 	for (int i = children.size()-1; i >= 0; i--) {
-		JavaElement child = (JavaElement)children.get(i);
+		SourceRefElement child = (SourceRefElement)children.get(i);
 		switch (child.getElementType()) {
 			case IJavaElement.PACKAGE_DECLARATION:
 				currentElement = ((ICompilationUnit)currentElement).getPackageDeclaration(child.getElementName());
@@ -624,14 +624,20 @@
 		return e;
 	}
 }
+public String getElementName() {
+	return this.name;
+}
 /**
  * @see IJavaElement
  */
 public int getElementType() {
 	return COMPILATION_UNIT;
 }
+/**
+ * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
+ */
 public char[] getFileName(){
-	return getElementName().toCharArray();
+	return getPath().toString().toCharArray();
 }
 
 /*
@@ -639,16 +645,16 @@
  */
 public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner workingCopyOwner) {
 	switch (token.charAt(0)) {
-		case JEM_COUNT:
-			return getHandleUpdatingCountFromMemento(memento, workingCopyOwner);
 		case JEM_IMPORTDECLARATION:
 			JavaElement container = (JavaElement)getImportContainer();
 			return container.getHandleFromMemento(token, memento, workingCopyOwner);
 		case JEM_PACKAGEDECLARATION:
+			if (!memento.hasMoreTokens()) return this;
 			String pkgName = memento.nextToken();
 			JavaElement pkgDecl = (JavaElement)getPackageDeclaration(pkgName);
 			return pkgDecl.getHandleFromMemento(memento, workingCopyOwner);
 		case JEM_TYPE:
+			if (!memento.hasMoreTokens()) return this;
 			String typeName = memento.nextToken();
 			JavaElement type = (JavaElement)getType(typeName);
 			return type.getHandleFromMemento(memento, workingCopyOwner);
@@ -751,8 +757,10 @@
  * @see org.eclipse.jdt.internal.compiler.env.ICompilationUnit#getPackageName()
  */
 public char[][] getPackageName() {
-	return null;
+	PackageFragment packageFragment = (PackageFragment) getParent();
+	return Util.toCharArrays(packageFragment.names);
 }
+
 /**
  * @see IJavaElement#getPath()
  */
@@ -930,21 +938,23 @@
 protected boolean isSourceElement() {
 	return true;
 }
-protected boolean isValidCompilationUnit() {
+protected IStatus validateCompilationUnit(IResource resource) {
 	IPackageFragmentRoot root = getPackageFragmentRoot();
 	try {
-		if (root.getKind() != IPackageFragmentRoot.K_SOURCE) return false;
+		if (root.getKind() != IPackageFragmentRoot.K_SOURCE) 
+			return new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, root);
 	} catch (JavaModelException e) {
-		return false;
+		return e.getJavaModelStatus();
 	}
-	IResource resource = getResource();
 	if (resource != null) {
 		char[][] inclusionPatterns = ((PackageFragmentRoot)root).fullInclusionPatternChars();
 		char[][] exclusionPatterns = ((PackageFragmentRoot)root).fullExclusionPatternChars();
-		if (Util.isExcluded(resource, inclusionPatterns, exclusionPatterns)) return false;
+		if (Util.isExcluded(resource, inclusionPatterns, exclusionPatterns)) 
+			return new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_NOT_ON_CLASSPATH, this);
+		if (!resource.isAccessible())
+			return new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this);
 	}
-	if (!Util.isValidCompilationUnitName(getElementName())) return false;
-	return true;
+	return JavaConventions.validateCompilationUnitName(getElementName());
 }
 /*
  * @see ICompilationUnit#isWorkingCopy()
@@ -1086,9 +1096,8 @@
 		// client asking for level 2 AST; these are supported
 		createAST = true;
 	} else if (astLevel == AST.JLS3) {
-		// client asking for level 3 ASTs; these are not supported
-		// TODO (jerome) - these should also be supported in 1.5 stream
-		createAST = false;
+		// client asking for level 3 ASTs; these are supported
+		createAST = true;
 	} else {
 		// client asking for no AST (0) or unknown ast level
 		// either way, request denied
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitElementInfo.java
index 90b97fd..7a360af 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitElementInfo.java
@@ -10,9 +10,12 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.util.HashMap;
+
+import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.ISourceRange;
 
-/* package */ class CompilationUnitElementInfo extends OpenableElementInfo {
+public class CompilationUnitElementInfo extends OpenableElementInfo {
 
 	/**
 	 * The length of this compilation unit's source code <code>String</code>
@@ -24,6 +27,19 @@
 	 * was opened or last updated.
 	 */
 	protected long timestamp;
+	
+	/*
+	 * The positions of annotations for each element in this compilation unit.
+	 * A map from IJavaElement to long[]
+	 */
+	public HashMap annotationPositions;
+	
+public void addAnnotationPositions(IJavaElement handle, long[] positions) {
+	if (positions == null) return;
+	if (this.annotationPositions == null)
+		this.annotationPositions = new HashMap();
+	this.annotationPositions.put(handle, positions);
+}
 /**
  * Returns the length of the source string.
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
index 73f62fd..0646210 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
@@ -13,9 +13,9 @@
 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.*;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.*;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
@@ -24,12 +24,12 @@
 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;
 import org.eclipse.jdt.internal.compiler.env.ISourceType;
 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
 import org.eclipse.jdt.internal.compiler.parser.Parser;
 import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
-import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
 import org.eclipse.jdt.internal.core.util.CommentRecorderParser;
 import org.eclipse.jdt.internal.core.util.Util;
 
@@ -87,7 +87,7 @@
 	/**
 	 * Add additional source types
 	 */
-	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
+	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
 		// ensure to jump back to toplevel type for first one (could be a member)
 //		while (sourceTypes[0].getEnclosingType() != null)
 //			sourceTypes[0] = sourceTypes[0].getEnclosingType();
@@ -106,7 +106,7 @@
 				result);
 
 		if (unit != null) {
-			this.lookupEnvironment.buildTypeBindings(unit);
+			this.lookupEnvironment.buildTypeBindings(unit, accessRestriction);
 			this.lookupEnvironment.completeTypeBindings(unit);
 		}
 	}
@@ -136,38 +136,37 @@
 		Parser parser,
 		WorkingCopyOwner workingCopyOwner,
 		IProblemRequestor problemRequestor,
-		IProblemFactory problemFactory,
 		boolean cleanupCU,
 		IProgressMonitor monitor)
 		throws JavaModelException {
 
-		char[] fileName = unitElement.getElementName().toCharArray();
-		
 		JavaProject project = (JavaProject) unitElement.getJavaProject();
-		CompilationUnitProblemFinder problemFinder =
-			new CompilationUnitProblemFinder(
-				project.newSearchableNameEnvironment(workingCopyOwner),
+		CancelableNameEnvironment environment = null;
+		CancelableProblemFactory problemFactory = null;
+		CompilationUnitProblemFinder problemFinder = null;
+		try {
+			environment = new CancelableNameEnvironment(project, workingCopyOwner, monitor);
+			problemFactory = new CancelableProblemFactory(monitor);
+			problemFinder = new CompilationUnitProblemFinder(
+				environment,
 				getHandlingPolicy(),
 				project.getOptions(true),
 				getRequestor(),
 				problemFactory);
-		if (parser != null) {
-			problemFinder.parser = parser;
-		}
-
-		try {
-			
-			IPackageFragment packageFragment = (IPackageFragment)unitElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
+			if (parser != null) {
+				problemFinder.parser = parser;
+			}
+			PackageFragment packageFragment = (PackageFragment)unitElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
 			char[][] expectedPackageName = null;
 			if (packageFragment != null){
-				expectedPackageName = CharOperation.splitOn('.', packageFragment.getElementName().toCharArray());
+				expectedPackageName = Util.toCharArrays(packageFragment.names);
 			}
 			if (unit == null) {
 				unit = problemFinder.resolve(
 					new BasicCompilationUnit(
 						contents,
 						expectedPackageName,
-						new String(fileName),
+						unitElement.getPath().toString(),
 						unitElement),
 					true, // verify methods
 					true, // analyze code
@@ -181,16 +180,24 @@
 					true); // generate code
 			}
 			reportProblems(unit, problemRequestor, monitor);
+			if (NameLookup.VERBOSE)
+				System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
 			return unit;
+		} catch (OperationCanceledException e) {
+			throw e;
 		} catch(RuntimeException e) { 
 			// avoid breaking other tools due to internal compiler failure (40334)
 			Util.log(e, "Exception occurred during problem detection: "); //$NON-NLS-1$ 
 			throw new JavaModelException(e, IJavaModelStatusConstants.COMPILER_FAILURE);
 		} finally {
-			if (cleanupCU && unit != null) {
+			if (environment != null)
+				environment.monitor = null; // don't hold a reference to this external object
+			if (problemFactory != null)
+				problemFactory.monitor = null; // don't hold a reference to this external object
+			if (cleanupCU && unit != null)
 				unit.cleanUp();
-			}
-			problemFinder.lookupEnvironment.reset();			
+			if (problemFinder != null)
+				problemFinder.lookupEnvironment.reset();			
 		}
 	}
 
@@ -203,7 +210,7 @@
 		IProgressMonitor monitor)
 		throws JavaModelException {
 			
-		return process(null/*no CompilationUnitDeclaration*/, unitElement, contents, null/*use default Parser*/, workingCopyOwner, problemRequestor, new DefaultProblemFactory(), cleanupCU, monitor);
+		return process(null/*no CompilationUnitDeclaration*/, unitElement, contents, null/*use default Parser*/, workingCopyOwner, problemRequestor, cleanupCU, monitor);
 	}
 
 	
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
index a61d387..7115f21 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
@@ -15,12 +15,7 @@
 
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IField;
-import org.eclipse.jdt.core.IInitializer;
 import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IMethod;
-import org.eclipse.jdt.core.IPackageDeclaration;
-import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.IProblem;
@@ -116,7 +111,7 @@
 	this.unit = unit;
 	this.unitInfo = unitInfo;
 	this.newElements = newElements;
-	this.sourceFileName= unit.getElementName().toCharArray();
+	this.sourceFileName= unit.getPath().toString().toCharArray();
 } 
 /**
  * @see ISourceElementRequestor
@@ -133,7 +128,6 @@
 	ImportContainer importContainer= (ImportContainer)parentCU.getImportContainer();
 	if (this.importContainerInfo == null) {
 		this.importContainerInfo= new JavaElementInfo();
-		this.importContainerInfo.setIsStructureKnown(true);
 		parentInfo.addChild(importContainer);
 		this.newElements.put(importContainer, this.importContainerInfo);
 	}
@@ -153,7 +147,7 @@
 	info.setSourceRangeStart(declarationStart);
 	info.setSourceRangeEnd(declarationEnd);
 	info.setFlags(modifiers);
-	info.setName(name); // no trailing * if onDemand
+	info.name  = name; // no trailing * if onDemand
 	info.setOnDemand(onDemand);
 
 	this.importContainerInfo.addChild(handle);
@@ -176,7 +170,7 @@
 
 		JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
 		JavaElement parentHandle= (JavaElement) this.handleStack.peek();
-		IPackageDeclaration handle = null;
+		PackageDeclaration handle = null;
 		this.packageName= name;
 		
 		if (parentHandle.getElementType() == IJavaElement.COMPILATION_UNIT) {
@@ -219,21 +213,6 @@
 /**
  * @see ISourceElementRequestor
  */
-public void enterClass(
-	int declarationStart,
-	int modifiers,
-	char[] name,
-	int nameSourceStart,
-	int nameSourceEnd,
-	char[] superclass,
-	char[][] superinterfaces) {
-
-	enterType(declarationStart, modifiers, name, nameSourceStart, nameSourceEnd, superclass, superinterfaces);
-
-}
-/**
- * @see ISourceElementRequestor
- */
 public void enterCompilationUnit() {
 	this.infoStack = new Stack();
 	this.handleStack= new Stack();
@@ -243,55 +222,41 @@
 /**
  * @see ISourceElementRequestor
  */
-public void enterConstructor(
-	int declarationStart,
-	int modifiers,
-	char[] name,
-	int nameSourceStart,
-	int nameSourceEnd,
-	char[][] parameterTypes,
-	char[][] parameterNames,
-	char[][] exceptionTypes) {
-
-		enterMethod(declarationStart, modifiers, null, name, nameSourceStart,
-			nameSourceEnd,	parameterTypes, parameterNames, exceptionTypes, true);
+public void enterConstructor(MethodInfo methodInfo) {
+	enterMethod(methodInfo);
 }
 /**
  * @see ISourceElementRequestor
  */
-public void enterField(
-	int declarationStart,
-	int modifiers,
-	char[] type,
-	char[] name,
-	int nameSourceStart,
-	int nameSourceEnd) {
+public void enterField(FieldInfo fieldInfo) {
 
-		SourceTypeElementInfo parentInfo = (SourceTypeElementInfo) this.infoStack.peek();
-		JavaElement parentHandle= (JavaElement) this.handleStack.peek();
-		IField handle = null;
-		
-		if (parentHandle.getElementType() == IJavaElement.TYPE) {
-			handle = new SourceField(parentHandle, new String(name));
-		}
-		else {
-			Assert.isTrue(false); // Should not happen
-		}
-		resolveDuplicates(handle);
-		
-		SourceFieldElementInfo info = new SourceFieldElementInfo();
-		info.setName(name);
-		info.setNameSourceStart(nameSourceStart);
-		info.setNameSourceEnd(nameSourceEnd);
-		info.setSourceRangeStart(declarationStart);
-		info.setFlags(modifiers);
-		info.setTypeName(type);
+	SourceTypeElementInfo parentInfo = (SourceTypeElementInfo) this.infoStack.peek();
+	JavaElement parentHandle= (JavaElement) this.handleStack.peek();
+	SourceField handle = null;
+	
+	if (parentHandle.getElementType() == IJavaElement.TYPE) {
+		handle = new SourceField(parentHandle, new String(fieldInfo.name));
+	}
+	else {
+		Assert.isTrue(false); // Should not happen
+	}
+	resolveDuplicates(handle);
+	
+	SourceFieldElementInfo info = new SourceFieldElementInfo();
+	info.fieldName = fieldInfo.name;
+	info.setNameSourceStart(fieldInfo.nameSourceStart);
+	info.setNameSourceEnd(fieldInfo.nameSourceEnd);
+	info.setSourceRangeStart(fieldInfo.declarationStart);
+	info.setFlags(fieldInfo.modifiers);
+	info.setTypeName(fieldInfo.type);
+	
+	this.unitInfo.addAnnotationPositions(handle, fieldInfo.annotationPositions);
 
-		parentInfo.addChild(handle);
-		this.newElements.put(handle, info);
+	parentInfo.addChild(handle);
+	this.newElements.put(handle, info);
 
-		this.infoStack.push(info);
-		this.handleStack.push(handle);
+	this.infoStack.push(info);
+	this.handleStack.push(handle);
 }
 /**
  * @see ISourceElementRequestor
@@ -301,10 +266,10 @@
 	int modifiers) {
 		JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
 		JavaElement parentHandle= (JavaElement) this.handleStack.peek();
-		IInitializer handle = null;
+		Initializer handle = null;
 		
 		if (parentHandle.getElementType() == IJavaElement.TYPE) {
-			handle = ((IType) parentHandle).getInitializer(1);
+			handle = new Initializer(parentHandle, 1);
 		}
 		else {
 			Assert.isTrue(false); // Should not happen
@@ -324,149 +289,129 @@
 /**
  * @see ISourceElementRequestor
  */
-public void enterInterface(
-	int declarationStart,
-	int modifiers,
-	char[] name,
-	int nameSourceStart,
-	int nameSourceEnd,
-	char[][] superinterfaces) {
+public void enterMethod(MethodInfo methodInfo) {
 
-	enterType(declarationStart, modifiers, name, nameSourceStart, nameSourceEnd, null, superinterfaces);
+	SourceTypeElementInfo parentInfo = (SourceTypeElementInfo) this.infoStack.peek();
+	JavaElement parentHandle= (JavaElement) this.handleStack.peek();
+	SourceMethod handle = null;
 
+	// translate nulls to empty arrays
+	if (methodInfo.parameterTypes == null) {
+		methodInfo.parameterTypes= CharOperation.NO_CHAR_CHAR;
+	}
+	if (methodInfo.parameterNames == null) {
+		methodInfo.parameterNames= CharOperation.NO_CHAR_CHAR;
+	}
+	if (methodInfo.exceptionTypes == null) {
+		methodInfo.exceptionTypes= CharOperation.NO_CHAR_CHAR;
+	}
+	
+	String[] parameterTypeSigs = convertTypeNamesToSigs(methodInfo.parameterTypes);
+	if (parentHandle.getElementType() == IJavaElement.TYPE) {
+		handle = new SourceMethod(parentHandle, new String(methodInfo.name), parameterTypeSigs);
+	}
+	else {
+		Assert.isTrue(false); // Should not happen
+	}
+	resolveDuplicates(handle);
+	
+	SourceMethodElementInfo info;
+	if (methodInfo.isConstructor)
+		info = new SourceConstructorInfo();
+	else if (methodInfo.isAnnotation)
+		info = new SourceAnnotationMethodInfo();
+	else
+		info = new SourceMethodInfo();
+	info.setSourceRangeStart(methodInfo.declarationStart);
+	int flags = methodInfo.modifiers;
+	info.selector = methodInfo.name;
+	info.setNameSourceStart(methodInfo.nameSourceStart);
+	info.setNameSourceEnd(methodInfo.nameSourceEnd);
+	info.setFlags(flags);
+	info.setArgumentNames(methodInfo.parameterNames);
+	info.setArgumentTypeNames(methodInfo.parameterTypes);
+	info.setReturnType(methodInfo.returnType == null ? new char[]{'v', 'o','i', 'd'} : methodInfo.returnType);
+	info.setExceptionTypeNames(methodInfo.exceptionTypes);
+	this.unitInfo.addAnnotationPositions(handle, methodInfo.annotationPositions);
+	parentInfo.addChild(handle);
+	this.newElements.put(handle, info);
+	this.infoStack.push(info);
+	this.handleStack.push(handle);
+
+	if (methodInfo.typeParameters != null) {
+		for (int i = 0, length = methodInfo.typeParameters.length; i < length; i++) {
+			TypeParameterInfo typeParameterInfo = methodInfo.typeParameters[i];
+			enterTypeParameter(typeParameterInfo);
+			exitMember(typeParameterInfo.declarationEnd);
+		}
+	}
 }
 /**
  * @see ISourceElementRequestor
  */
-public void enterMethod(
-	int declarationStart,
-	int modifiers,
-	char[] returnType,
-	char[] name,
-	int nameSourceStart,
-	int nameSourceEnd,
-	char[][] parameterTypes,
-	char[][] parameterNames,
-	char[][] exceptionTypes) {
-
-		enterMethod(declarationStart, modifiers, returnType, name, nameSourceStart,
-			nameSourceEnd, parameterTypes, parameterNames, exceptionTypes, false);
-}
-/**
- * @see ISourceElementRequestor
- */
-protected void enterMethod(
-	int declarationStart,
-	int modifiers,
-	char[] returnType,
-	char[] name,
-	int nameSourceStart,
-	int nameSourceEnd,
-	char[][] parameterTypes,
-	char[][] parameterNames,
-	char[][] exceptionTypes,
-	boolean isConstructor) {
-
-		SourceTypeElementInfo parentInfo = (SourceTypeElementInfo) this.infoStack.peek();
-		JavaElement parentHandle= (JavaElement) this.handleStack.peek();
-		IMethod handle = null;
-
-		// translate nulls to empty arrays
-		if (parameterTypes == null) {
-			parameterTypes= CharOperation.NO_CHAR_CHAR;
-		}
-		if (parameterNames == null) {
-			parameterNames= CharOperation.NO_CHAR_CHAR;
-		}
-		if (exceptionTypes == null) {
-			exceptionTypes= CharOperation.NO_CHAR_CHAR;
-		}
-		
-		String[] parameterTypeSigs = convertTypeNamesToSigs(parameterTypes);
-		if (parentHandle.getElementType() == IJavaElement.TYPE) {
-			handle = new SourceMethod(parentHandle, new String(name), parameterTypeSigs);
-		}
-		else {
-			Assert.isTrue(false); // Should not happen
-		}
-		resolveDuplicates(handle);
-		
-		SourceMethodElementInfo info = new SourceMethodElementInfo();
-		info.setSourceRangeStart(declarationStart);
-		int flags = modifiers;
-		info.setName(name);
-		info.setNameSourceStart(nameSourceStart);
-		info.setNameSourceEnd(nameSourceEnd);
-		info.setConstructor(isConstructor);
-		info.setFlags(flags);
-		info.setArgumentNames(parameterNames);
-		info.setArgumentTypeNames(parameterTypes);
-		info.setReturnType(returnType == null ? new char[]{'v', 'o','i', 'd'} : returnType);
-		info.setExceptionTypeNames(exceptionTypes);
-
-		parentInfo.addChild(handle);
-		this.newElements.put(handle, info);
-		this.infoStack.push(info);
-		this.handleStack.push(handle);
-}
-/**
- * Common processing for classes and interfaces.
- */
-protected void enterType(
-	int declarationStart,
-	int modifiers,
-	char[] name,
-	int nameSourceStart,
-	int nameSourceEnd,
-	char[] superclass,
-	char[][] superinterfaces) {
+public void enterType(TypeInfo typeInfo) {
 
 	JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
 	JavaElement parentHandle= (JavaElement) this.handleStack.peek();
-	IType handle = null;
-	String nameString= new String(name);
-	
-	switch(parentHandle.getElementType()) {
-		case IJavaElement.COMPILATION_UNIT:
-			handle = ((ICompilationUnit) parentHandle).getType(nameString);
-			break;
-		case IJavaElement.TYPE:
-			handle = ((IType) parentHandle).getType(nameString);
-			break;
-		case IJavaElement.FIELD:
-		case IJavaElement.INITIALIZER:
-		case IJavaElement.METHOD:
-			handle = ((IMember) parentHandle).getType(nameString, 1); //NB: occurenceCount is computed in resolveDuplicates
-			break;
-		default:
-			Assert.isTrue(false); // Should not happen
-	}
+	String nameString= new String(typeInfo.name);
+	SourceType handle = handle = new SourceType(parentHandle, nameString); //NB: occurenceCount is computed in resolveDuplicates
 	resolveDuplicates(handle);
 	
 	SourceTypeElementInfo info = new SourceTypeElementInfo();
 	info.setHandle(handle);
-	info.setSourceRangeStart(declarationStart);
-	info.setFlags(modifiers);
-	info.setName(name);
-	info.setNameSourceStart(nameSourceStart);
-	info.setNameSourceEnd(nameSourceEnd);
-	info.setSuperclassName(superclass);
-	info.setSuperInterfaceNames(superinterfaces);
+	info.setSourceRangeStart(typeInfo.declarationStart);
+	info.setFlags(typeInfo.modifiers);
+	info.setNameSourceStart(typeInfo.nameSourceStart);
+	info.setNameSourceEnd(typeInfo.nameSourceEnd);
+	info.setSuperclassName(typeInfo.superclass);
+	info.setSuperInterfaceNames(typeInfo.superinterfaces);
 	info.setSourceFileName(this.sourceFileName);
 	info.setPackageName(this.packageName);
 	parentInfo.addChild(handle);
+	this.unitInfo.addAnnotationPositions(handle, typeInfo.annotationPositions);
 	this.newElements.put(handle, info);
-
 	this.infoStack.push(info);
 	this.handleStack.push(handle);
-
+	
+	if (typeInfo.typeParameters != null) {
+		for (int i = 0, length = typeInfo.typeParameters.length; i < length; i++) {
+			TypeParameterInfo typeParameterInfo = typeInfo.typeParameters[i];
+			enterTypeParameter(typeParameterInfo);
+			exitMember(typeParameterInfo.declarationEnd);
+		}
+	}
 }
-/**
- * @see ISourceElementRequestor
- */
-public void exitClass(int declarationEnd) {
-
-	exitMember(declarationEnd);
+protected void enterTypeParameter(TypeParameterInfo typeParameterInfo) {
+	JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
+	JavaElement parentHandle = (JavaElement) this.handleStack.peek();
+	String nameString = new String(typeParameterInfo.name);
+	TypeParameter handle = handle = new TypeParameter(parentHandle, nameString); //NB: occurenceCount is computed in resolveDuplicates
+	resolveDuplicates(handle);
+	
+	TypeParameterElementInfo info = new TypeParameterElementInfo();
+	info.setSourceRangeStart(typeParameterInfo.declarationStart);
+	info.nameStart = typeParameterInfo.nameSourceStart;
+	info.nameEnd = typeParameterInfo.nameSourceEnd;
+	info.bounds = typeParameterInfo.bounds;
+	if (parentInfo instanceof SourceTypeElementInfo) {
+		SourceTypeElementInfo elementInfo = (SourceTypeElementInfo) parentInfo;
+		ITypeParameter[] typeParameters = elementInfo.typeParameters;
+		int length = typeParameters.length;
+		System.arraycopy(typeParameters, 0, typeParameters = new ITypeParameter[length+1], 0, length);
+		typeParameters[length] = handle;
+		elementInfo.typeParameters = typeParameters;
+	} else {
+		SourceMethodElementInfo elementInfo = (SourceMethodElementInfo) parentInfo;
+		ITypeParameter[] typeParameters = elementInfo.typeParameters;
+		int length = typeParameters.length;
+		System.arraycopy(typeParameters, 0, typeParameters = new ITypeParameter[length+1], 0, length);
+		typeParameters[length] = handle;
+		elementInfo.typeParameters = typeParameters;
+	}
+	this.unitInfo.addAnnotationPositions(handle, typeParameterInfo.annotationPositions);
+	this.newElements.put(handle, info);
+	this.infoStack.push(info);
+	this.handleStack.push(handle);
 }
 /**
  * @see ISourceElementRequestor
@@ -514,12 +459,6 @@
 	exitMember(declarationEnd);
 }
 /**
- * @see ISourceElementRequestor
- */
-public void exitInterface(int declarationEnd) {
-	exitMember(declarationEnd);
-}
-/**
  * common processing for classes and interfaces
  */
 protected void exitMember(int declarationEnd) {
@@ -530,17 +469,32 @@
 /**
  * @see ISourceElementRequestor
  */
-public void exitMethod(int declarationEnd) {
+public void exitMethod(int declarationEnd, int defaultValueStart, int defaultValueEnd) {
+	SourceMethodElementInfo info = (SourceMethodElementInfo) this.infoStack.pop();
+	info.setSourceRangeEnd(declarationEnd);
+	
+	// remember default value of annotation method
+	if (info.isAnnotationMethod()) {
+		SourceAnnotationMethodInfo annotationMethodInfo = (SourceAnnotationMethodInfo) info;
+		annotationMethodInfo.defaultValueStart = defaultValueStart;
+		annotationMethodInfo.defaultValueEnd = defaultValueEnd;
+	}
+	this.handleStack.pop();
+}
+/**
+ * @see ISourceElementRequestor
+ */
+public void exitType(int declarationEnd) {
+
 	exitMember(declarationEnd);
 }
 /**
  * Resolves duplicate handles by incrementing the occurrence count
  * of the handle being created until there is no conflict.
  */
-protected void resolveDuplicates(IJavaElement handle) {
+protected void resolveDuplicates(SourceRefElement handle) {
 	while (this.newElements.containsKey(handle)) {
-		JavaElement h = (JavaElement) handle;
-		h.occurrenceCount++;
+		handle.occurrenceCount++;
 	}
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitVisitor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitVisitor.java
index e34a1f8..488ae0d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitVisitor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitVisitor.java
@@ -15,10 +15,7 @@
 
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IPackageFragment;
-//import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.Compiler;
@@ -27,11 +24,13 @@
 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;
 import org.eclipse.jdt.internal.compiler.env.ISourceType;
 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
 import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.jdt.internal.core.util.Util;
 
 public class CompilationUnitVisitor extends Compiler {
 	
@@ -81,7 +80,7 @@
 	/**
 	 * Add additional source types
 	 */
-	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
+	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
 		CompilationResult result =
 			new CompilationResult(sourceTypes[0].getFileName(), 1, 1, this.options.maxProblemsPerUnit);
 		// need to hold onto this
@@ -95,7 +94,7 @@
 				result);
 
 		if (unit != null) {
-			this.lookupEnvironment.buildTypeBindings(unit);
+			this.lookupEnvironment.buildTypeBindings(unit, accessRestriction);
 			this.lookupEnvironment.completeTypeBindings(unit, true);
 		}
 	}
@@ -144,10 +143,10 @@
 		CompilationUnitDeclaration unit = null;
 		try {
 
-			IPackageFragment packageFragment = (IPackageFragment)unitElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
+			PackageFragment packageFragment = (PackageFragment)unitElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
 			char[][] expectedPackageName = null;
 			if (packageFragment != null){
-				expectedPackageName = CharOperation.splitOn('.', packageFragment.getElementName().toCharArray());
+				expectedPackageName = Util.toCharArrays(packageFragment.names);
 			}
 			unit =
 				compilationUnitVisitor.resolve(
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompletionRequestorWrapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompletionRequestorWrapper.java
deleted file mode 100644
index c58726e..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompletionRequestorWrapper.java
+++ /dev/null
@@ -1,431 +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 Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.core;
-
-import org.eclipse.jdt.core.ICompletionRequestor;
-import org.eclipse.jdt.core.IMethod;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.Signature;
-import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.core.compiler.IProblem;
-import org.eclipse.jdt.internal.codeassist.CompletionEngine;
-import org.eclipse.jdt.internal.codeassist.IExtendedCompletionRequestor;
-
-public class CompletionRequestorWrapper implements IExtendedCompletionRequestor {
-	private static Object NO_ATTACHED_SOURCE = new Object();
-	
-	static final char[] ARG = "arg".toCharArray();  //$NON-NLS-1$
-	static final char[] ARG0 = "arg0".toCharArray();  //$NON-NLS-1$
-	static final char[] ARG1 = "arg1".toCharArray();  //$NON-NLS-1$
-	static final char[] ARG2 = "arg2".toCharArray();  //$NON-NLS-1$
-	static final char[] ARG3 = "arg3".toCharArray();  //$NON-NLS-1$
-	static final char[][] ARGS1 = new char[][]{ARG0};
-	static final char[][] ARGS2 = new char[][]{ARG0, ARG1};
-	static final char[][] ARGS3 = new char[][]{ARG0, ARG1, ARG2};
-	static final char[][] ARGS4 = new char[][]{ARG0, ARG1, ARG2, ARG3};
-	
-	public CompletionEngine completionEngine;
-	ICompletionRequestor clientRequestor;
-	NameLookup nameLookup;
-	
-public CompletionRequestorWrapper(ICompletionRequestor clientRequestor, NameLookup nameLookup){
-	this.clientRequestor = clientRequestor;
-	this.nameLookup = nameLookup;
-}
-public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
-	if(parameterNames == null)
-		parameterNames = findMethodParameterNames(superTypePackageName, superTypeName, superTypeName, parameterPackageNames, parameterTypeNames);
-
-	if(CompletionEngine.DEBUG) {
-		printDebug("acceptAnonymousType",  new String[]{ //$NON-NLS-1$
-			String.valueOf(superTypePackageName),
-			String.valueOf(superTypeName),
-			String.valueOf(parameterPackageNames),
-			String.valueOf(parameterTypeNames),
-			String.valueOf(parameterNames),
-			String.valueOf(completionName),
-			String.valueOf(modifiers),
-			String.valueOf(completionStart),
-			String.valueOf(completionEnd),
-			String.valueOf(relevance)
-		});
-	}
-	this.clientRequestor.acceptAnonymousType(superTypePackageName, superTypeName, parameterPackageNames, parameterTypeNames, parameterNames, completionName, modifiers, completionStart, completionEnd, relevance);
-}
-/**
- * See ICompletionRequestor
- */
-public void acceptClass(char[] packageName, char[] className, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-	
-	if(CompletionEngine.DEBUG) {
-		printDebug("acceptClass",  new String[]{ //$NON-NLS-1$
-			String.valueOf(packageName),
-			String.valueOf(className),
-			String.valueOf(completionName),
-			String.valueOf(modifiers),
-			String.valueOf(completionStart),
-			String.valueOf(completionEnd),
-			String.valueOf(relevance)
-		});
-	}
-	this.clientRequestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd, relevance);
-}
-/**
- * See ICompletionRequestor
- */
-public void acceptError(IProblem error) {
-	
-	if(CompletionEngine.DEBUG) {
-		System.out.print("COMPLETION - acceptError("); //$NON-NLS-1$
-		System.out.print(error);
-		System.out.println(")"); //$NON-NLS-1$
-	}
-	this.clientRequestor.acceptError(error);
-}
-/**
- * See ICompletionRequestor
- */
-public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-	
-	if(CompletionEngine.DEBUG) {
-		printDebug("acceptField",  new String[]{ //$NON-NLS-1$
-			String.valueOf(declaringTypePackageName),
-			String.valueOf(declaringTypeName),
-			String.valueOf(name),
-			String.valueOf(typePackageName),
-			String.valueOf(typeName),
-			String.valueOf(completionName),
-			String.valueOf(modifiers),
-			String.valueOf(completionStart),
-			String.valueOf(completionEnd),
-			String.valueOf(relevance)
-		});
-	}
-	this.clientRequestor.acceptField(declaringTypePackageName, declaringTypeName, name, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd, relevance);
-}
-/**
- * See ICompletionRequestor
- */
-public void acceptInterface(char[] packageName, char[] interfaceName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-	
-	if(CompletionEngine.DEBUG) {
-		printDebug("acceptInterface",  new String[]{ //$NON-NLS-1$
-			String.valueOf(packageName),
-			String.valueOf(interfaceName),
-			String.valueOf(completionName),
-			String.valueOf(modifiers),
-			String.valueOf(completionStart),
-			String.valueOf(completionEnd),
-			String.valueOf(relevance)
-		});
-	}
-	this.clientRequestor.acceptInterface(packageName, interfaceName, completionName, modifiers, completionStart, completionEnd, relevance);
-}
-/**
- * See ICompletionRequestor
- */
-public void acceptKeyword(char[] keywordName, int completionStart, int completionEnd, int relevance) {
-	
-	if(CompletionEngine.DEBUG) {
-		printDebug("acceptKeyword",  new String[]{ //$NON-NLS-1$
-			String.valueOf(keywordName),
-			String.valueOf(completionStart),
-			String.valueOf(completionEnd),
-			String.valueOf(relevance)
-		});
-	}
-	this.clientRequestor.acceptKeyword(keywordName, completionStart, completionEnd, relevance);
-}
-/**
- * See ICompletionRequestor
- */
-public void acceptLabel(char[] labelName, int completionStart, int completionEnd, int relevance) {
-	
-	if(CompletionEngine.DEBUG) {
-		printDebug("acceptLabel",  new String[]{ //$NON-NLS-1$
-			String.valueOf(labelName),
-			String.valueOf(completionStart),
-			String.valueOf(completionEnd),
-			String.valueOf(relevance)
-		});
-	}
-	this.clientRequestor.acceptLabel(labelName, completionStart, completionEnd, relevance);
-}
-/**
- * See ICompletionRequestor
- */
-public void acceptLocalVariable(char[] name, char[] typePackageName, char[] typeName, int modifiers, int completionStart, int completionEnd, int relevance) {
-	
-	if(CompletionEngine.DEBUG) {
-		printDebug("acceptLocalVariable",  new String[]{ //$NON-NLS-1$
-			String.valueOf(name),
-			String.valueOf(typePackageName),
-			String.valueOf(typeName),
-			String.valueOf(modifiers),
-			String.valueOf(completionStart),
-			String.valueOf(completionEnd),
-			String.valueOf(relevance)
-		});
-	}
-	this.clientRequestor.acceptLocalVariable(name, typePackageName, typeName, modifiers, completionStart, completionEnd, relevance);
-}
-/**
- * See ICompletionRequestor
- */
-public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, char[][] parameterNames, char[] returnTypePackageName, char[] returnTypeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-	if(parameterNames == null)
-		parameterNames = findMethodParameterNames(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames);
-
-	if(CompletionEngine.DEBUG) {
-		printDebug("acceptMethod",  new String[]{ //$NON-NLS-1$
-			String.valueOf(declaringTypePackageName),
-			String.valueOf(declaringTypeName),
-			String.valueOf(selector),
-			String.valueOf(parameterPackageNames),
-			String.valueOf(parameterTypeNames),
-			String.valueOf(parameterNames),
-			String.valueOf(returnTypePackageName),
-			String.valueOf(returnTypeName),
-			String.valueOf(completionName),
-			String.valueOf(modifiers),
-			String.valueOf(completionStart),
-			String.valueOf(completionEnd),
-			String.valueOf(relevance)
-		});
-	}
-	this.clientRequestor.acceptMethod(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, parameterNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart, completionEnd, relevance);
-}
-/**
- * See ICompletionRequestor
- */
-public void acceptMethodDeclaration(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, char[][] parameterNames, char[] returnTypePackageName, char[] returnTypeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-	if(parameterNames == null) {
-		int length = parameterTypeNames.length;
-		
-		parameterNames = findMethodParameterNames(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames);
-		
-		StringBuffer completion = new StringBuffer(completionName.length);
-			
-		int start = 0;
-		int end = CharOperation.indexOf('%', completionName);
-
-		completion.append(CharOperation.subarray(completionName, start, end));
-		
-		for(int i = 0 ; i < length ; i++){
-			completion.append(parameterNames[i]);
-			start = end + 1;
-			end = CharOperation.indexOf('%', completionName, start);
-			if(end > -1){
-				completion.append(CharOperation.subarray(completionName, start, end));
-			} else {
-				completion.append(CharOperation.subarray(completionName, start, completionName.length));
-			}
-		}
-		
-		completionName = completion.toString().toCharArray();
-	}	
-	
-	if(CompletionEngine.DEBUG) {
-		printDebug("acceptMethodDeclaration",  new String[]{ //$NON-NLS-1$
-			String.valueOf(declaringTypePackageName),
-			String.valueOf(declaringTypeName),
-			String.valueOf(selector),
-			String.valueOf(parameterPackageNames),
-			String.valueOf(parameterTypeNames),
-			String.valueOf(parameterNames),
-			String.valueOf(returnTypePackageName),
-			String.valueOf(returnTypeName),
-			String.valueOf(completionName),
-			String.valueOf(modifiers),
-			String.valueOf(completionStart),
-			String.valueOf(completionEnd),
-			String.valueOf(relevance)
-		});
-	}
-	this.clientRequestor.acceptMethodDeclaration(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, parameterNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart, completionEnd, relevance);
-}
-/**
- * See ICompletionRequestor
- */
-public void acceptModifier(char[] modifierName, int completionStart, int completionEnd, int relevance) {
-	
-	if(CompletionEngine.DEBUG) {
-		printDebug("acceptModifier",  new String[]{ //$NON-NLS-1$
-			String.valueOf(modifierName),
-			String.valueOf(completionStart),
-			String.valueOf(completionEnd),
-			String.valueOf(relevance)
-		});
-	}
-	this.clientRequestor.acceptModifier(modifierName, completionStart, completionEnd, relevance);
-}
-/**
- * See ICompletionRequestor
- */
-public void acceptPackage(char[] packageName, char[] completionName, int completionStart, int completionEnd, int relevance) {
-	
-	if(CompletionEngine.DEBUG) {
-		printDebug("acceptPackage",  new String[]{ //$NON-NLS-1$
-			String.valueOf(packageName),
-			String.valueOf(completionName),
-			String.valueOf(completionStart),
-			String.valueOf(completionEnd),
-			String.valueOf(relevance)
-		});
-	}
-	this.clientRequestor.acceptPackage(packageName, completionName, completionStart, completionEnd, relevance);
-}
-/**
- * See ICompletionRequestor
- */
-public void acceptType(char[] packageName, char[] typeName, char[] completionName, int completionStart, int completionEnd, int relevance) {
-	
-	if(CompletionEngine.DEBUG) {
-		printDebug("acceptType",  new String[]{ //$NON-NLS-1$
-			String.valueOf(packageName),
-			String.valueOf(typeName),
-			String.valueOf(completionName),
-			String.valueOf(completionStart),
-			String.valueOf(completionEnd),
-			String.valueOf(relevance)
-		});
-	}
-	this.clientRequestor.acceptType(packageName, typeName, completionName, completionStart, completionEnd, relevance);
-}
-public void acceptVariableName(char[] typePackageName, char[] typeName, char[] name, char[] completionName, int completionStart, int completionEnd, int relevance){
-	
-	if(CompletionEngine.DEBUG) {
-		printDebug("acceptVariableName",  new String[]{ //$NON-NLS-1$
-			String.valueOf(typePackageName),
-			String.valueOf(typeName),
-			String.valueOf(name),
-			String.valueOf(completionName),
-			String.valueOf(completionStart),
-			String.valueOf(completionEnd),
-			String.valueOf(relevance)
-		});
-	}
-	this.clientRequestor.acceptVariableName(typePackageName, typeName, name, completionName, completionStart, completionEnd, relevance);
-}
-private char[][] findMethodParameterNames(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames){
-	char[][] parameterNames = null;
-	int length = parameterTypeNames.length;
-	
-	char[] typeName = CharOperation.concat(declaringTypePackageName,declaringTypeName,'.');
-	Object cachedType = this.completionEngine.typeCache.get(typeName);
-	
-	IType type = null;
-	if(cachedType != null) {
-		if(cachedType != NO_ATTACHED_SOURCE && cachedType instanceof BinaryType) {
-			type = (BinaryType)cachedType;
-		}
-	} else { 
-		type = this.nameLookup.findType(new String(typeName), false, NameLookup.ACCEPT_CLASSES & NameLookup.ACCEPT_INTERFACES);
-		if(type instanceof BinaryType){
-			if(((BinaryType)type).getSourceMapper() != null) {
-				this.completionEngine.typeCache.put(typeName, type);
-			} else {
-				this.completionEngine.typeCache.put(typeName, NO_ATTACHED_SOURCE);
-				type = null;
-			}
-		} else {
-			type = null;
-		}
-	}
-	
-	if(type != null) {
-		String[] args = new String[length];
-		for(int i = 0;	i< length ; i++){
-			char[] parameterType = CharOperation.concat(parameterPackageNames[i],parameterTypeNames[i],'.');
-			args[i] = Signature.createTypeSignature(parameterType,true);
-		}
-		IMethod method = type.getMethod(new String(selector),args);
-		try{
-			parameterNames = new char[length][];
-			String[] params = method.getParameterNames();
-			for(int i = 0;	i< length ; i++){
-				parameterNames[i] = params[i].toCharArray();
-			}
-		} catch(JavaModelException e){
-			parameterNames = null;
-		}
-	}
-	// default parameters name
-	if(parameterNames == null) {
-		switch (length) {
-			case 0 :
-				parameterNames = new char[length][];
-				break;
-			case 1 :
-				parameterNames = ARGS1;
-				break;
-			case 2 :
-				parameterNames = ARGS2;
-				break;
-			case 3 :
-				parameterNames = ARGS3;
-				break;
-			case 4 :
-				parameterNames = ARGS4;
-				break;
-			default :
-				parameterNames = new char[length][];
-				for (int i = 0; i < length; i++) {
-					parameterNames[i] = CharOperation.concat(ARG, String.valueOf(i).toCharArray());
-				}
-				break;
-		}
-		
-	}
-	return parameterNames;
-}
-public void acceptPotentialMethodDeclaration(char[] declaringTypePackageName,
-		char[] declaringTypeName, char[] selector, int completionStart,
-		int completionEnd, int relevance) {
-	if(this.clientRequestor instanceof IExtendedCompletionRequestor) {
-		if(CompletionEngine.DEBUG) {
-			printDebug("acceptPotentialMethodDeclaration",  new String[]{ //$NON-NLS-1$
-				String.valueOf(declaringTypePackageName),
-				String.valueOf(declaringTypeName),
-				String.valueOf(selector),
-				String.valueOf(completionStart),
-				String.valueOf(completionEnd),
-				String.valueOf(relevance)
-			});
-		}
-		
-		((IExtendedCompletionRequestor)this.clientRequestor).acceptPotentialMethodDeclaration(
-			declaringTypePackageName,
-			declaringTypeName,
-			selector,
-			completionStart,
-			completionEnd,
-			relevance);
-	}
-}
-
-private void printDebug(String header, String[] param){
-	StringBuffer buffer = new StringBuffer();
-	buffer.append("COMPLETION - "); //$NON-NLS-1$
-	buffer.append(header);
-	buffer.append("(");//$NON-NLS-1$
-	
-	for (int i = 0; i < param.length; i++) {
-		if(i != 0)
-			buffer.append(", ");//$NON-NLS-1$
-		buffer.append(param[i]);
-	}
-
-	buffer.append(")");//$NON-NLS-1$
-	System.out.println(buffer.toString());
-}
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyElementsOperation.java
index 1198b66..e6f0195 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyElementsOperation.java
@@ -13,6 +13,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaModelStatus;
@@ -98,7 +99,9 @@
 				return new CreateImportOperation(element.getElementName(), (ICompilationUnit) dest);
 			case IJavaElement.TYPE :
 				if (isRenamingMainType(element, dest)) {
-					return new RenameResourceElementsOperation(new IJavaElement[] {dest}, new IJavaElement[] {dest.getParent()}, new String[]{getNewNameFor(element) + SUFFIX_STRING_java}, this.force); //$NON-NLS-1$
+					IPath path = element.getPath();
+					String extension = path.getFileExtension();
+					return new RenameResourceElementsOperation(new IJavaElement[] {dest}, new IJavaElement[] {dest.getParent()}, new String[]{getNewNameFor(element) + '.' + extension}, this.force); //$NON-NLS-1$
 				} else {
 					return new CreateTypeOperation(dest, getSourceFor(element) + Util.LINE_SEPARATOR, this.force);
 				}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyPackageFragmentRootOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyPackageFragmentRootOperation.java
index 271ef41..9cf7045 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyPackageFragmentRootOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyPackageFragmentRootOperation.java
@@ -189,21 +189,21 @@
 	protected IClasspathEntry copy(IClasspathEntry entry) throws JavaModelException {
 		switch (entry.getEntryKind()) {
 			case IClasspathEntry.CPE_CONTAINER:
-				return JavaCore.newContainerEntry(entry.getPath(), entry.isExported());
+				return JavaCore.newContainerEntry(entry.getPath(), entry.getInclusionPatterns(), entry.getExclusionPatterns(), entry.isExported());
 			case IClasspathEntry.CPE_LIBRARY:
 				try {
-					return JavaCore.newLibraryEntry(this.destination, entry.getSourceAttachmentPath(), entry.getSourceAttachmentRootPath(), entry.isExported());
+					return JavaCore.newLibraryEntry(this.destination, entry.getSourceAttachmentPath(), entry.getSourceAttachmentRootPath(), entry.getInclusionPatterns(), entry.getExclusionPatterns(), entry.isExported());
 				} catch (Assert.AssertionFailedException e) {
 					IJavaModelStatus status = new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, e.getMessage());
 					throw new JavaModelException(status);
 				}
 			case IClasspathEntry.CPE_PROJECT:
-				return JavaCore.newProjectEntry(entry.getPath(), entry.isExported());
+				return JavaCore.newProjectEntry(entry.getPath(), entry.getInclusionPatterns(), entry.getExclusionPatterns(), entry.isExported());
 			case IClasspathEntry.CPE_SOURCE:
 				return JavaCore.newSourceEntry(this.destination, entry.getInclusionPatterns(), entry.getExclusionPatterns(), entry.getOutputLocation());
 			case IClasspathEntry.CPE_VARIABLE:
 				try {
-					return JavaCore.newVariableEntry(entry.getPath(), entry.getSourceAttachmentPath(), entry.getSourceAttachmentRootPath(), entry.isExported());
+					return JavaCore.newVariableEntry(entry.getPath(), entry.getSourceAttachmentPath(), entry.getSourceAttachmentRootPath(), entry.getInclusionPatterns(), entry.getExclusionPatterns(), entry.isExported());
 				} catch (Assert.AssertionFailedException e) {
 					IJavaModelStatus status = new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, e.getMessage());
 					throw new JavaModelException(status);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java
index 7fc4697..00fa790 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java
@@ -139,30 +139,29 @@
 	 * Creates any destination package fragment(s) which do not exists yet.
 	 * Return true if a read-only package fragment has been found among package fragments, false otherwise
 	 */
-	private boolean createNeededPackageFragments(IContainer sourceFolder, IPackageFragmentRoot root, String newFragName, boolean moveFolder) throws JavaModelException {
+	private boolean createNeededPackageFragments(IContainer sourceFolder, PackageFragmentRoot root, String[] newFragName, boolean moveFolder) throws JavaModelException {
 		boolean containsReadOnlyPackageFragment = false;
 		IContainer parentFolder = (IContainer) root.getResource();
 		JavaElementDelta projectDelta = null;
-		String[] names = Util.getTrimmedSimpleNames(newFragName);
-		StringBuffer sideEffectPackageName = new StringBuffer();
-		char[][] inclusionPatterns = ((PackageFragmentRoot)root).fullInclusionPatternChars();
-		char[][] exclusionPatterns = ((PackageFragmentRoot)root).fullExclusionPatternChars();
-		for (int i = 0; i < names.length; i++) {
-			String subFolderName = names[i];
-			sideEffectPackageName.append(subFolderName);
+		String[] sideEffectPackageName = null;
+		char[][] inclusionPatterns = root.fullInclusionPatternChars();
+		char[][] exclusionPatterns = root.fullExclusionPatternChars();
+		for (int i = 0; i < newFragName.length; i++) {
+			String subFolderName = newFragName[i];
+			sideEffectPackageName = Util.arrayConcat(sideEffectPackageName, subFolderName);
 			IResource subFolder = parentFolder.findMember(subFolderName);
 			if (subFolder == null) {
 				// create deepest folder only if not a move (folder will be moved in processPackageFragmentResource)
-				if (!(moveFolder && i == names.length-1)) {
+				if (!(moveFolder && i == newFragName.length-1)) {
 					createFolder(parentFolder, subFolderName, force);
 				}
 				parentFolder = parentFolder.getFolder(new Path(subFolderName));
 				sourceFolder = sourceFolder.getFolder(new Path(subFolderName));
-				if (sourceFolder.isReadOnly()) {
+				if (Util.isReadOnly(sourceFolder)) {
 					containsReadOnlyPackageFragment = true;
 				}
-				IPackageFragment sideEffectPackage = root.getPackageFragment(sideEffectPackageName.toString());
-				if (i < names.length - 1 // all but the last one are side effect packages
+				IPackageFragment sideEffectPackage = root.getPackageFragment(sideEffectPackageName);
+				if (i < newFragName.length - 1 // all but the last one are side effect packages
 						&& !Util.isExcluded(parentFolder, inclusionPatterns, exclusionPatterns)) { 
 					if (projectDelta == null) {
 						projectDelta = getDeltaFor(root.getJavaProject());
@@ -173,7 +172,6 @@
 			} else {
 				parentFolder = (IContainer) subFolder;
 			}
-			sideEffectPackageName.append('.');
 		}
 		return containsReadOnlyPackageFragment;
 	}
@@ -228,7 +226,7 @@
 	 * @exception JavaModelException if the operation is unable to
 	 * complete
 	 */
-	private void processCompilationUnitResource(ICompilationUnit source, IPackageFragment dest) throws JavaModelException {
+	private void processCompilationUnitResource(ICompilationUnit source, PackageFragment dest) throws JavaModelException {
 		String newCUName = getNewNameFor(source);
 		String destName = (newCUName != null) ? newCUName : source.getElementName();
 		String newContent = updatedContent(source, dest, newCUName); // null if unchanged
@@ -293,7 +291,7 @@
 					// when the file was copied, its read-only flag was preserved -> temporary set it to false
 					// note this doesn't interfer with repository providers as this is a new resource that cannot be under
 					// version control yet
-					destFile.setReadOnly(false);
+					Util.setReadOnly(destFile, false);
 					
 					destFile.setContents(
 						new ByteArrayInputStream(encoding == null ? newContent.getBytes() : newContent.getBytes(encoding)), 
@@ -304,7 +302,7 @@
 				} catch (CoreException e) {
 					throw new JavaModelException(e);
 				} finally {
-					destFile.setReadOnly(wasReadOnly);
+					Util.setReadOnly(destFile, wasReadOnly);
 				}
 			}
 		
@@ -371,11 +369,11 @@
 		IJavaElement dest = getDestinationParent(element);
 		switch (element.getElementType()) {
 			case IJavaElement.COMPILATION_UNIT :
-				processCompilationUnitResource((ICompilationUnit) element, (IPackageFragment) dest);
+				processCompilationUnitResource((ICompilationUnit) element, (PackageFragment) dest);
 				createdElements.add(((IPackageFragment) dest).getCompilationUnit(element.getElementName()));
 				break;
 			case IJavaElement.PACKAGE_FRAGMENT :
-				processPackageFragmentResource((IPackageFragment) element, (IPackageFragmentRoot) dest, getNewNameFor(element));
+				processPackageFragmentResource((PackageFragment) element, (PackageFragmentRoot) dest, getNewNameFor(element));
 				break;
 			default :
 				throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element));
@@ -407,9 +405,9 @@
 	 * @deprecated marked deprecated to suppress JDOM-related deprecation warnings
 	 */
     // TODO - JDOM - remove once model ported off of JDOM
-	private void processPackageFragmentResource(IPackageFragment source, IPackageFragmentRoot root, String newName) throws JavaModelException {
+	private void processPackageFragmentResource(PackageFragment source, PackageFragmentRoot root, String newName) throws JavaModelException {
 		try {
-			String newFragName = (newName == null) ? source.getElementName() : newName;
+			String[] newFragName = (newName == null) ? source.names : Util.getTrimmedSimpleNames(newName);
 			IPackageFragment newFrag = root.getPackageFragment(newFragName);
 			IResource[] resources = collectResourcesOfInterest(source);
 			
@@ -490,13 +488,14 @@
 			}
 	
 			// Update package statement in compilation unit if needed
-			if (!newFrag.getElementName().equals(source.getElementName())) { // if package has been renamed, update the compilation units
-				char[][] inclusionPatterns = ((PackageFragmentRoot)root).fullInclusionPatternChars();
-				char[][] exclusionPatterns = ((PackageFragmentRoot)root).fullExclusionPatternChars();
+			if (!Util.equalArraysOrNull(newFragName, source.names)) { // if package has been renamed, update the compilation units
+				char[][] inclusionPatterns = root.fullInclusionPatternChars();
+				char[][] exclusionPatterns = root.fullExclusionPatternChars();
 				for (int i = 0; i < resources.length; i++) {
-					if (resources[i].getName().endsWith(SUFFIX_STRING_java)) {
+					String resourceName = resources[i].getName();
+					if (Util.isJavaLikeFileName(resourceName)) {
 						// we only consider potential compilation units
-						ICompilationUnit cu = newFrag.getCompilationUnit(resources[i].getName());
+						ICompilationUnit cu = newFrag.getCompilationUnit(resourceName);
 						if (Util.isExcluded(cu.getPath(), inclusionPatterns, exclusionPatterns, false/*not a folder*/)) continue;
 						IDOMCompilationUnit domCU = fFactory.createCompilationUnit(cu.getSource(), cu.getElementName());
 						if (domCU != null) {
@@ -579,10 +578,10 @@
 	 * @deprecated marked deprecated to suppress JDOM-related deprecation warnings
 	 */
     // TODO - JDOM - remove once model ported off of JDOM
-	private String updatedContent(ICompilationUnit cu, IPackageFragment dest, String newName) throws JavaModelException {
-		String currPackageName = cu.getParent().getElementName();
-		String destPackageName = dest.getElementName();
-		if (currPackageName.equals(destPackageName) && newName == null) {
+	private String updatedContent(ICompilationUnit cu, PackageFragment dest, String newName) throws JavaModelException {
+		String[] currPackageName = ((PackageFragment) cu.getParent()).names;
+		String[] destPackageName = dest.names;
+		if (Util.equalArraysOrNull(currPackageName, destPackageName) && newName == null) {
 			return null; //nothing to change
 		} else {
 			String typeName = cu.getElementName();
@@ -603,15 +602,15 @@
 	 * @deprecated marked deprecated to suppress JDOM-related deprecation warnings
 	 */
     // TODO - JDOM - remove once model ported off of JDOM
-	private void updatePackageStatement(IDOMCompilationUnit domCU, String pkgName) {
-		boolean defaultPackage = pkgName.equals(IPackageFragment.DEFAULT_PACKAGE_NAME);
+	private void updatePackageStatement(IDOMCompilationUnit domCU, String[] pkgName) {
+		boolean defaultPackage = pkgName.length == 0;
 		boolean seenPackageNode = false;
 		Enumeration nodes = domCU.getChildren();
 		while (nodes.hasMoreElements()) {
 			IDOMNode node = (IDOMNode) nodes.nextElement();
 			if (node.getNodeType() == IDOMNode.PACKAGE) {
 				if (! defaultPackage) {
-					node.setName(pkgName);
+					node.setName(Util.concatWith(pkgName, '.'));
 				} else {
 					node.remove();
 				}
@@ -622,7 +621,7 @@
 		if (!seenPackageNode && !defaultPackage) {
 			//the cu was in a default package...no package declaration
 			//create the new package declaration as the first child of the cu
-			IDOMPackage pkg = fFactory.createPackage("package " + pkgName + ";" + org.eclipse.jdt.internal.compiler.util.Util.LINE_SEPARATOR); //$NON-NLS-1$ //$NON-NLS-2$
+			IDOMPackage pkg = fFactory.createPackage("package " + Util.concatWith(pkgName, '.') + ";" + org.eclipse.jdt.internal.compiler.util.Util.LINE_SEPARATOR); //$NON-NLS-1$ //$NON-NLS-2$
 			IDOMNode firstChild = domCU.getFirstChild();
 			if (firstChild != null) {
 				firstChild.insertSibling(pkg);
@@ -630,37 +629,29 @@
 		}
 	}
 	
-	private void updateReadOnlyPackageFragmentsForCopy(IContainer sourceFolder, IPackageFragmentRoot root, String newFragName) {
+	private void updateReadOnlyPackageFragmentsForCopy(IContainer sourceFolder, IPackageFragmentRoot root, String[] newFragName) {
 		IContainer parentFolder = (IContainer) root.getResource();
-		String[] names = Util.getTrimmedSimpleNames(newFragName);
-		StringBuffer sideEffectPackageName = new StringBuffer();
-		for (int i = 0, nameLength = names.length; i < nameLength; i++) {
-			String subFolderName = names[i];
-			sideEffectPackageName.append(subFolderName);
+		for (int i = 0, length = newFragName.length; i <length; i++) {
+			String subFolderName = newFragName[i];
 			parentFolder = parentFolder.getFolder(new Path(subFolderName));
 			sourceFolder = sourceFolder.getFolder(new Path(subFolderName));
-			if (sourceFolder.exists() && sourceFolder.isReadOnly()) {
-				parentFolder.setReadOnly(true);
+			if (sourceFolder.exists() && Util.isReadOnly(sourceFolder)) {
+				Util.setReadOnly(parentFolder, true);
 			}
-			sideEffectPackageName.append('.');
 		}
 	}
 
-	private void updateReadOnlyPackageFragmentsForMove(IContainer sourceFolder, IPackageFragmentRoot root, String newFragName, boolean sourceFolderIsReadOnly) {
+	private void updateReadOnlyPackageFragmentsForMove(IContainer sourceFolder, IPackageFragmentRoot root, String[] newFragName, boolean sourceFolderIsReadOnly) {
 		IContainer parentFolder = (IContainer) root.getResource();
-		String[] names = Util.getTrimmedSimpleNames(newFragName);
-		StringBuffer sideEffectPackageName = new StringBuffer();
-		for (int i = 0, nameLength = names.length; i < nameLength; i++) {
-			String subFolderName = names[i];
-			sideEffectPackageName.append(subFolderName);
+		for (int i = 0, length = newFragName.length; i < length; i++) {
+			String subFolderName = newFragName[i];
 			parentFolder = parentFolder.getFolder(new Path(subFolderName));
 			sourceFolder = sourceFolder.getFolder(new Path(subFolderName));
-			if ((sourceFolder.exists() && sourceFolder.isReadOnly()) || (i == nameLength - 1 && sourceFolderIsReadOnly)) {
-				parentFolder.setReadOnly(true);
+			if ((sourceFolder.exists() && Util.isReadOnly(sourceFolder)) || (i == length - 1 && sourceFolderIsReadOnly)) {
+				Util.setReadOnly(parentFolder, true);
 				// the source folder will be deleted anyway (move operation)
-				sourceFolder.setReadOnly(false);
+				Util.setReadOnly(sourceFolder, false);
 			}
-			sideEffectPackageName.append('.');
 		}
 	}
 		/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageFragmentOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageFragmentOperation.java
index b473182..e4bdf14 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageFragmentOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageFragmentOperation.java
@@ -23,6 +23,7 @@
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaConventions;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.core.util.Util;
 
 /**
@@ -47,7 +48,7 @@
 	/**
 	 * The fully qualified, dot-delimited, package name.
 	 */
-	protected String fName;
+	protected String[] pkgName;
 /**
  * When executed, this operation will create a package fragment with the given name
  * under the given package fragment root. The dot-separated name is broken into
@@ -56,7 +57,7 @@
  */
 public CreatePackageFragmentOperation(IPackageFragmentRoot parentElement, String packageName, boolean force) {
 	super(null, new IJavaElement[]{parentElement}, force);
-	fName = packageName;
+	this.pkgName = packageName == null ? null : Util.getTrimmedSimpleNames(packageName);
 }
 /**
  * Execute the operation - creates the new package fragment and any
@@ -66,18 +67,17 @@
  */
 protected void executeOperation() throws JavaModelException {
 	JavaElementDelta delta = null;
-	IPackageFragmentRoot root = (IPackageFragmentRoot) getParentElement();
-	String[] names = Util.getTrimmedSimpleNames(fName);
-	beginTask(Util.bind("operation.createPackageFragmentProgress"), names.length); //$NON-NLS-1$
+	PackageFragmentRoot root = (PackageFragmentRoot) getParentElement();
+	beginTask(Util.bind("operation.createPackageFragmentProgress"), this.pkgName.length); //$NON-NLS-1$
 	IContainer parentFolder = (IContainer) root.getResource();
-	String sideEffectPackageName = ""; //$NON-NLS-1$
-	ArrayList results = new ArrayList(names.length);
-	char[][] inclusionPatterns = ((PackageFragmentRoot)root).fullInclusionPatternChars();
-	char[][] exclusionPatterns = ((PackageFragmentRoot)root).fullExclusionPatternChars();
+	String[] sideEffectPackageName = CharOperation.NO_STRINGS; 
+	ArrayList results = new ArrayList(this.pkgName.length);
+	char[][] inclusionPatterns = root.fullInclusionPatternChars();
+	char[][] exclusionPatterns = root.fullExclusionPatternChars();
 	int i;
-	for (i = 0; i < names.length; i++) {
-		String subFolderName = names[i];
-		sideEffectPackageName += subFolderName;
+	for (i = 0; i < this.pkgName.length; i++) {
+		String subFolderName = this.pkgName[i];
+		sideEffectPackageName = Util.arrayConcat(sideEffectPackageName, subFolderName);
 		IResource subFolder = parentFolder.findMember(subFolderName);
 		if (subFolder == null) {
 			createFolder(parentFolder, subFolderName, force);
@@ -93,12 +93,11 @@
 		} else {
 			parentFolder = (IContainer) subFolder;
 		}
-		sideEffectPackageName += '.';
 		worked(1);
 	}
 	if (results.size() > 0) {
-		resultElements = new IJavaElement[results.size()];
-		results.toArray(resultElements);
+		this.resultElements = new IJavaElement[results.size()];
+		results.toArray(this.resultElements);
 		if (delta != null) {
 			addDelta(delta);
 		}
@@ -124,18 +123,18 @@
 		return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
 	}
 	
-	if (fName == null || (fName.length() > 0 && JavaConventions.validatePackageName(fName).getSeverity() == IStatus.ERROR)) {
-		return new JavaModelStatus(IJavaModelStatusConstants.INVALID_NAME, fName);
+	String packageName = this.pkgName == null ? null : Util.concatWith(this.pkgName, '.');
+	if (this.pkgName == null || (this.pkgName.length > 0 && JavaConventions.validatePackageName(packageName).getSeverity() == IStatus.ERROR)) {
+		return new JavaModelStatus(IJavaModelStatusConstants.INVALID_NAME, packageName);
 	}
 	IPackageFragmentRoot root = (IPackageFragmentRoot) getParentElement();
 	if (root.isReadOnly()) {
 		return new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, root);
 	}
-	String[] names = Util.getTrimmedSimpleNames(fName);
 	IContainer parentFolder = (IContainer) root.getResource();
 	int i;
-	for (i = 0; i < names.length; i++) {
-		IResource subFolder = parentFolder.findMember(names[i]);
+	for (i = 0; i < this.pkgName.length; i++) {
+		IResource subFolder = parentFolder.findMember(this.pkgName[i]);
 		if (subFolder != null) {
 			if (subFolder.getType() != IResource.FOLDER) {
 				return new JavaModelStatus(
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java
index 3306502..703160a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java
@@ -14,6 +14,9 @@
 import java.util.Iterator;
 import java.util.Map;
 
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
 import org.eclipse.jdt.core.IBuffer;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaElement;
@@ -73,6 +76,14 @@
 	protected String getMainTaskName() {
 		return Util.bind("operation.deleteElementProgress"); //$NON-NLS-1$
 	}
+	protected ISchedulingRule getSchedulingRule() {
+		if (this.elementsToProcess != null && this.elementsToProcess.length == 1) {
+			IResource resource = this.elementsToProcess[0].getResource();
+			if (resource != null)
+				return ResourcesPlugin.getWorkspace().getRuleFactory().modifyRule(resource);
+		}
+		return super.getSchedulingRule();
+	}
 	/**
 	 * Groups the elements to be processed by their compilation unit.
 	 * If parent/child combinations are present, children are
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
index 6d22858..f915e8e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
@@ -31,7 +31,6 @@
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.Preferences;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.ElementChangedEvent;
 import org.eclipse.jdt.core.IClasspathEntry;
@@ -43,6 +42,7 @@
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.core.builder.JavaBuilder;
 import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
 import org.eclipse.jdt.internal.core.search.AbstractSearchScope;
@@ -613,12 +613,11 @@
 			case IJavaElement.PACKAGE_FRAGMENT:
 				if (rootInfo != null) {
 					if (rootInfo.project.contains(resource)) {
-						IPackageFragmentRoot root = rootInfo.getPackageFragmentRoot(null);
+						PackageFragmentRoot root = (PackageFragmentRoot) rootInfo.getPackageFragmentRoot(null);
 						// create package handle
 						IPath pkgPath = path.removeFirstSegments(rootInfo.rootPath.segmentCount());
-						String pkg = Util.packageName(pkgPath);
-						if (pkg == null) return null;
-						element = root.getPackageFragment(pkg);
+						String[] pkgName = pkgPath.segments();
+						element = root.getPackageFragment(pkgName);
 					}
 				} else {
 					// find the element that encloses the resource
@@ -628,15 +627,14 @@
 						element = JavaCore.create(resource);
 					} else {
 						// find the root
-						IPackageFragmentRoot root = this.currentElement.getPackageFragmentRoot();
+						PackageFragmentRoot root = this.currentElement.getPackageFragmentRoot();
 						if (root == null) {
 							element =  JavaCore.create(resource);
 						} else if (((JavaProject)root.getJavaProject()).contains(resource)) {
 							// create package handle
 							IPath pkgPath = path.removeFirstSegments(root.getPath().segmentCount());
-							String pkg = Util.packageName(pkgPath);
-							if (pkg == null) return null;
-							element = root.getPackageFragment(pkg);
+							String[] pkgName = pkgPath.segments();
+							element = root.getPackageFragment(pkgName);
 						}
 					}
 				}
@@ -653,13 +651,11 @@
 					IPackageFragment pkgFragment = null;
 					switch (this.currentElement.getElementType()) {
 						case IJavaElement.PACKAGE_FRAGMENT_ROOT:
-							IPackageFragmentRoot root = (IPackageFragmentRoot)this.currentElement;
+							PackageFragmentRoot root = (PackageFragmentRoot)this.currentElement;
 							IPath rootPath = root.getPath();
 							IPath pkgPath = path.removeLastSegments(1);
-							String pkgName = Util.packageName(pkgPath.removeFirstSegments(rootPath.segmentCount()));
-							if (pkgName != null) {
-								pkgFragment = root.getPackageFragment(pkgName);
-							}
+							String[] pkgName = pkgPath.removeFirstSegments(rootPath.segmentCount()).segments();
+							pkgFragment = root.getPackageFragment(pkgName);
 							break;
 						case IJavaElement.PACKAGE_FRAGMENT:
 							Openable pkg = this.currentElement;
@@ -910,7 +906,8 @@
 					javaProject, 
 					javaProject.computePackageFragmentRoots(
 						javaProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/), 
-						false));
+						false,
+						null /*no reverse map*/));
 			}
 			
 			javaProject.close();
@@ -921,6 +918,8 @@
 			}
 			this.removeFromParentInfo(javaProject);
 
+			// remove preferences from per project info
+			this.manager.resetProjectPreferences(javaProject);	
 		} catch (JavaModelException e) {
 			// java project doesn't exist: ignore
 		}
@@ -1032,28 +1031,6 @@
 					project = (JavaProject) element.getJavaProject();
 					this.projectCachesToReset.add(project);						
 
-					// add subpackages
-					if (delta != null){
-						PackageFragmentRoot root = element.getPackageFragmentRoot();
-						String name = element.getElementName();
-						IResourceDelta[] children = delta.getAffectedChildren();
-						for (int i = 0, length = children.length; i < length; i++) {
-							IResourceDelta child = children[i];
-							IResource resource = child.getResource();
-							if (resource instanceof IFolder) {
-								String folderName = resource.getName();
-								if (Util.isValidFolderNameForPackage(folderName)) {
-									String subpkgName = 
-										name.length() == 0 ? 
-											folderName : 
-											name + "." + folderName; //$NON-NLS-1$
-									Openable subpkg = (Openable)root.getPackageFragment(subpkgName);
-									this.updateIndex(subpkg, child);
-									this.elementAdded(subpkg, child, rootInfo);
-								}
-							}
-						}
-					}
 					break;
 			}
 		}
@@ -1151,28 +1128,6 @@
 				project = (JavaProject) element.getJavaProject();
 				this.projectCachesToReset.add(project);
 
-				// remove subpackages
-				if (delta != null){
-					PackageFragmentRoot root = element.getPackageFragmentRoot();
-					String name = element.getElementName();
-					IResourceDelta[] children = delta.getAffectedChildren();
-					for (int i = 0, length = children.length; i < length; i++) {
-						IResourceDelta child = children[i];
-						IResource resource = child.getResource();
-						if (resource instanceof IFolder) {
-							String folderName = resource.getName();
-							if (Util.isValidFolderNameForPackage(folderName)) {
-								String subpkgName = 
-									name.length() == 0 ? 
-										folderName : 
-										name + "." + folderName; //$NON-NLS-1$
-								Openable subpkg = (Openable)root.getPackageFragment(subpkgName);
-								this.updateIndex(subpkg, child);
-								this.elementRemoved(subpkg, child, rootInfo);
-							}
-						}
-					}
-				}
 				break;
 		}
 	}
@@ -1342,6 +1297,7 @@
 		if (rootDelta != null) {
 			// use local exception to quickly escape from delta traversal
 			class FoundRelevantDeltaException extends RuntimeException {
+				private static final long serialVersionUID = 7137113252936111022L; // backward compatible
 				// only the class name is used (to differenciate from other RuntimeExceptions)
 			}
 			try {
@@ -1610,7 +1566,7 @@
 			}
 			if (currentElementPath != null) {
 				if (this.currentElement instanceof IPackageFragment 
-					&& this.currentElement.getElementName().length() == 0
+					&& ((IPackageFragment) this.currentElement).isDefaultPackage()
 					&& currentElementPath.segmentCount() != path.segmentCount()-1) {
 						// default package and path is not a direct child
 						this.currentElement = (Openable)this.currentElement.getParent();
@@ -1712,8 +1668,10 @@
 //				}
 				break;
 			case IResourceDelta.CHANGED :
-				if ((delta.getFlags() & IResourceDelta.CONTENT) == 0  // only consider content change
-					&& (delta.getFlags() & IResourceDelta.MOVED_FROM) == 0) {// and also move and overide scenario (see http://dev.eclipse.org/bugs/show_bug.cgi?id=21420)
+				int flags = delta.getFlags();
+				if ((flags & IResourceDelta.CONTENT) == 0  // only consider content change
+					&& (flags & IResourceDelta.ENCODING) == 0 // and encoding change
+					&& (flags & IResourceDelta.MOVED_FROM) == 0) {// and also move and overide scenario (see http://dev.eclipse.org/bugs/show_bug.cgi?id=21420)
 					break;
 				}
 			// fall through
@@ -1731,65 +1689,7 @@
 				}
 		}
 	}
-	/*
-	 * Update the JavaModel according to a .jprefs file change. The file can have changed as a result of a previous
-	 * call to JavaProject#setOptions or as a result of some user update (through repository)
-	 * Unused until preference file get shared (.jpref)
-	 */
-	void reconcilePreferenceFileUpdate(IResourceDelta delta, IFile file, JavaProject project) {
-			
-		switch (delta.getKind()) {
-			case IResourceDelta.REMOVED : // flush project custom settings
-				project.setOptions(null);
-				return;
-			case IResourceDelta.CHANGED :
-				if ((delta.getFlags() & IResourceDelta.CONTENT) == 0  // only consider content change
-						&& (delta.getFlags() & IResourceDelta.MOVED_FROM) == 0) // and also move and overide scenario
-					break;
-				identityCheck : { // check if any actual difference
-					// force to (re)read the property file
-					Preferences filePreferences = project.loadPreferences();
-					if (filePreferences == null){ 
-						project.setOptions(null); // should have got removed delta.
-						return;
-					}
-					Preferences projectPreferences = project.getPreferences();
-					if (projectPreferences == null) return; // not a Java project
-						
-					// compare preferences set to their default
-					String[] defaultProjectPropertyNames = projectPreferences.defaultPropertyNames();
-					String[] defaultFilePropertyNames = filePreferences.defaultPropertyNames();
-					if (defaultProjectPropertyNames.length == defaultFilePropertyNames.length) {
-						for (int i = 0; i < defaultProjectPropertyNames.length; i++){
-							String propertyName = defaultProjectPropertyNames[i];
-							if (!projectPreferences.getString(propertyName).trim().equals(filePreferences.getString(propertyName).trim())){
-								break identityCheck;
-							}
-						}		
-					} else break identityCheck;
 
-					// compare custom preferences not set to their default
-					String[] projectPropertyNames = projectPreferences.propertyNames();
-					String[] filePropertyNames = filePreferences.propertyNames();
-					if (projectPropertyNames.length == filePropertyNames.length) {
-						for (int i = 0; i < projectPropertyNames.length; i++){
-						String propertyName = projectPropertyNames[i];
-							if (!projectPreferences.getString(propertyName).trim().equals(filePreferences.getString(propertyName).trim())){
-								break identityCheck;
-							}
-						}		
-					} else break identityCheck;
-					
-					// identical - do nothing
-					return;
-				}
-			case IResourceDelta.ADDED :
-				// not identical, create delta and reset cached preferences
-				project.setPreferences(null);
-				// create delta
-				//fCurrentDelta.changed(project, IJavaElementDelta.F_OPTIONS_CHANGED);				
-		}
-	}
 	/*
 	 * Traverse the set of projects which have changed namespace, and reset their 
 	 * caches and their dependents
@@ -2272,7 +2172,7 @@
 				}
 				updateIndex(element, delta);
 				elementAdded(element, delta, rootInfo);
-				return false;
+				return elementType == IJavaElement.PACKAGE_FRAGMENT;
 			case IResourceDelta.REMOVED :
 				deltaRes = delta.getResource();
 				element = createElement(deltaRes, elementType, rootInfo);
@@ -2288,11 +2188,11 @@
 					// reset the corresponding project built state, since cannot reuse if added back
 					this.manager.setLastBuiltState((IProject)deltaRes, null /*no state*/);
 				}
-				return false;
+				return elementType == IJavaElement.PACKAGE_FRAGMENT;
 			case IResourceDelta.CHANGED :
 				int flags = delta.getFlags();
-				if ((flags & IResourceDelta.CONTENT) != 0) {
-					// content has changed
+				if ((flags & IResourceDelta.CONTENT) != 0 || (flags & IResourceDelta.ENCODING) != 0) {
+					// content or encoding has changed
 					element = createElement(delta.getResource(), elementType, rootInfo);
 					if (element == null) return false;
 					updateIndex(element, delta);
@@ -2309,14 +2209,23 @@
 						}
 						if (res.isOpen()) {
 							if (JavaProject.hasJavaNature(res)) {
-								elementAdded(element, delta, rootInfo);
+								addToParentInfo(element);
+								currentDelta().opened(element);
+								this.state.updateRoots(element.getPath(), delta, this);
+								
+								// refresh pkg fragment roots and caches of the project (and its dependents)
+								this.rootsToRefresh.add(element);
+								this.projectCachesToReset.add(element);
+								
 								this.manager.indexManager.indexAll(res);
 							}
 						} else {
 							JavaModel javaModel = this.manager.getJavaModel();
 							boolean wasJavaProject = javaModel.findJavaProject(res) != null;
 							if (wasJavaProject) {
-								elementRemoved(element, delta, rootInfo);
+								close(element);
+								removeFromParentInfo(element);
+								currentDelta().closed(element);
 								this.manager.indexManager.discardJobs(element.getElementName());
 								this.manager.indexManager.removeIndexFamily(res.getFullPath());
 							}
@@ -2396,8 +2305,8 @@
 				}
 				int kind = delta.getKind();
 				if (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED) {
-					IPackageFragmentRoot root = (IPackageFragmentRoot)element;
-					this.updateRootIndex(root, root.getPackageFragment(""), delta); //$NON-NLS-1$
+					PackageFragmentRoot root = (PackageFragmentRoot)element;
+					this.updateRootIndex(root, CharOperation.NO_STRINGS, delta);
 					break;
 				}
 				// don't break as packages of the package fragment root can be indexed below
@@ -2407,8 +2316,8 @@
 					case IResourceDelta.REMOVED:
 						IPackageFragment pkg = null;
 						if (element instanceof IPackageFragmentRoot) {
-							IPackageFragmentRoot root = (IPackageFragmentRoot)element;
-							pkg = root.getPackageFragment(""); //$NON-NLS-1$
+							PackageFragmentRoot root = (PackageFragmentRoot)element;
+							pkg = root.getPackageFragment(CharOperation.NO_STRINGS);
 						} else {
 							pkg = (IPackageFragment)element;
 						}
@@ -2420,10 +2329,11 @@
 						for (int i = 0, length = children.length; i < length; i++) {
 							IResourceDelta child = children[i];
 							IResource resource = child.getResource();
+							// TODO (philippe) Why do this? Every child is added anyway as the delta is walked
 							if (resource instanceof IFile) {
 								String name = resource.getName();
 								if (isSource) {
-									if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(name)) {
+									if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(name)) {
 										Openable cu = (Openable)pkg.getCompilationUnit(name);
 										this.updateIndex(cu, child);
 									}
@@ -2452,7 +2362,8 @@
 				switch (delta.getKind()) {
 					case IResourceDelta.CHANGED :
 						// no need to index if the content has not changed
-						if ((delta.getFlags() & IResourceDelta.CONTENT) == 0)
+						int flags = delta.getFlags();
+						if ((flags & IResourceDelta.CONTENT) == 0 && (flags & IResourceDelta.ENCODING) == 0)
 							break;
 					case IResourceDelta.ADDED :
 						indexManager.addBinary(file, binaryFolderPath);
@@ -2467,7 +2378,8 @@
 				switch (delta.getKind()) {
 					case IResourceDelta.CHANGED :
 						// no need to index if the content has not changed
-						if ((delta.getFlags() & IResourceDelta.CONTENT) == 0)
+						int flags = delta.getFlags();
+						if ((flags & IResourceDelta.CONTENT) == 0 && (flags & IResourceDelta.ENCODING) == 0)
 							break;
 					case IResourceDelta.ADDED :
 						indexManager.addSource(file, file.getProject().getFullPath());
@@ -2496,20 +2408,16 @@
 	 * Updates the index of the given root (assuming it's an addition or a removal).
 	 * This is done recusively, pkg being the current package.
 	 */
-	private void updateRootIndex(IPackageFragmentRoot root, IPackageFragment pkg, IResourceDelta delta) {
-		this.updateIndex((Openable)pkg, delta);
+	private void updateRootIndex(PackageFragmentRoot root, String[] pkgName, IResourceDelta delta) {
+		Openable pkg = root.getPackageFragment(pkgName);
+		this.updateIndex(pkg, delta);
 		IResourceDelta[] children = delta.getAffectedChildren();
-		String name = pkg.getElementName();
 		for (int i = 0, length = children.length; i < length; i++) {
 			IResourceDelta child = children[i];
 			IResource resource = child.getResource();
 			if (resource instanceof IFolder) {
-				String subpkgName = 
-					name.length() == 0 ? 
-						resource.getName() : 
-						name + "." + resource.getName(); //$NON-NLS-1$
-				IPackageFragment subpkg = root.getPackageFragment(subpkgName);
-				this.updateRootIndex(root, subpkg, child);
+				String[] subpkgName = Util.arrayConcat(pkgName, resource.getName());
+				this.updateRootIndex(root, subpkgName, child);
 			}
 		}
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ElementCache.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ElementCache.java
index 55a8059..f97c292 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ElementCache.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ElementCache.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.internal.core.util.LRUCache;
 
@@ -17,6 +18,9 @@
  * An LRU cache of <code>JavaElements</code>.
  */
 public class ElementCache extends OverflowingLRUCache {
+	
+	IJavaElement spaceLimitParent = null;
+	
 /**
  * Constructs a new element cache of the given size.
  */
@@ -56,10 +60,38 @@
 		return false;
 	}
 }
-	/**
-	 * Returns a new instance of the reciever.
-	 */
-	protected LRUCache newInstance(int size, int overflow) {
-		return new ElementCache(size, overflow);
+
+/*
+ * Ensures that there is enough room for adding the given number of children.
+ * If the space limit must be increased, record the parent that needed this space limit.
+ */
+protected void ensureSpaceLimit(int childrenSize, IJavaElement parent) {
+	// ensure the children can be put without closing other elements
+	int spaceNeeded = 1 + (int)((1 + fLoadFactor) * (childrenSize + fOverflow));
+	if (fSpaceLimit < spaceNeeded) {
+		// parent is being opened with more children than the space limit
+		shrink(); // remove overflow
+		setSpaceLimit(spaceNeeded); 
+		this.spaceLimitParent = parent;
 	}
 }
+
+/*
+ * If the given parent was the one that increased the space limit, reset
+ * the space limit to the given default value.
+ */
+protected void resetSpaceLimit(int defaultLimit, IJavaElement parent) {
+	if (parent.equals(this.spaceLimitParent)) {
+		setSpaceLimit(defaultLimit);
+		this.spaceLimitParent = null;
+	}
+}
+
+/**
+ * Returns a new instance of the reciever.
+ */
+protected LRUCache newInstance(int size, int overflow) {
+	return new ElementCache(size, overflow);
+}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportContainer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportContainer.java
index 4f3c774..fe7e9ee 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportContainer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportContainer.java
@@ -24,7 +24,7 @@
  */
 public class ImportContainer extends SourceRefElement implements IImportContainer {
 protected ImportContainer(CompilationUnit parent) {
-	super(parent, ""); //$NON-NLS-1$
+	super(parent);
 }
 public boolean equals(Object o) {
 	if (!(o instanceof ImportContainer)) return false;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclaration.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclaration.java
index 99a2bb0..8b29cc5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclaration.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclaration.java
@@ -22,13 +22,15 @@
 
 /* package */ class ImportDeclaration extends SourceRefElement implements IImportDeclaration {
 
-
+	protected String name;
+	
 /**
  * Constructs an ImportDeclaration in the given import container
  * with the given name.
  */
 protected ImportDeclaration(ImportContainer parent, String name) {
-	super(parent, name);
+	super(parent);
+	this.name = name;
 }
 public boolean equals(Object o) {
 	if (!(o instanceof ImportDeclaration)) return false;
@@ -42,6 +44,9 @@
 protected boolean equalsDOMNode(IDOMNode node) {
 	return (node.getNodeType() == IDOMNode.IMPORT) && getElementName().equals(node.getName());
 }
+public String getElementName() {
+	return this.name;
+}
 /**
  * @see IJavaElement
  */
@@ -56,17 +61,16 @@
 	return info.getModifiers();
 }
 /**
- * @see JavaElement#getHandleMemento()
+ * @see JavaElement#getHandleMemento(StringBuffer)
  * For import declarations, the handle delimiter is associated to the import container already
  */
-public String getHandleMemento(){
-	StringBuffer buff= new StringBuffer(((JavaElement)getParent()).getHandleMemento());
+protected void getHandleMemento(StringBuffer buff) {
+	((JavaElement)getParent()).getHandleMemento(buff);
 	escapeMementoName(buff, getElementName());
 	if (this.occurrenceCount > 1) {
 		buff.append(JEM_COUNT);
 		buff.append(this.occurrenceCount);
 	}
-	return buff.toString();
 }
 /**
  * @see JavaElement#getHandleMemento()
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclarationElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclarationElementInfo.java
index 8c48710..12a5372 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclarationElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclarationElementInfo.java
@@ -18,9 +18,14 @@
  */
 public class ImportDeclarationElementInfo extends MemberElementInfo implements ISourceImport{
 	
+	char[] name;
+	
 	// record if import is on demand, the import name doesn't have trailing start
 	boolean onDemand;
 	
+	public char[] getName() {
+		return this.name;
+	}
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.internal.compiler.env.ISourceImport#onDemand()
 	 */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Initializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Initializer.java
index d8254ea..e0d4e91 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Initializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Initializer.java
@@ -28,7 +28,7 @@
 /* package */ class Initializer extends Member implements IInitializer {
 
 protected Initializer(JavaElement parent, int count) {
-	super(parent, ""); //$NON-NLS-1$
+	super(parent);
 	// 0 is not valid: this first occurrence is occurrence 1.
 	if (count <= 0)
 		throw new IllegalArgumentException();
@@ -61,13 +61,12 @@
 	return INITIALIZER;
 }
 /**
- * @see JavaElement#getHandleMemento()
+ * @see JavaElement#getHandleMemento(StringBuffer)
  */
-public String getHandleMemento(){
-	StringBuffer buff= new StringBuffer(((JavaElement)getParent()).getHandleMemento());
+protected void getHandleMemento(StringBuffer buff) {
+	((JavaElement)getParent()).getHandleMemento(buff);
 	buff.append(getHandleMementoDelimiter());
 	buff.append(this.occurrenceCount);
-	return buff.toString();
 }
 /**
  * @see JavaElement#getHandleMemento()
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java
index 207337e..26cbbe6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java
@@ -22,6 +22,7 @@
 import org.eclipse.jdt.core.IJavaModelStatusConstants;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * A package fragment that represents a package fragment found in a JAR.
@@ -32,8 +33,8 @@
 /**
  * Constructs a package fragment that is contained within a jar or a zip.
  */
-protected JarPackageFragment(PackageFragmentRoot root, String name) {
-	super(root, name);
+protected JarPackageFragment(PackageFragmentRoot root, String[] names) {
+	super(root, names);
 }
 /**
  * Compute the children of this package fragment. Children of jar package fragments
@@ -72,10 +73,8 @@
 		for (int i = 0; i < max; i++) {
 			String resName = resNames[i];
 			// consider that a .java file is not a non-java resource (see bug 12246 Packages view shows .class and .java files when JAR has source)
-			if (!resName.toLowerCase().endsWith(SUFFIX_STRING_java)) {
-				if (!this.isDefaultPackage()) {
-					resName = this.getElementName().replace('.', '/') + "/" + resName;//$NON-NLS-1$
-				}
+			if (!Util.isJavaLikeFileName(resName)) {
+				resName = Util.concatWith(this.names, resName, '/');
 				res[index++] = new JarEntryFile(resName, zipName);
 			}
 		} 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java
index e631714..fd2f43b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java
@@ -19,6 +19,9 @@
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * A package fragment root that corresponds to a .jar or .zip.
@@ -32,7 +35,6 @@
  */
 public class JarPackageFragmentRoot extends PackageFragmentRoot {
 	
-	public final static String[] NO_STRINGS = new String[0];
 	public final static ArrayList EMPTY_LIST = new ArrayList();
 	
 	/**
@@ -48,7 +50,7 @@
 	 * does not have an associated <code>IResource</code>.
 	 */
 	protected JarPackageFragmentRoot(IPath jarPath, JavaProject project) {
-		super(null, project, jarPath.lastSegment());
+		super(null, project);
 		this.jarPath = jarPath;
 	}
 	/**
@@ -56,7 +58,7 @@
 	 * based on a JAR file.
 	 */
 	protected JarPackageFragmentRoot(IResource resource, JavaProject project) {
-		super(resource, project, resource.getName());
+		super(resource, project);
 		this.jarPath = resource.getFullPath();
 	}
 
@@ -75,10 +77,10 @@
 		try {
 			jar= getJar();
 	
-			HashMap packageFragToTypes= new HashMap();
+			HashtableOfArrayToObject packageFragToTypes= new HashtableOfArrayToObject();
 	
 			// always create the default package
-			packageFragToTypes.put(IPackageFragment.DEFAULT_PACKAGE_NAME, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
+			packageFragToTypes.put(CharOperation.NO_STRINGS, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
 	
 			for (Enumeration e= jar.entries(); e.hasMoreElements();) {
 				ZipEntry member= (ZipEntry) e.nextElement();
@@ -86,47 +88,16 @@
 	
 				if (member.isDirectory()) {
 					
-					int last = entryName.length() - 1;
-					entryName= entryName.substring(0, last);
-					entryName= entryName.replace('/', '.');
-	
-					// add the package name & all of its parent packages
-					while (true) {
-						// extract the package name
-						if (packageFragToTypes.containsKey(entryName)) break;
-						packageFragToTypes.put(entryName, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
-						
-						if ((last = entryName.lastIndexOf('.')) < 0) break;
-						entryName = entryName.substring(0, last);
-					}
+					initPackageFragToTypes(packageFragToTypes, entryName, entryName.length()-1);
 				} else {
 					//store the class file / non-java rsc entry name to be cached in the appropriate package fragment
 					//zip entries only use '/'
 					int lastSeparator= entryName.lastIndexOf('/');
-					String packageName;
-					String fileName;
-					if (lastSeparator != -1) { //not in the default package
-						entryName= entryName.replace('/', '.');
-						fileName= entryName.substring(lastSeparator + 1);
-						packageName= entryName.substring(0, lastSeparator);
-					} else {
-						fileName = entryName;
-						packageName =  IPackageFragment.DEFAULT_PACKAGE_NAME;
-					}
-					
-					// add the package name & all of its parent packages
-					String currentPackageName = packageName;
-					while (true) {
-						// extract the package name
-						if (packageFragToTypes.containsKey(currentPackageName)) break;
-						packageFragToTypes.put(currentPackageName, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
-						
-						int last;
-						if ((last = currentPackageName.lastIndexOf('.')) < 0) break;
-						currentPackageName = currentPackageName.substring(0, last);
-					}
+					String fileName= entryName.substring(lastSeparator + 1);
+					String[] pkgName = initPackageFragToTypes(packageFragToTypes, entryName, lastSeparator);
+
 					// add classfile info amongst children
-					ArrayList[] children = (ArrayList[]) packageFragToTypes.get(packageName);
+					ArrayList[] children = (ArrayList[]) packageFragToTypes.get(pkgName);
 					if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entryName)) {
 						if (children[JAVA] == EMPTY_LIST) children[JAVA] = new ArrayList();
 						children[JAVA].add(fileName);
@@ -138,16 +109,16 @@
 			}
 			//loop through all of referenced packages, creating package fragments if necessary
 			// and cache the entry names in the infos created for those package fragments
-			Iterator packages = packageFragToTypes.keySet().iterator();
-			while (packages.hasNext()) {
-				String packName = (String) packages.next();
+			for (int i = 0, length = packageFragToTypes.keyTable.length; i < length; i++) {
+				String[] pkgName = (String[]) packageFragToTypes.keyTable[i];
+				if (pkgName == null) continue;
 				
-				ArrayList[] entries= (ArrayList[]) packageFragToTypes.get(packName);
-				JarPackageFragment packFrag= (JarPackageFragment) getPackageFragment(packName);
+				ArrayList[] entries= (ArrayList[]) packageFragToTypes.get(pkgName);
+				JarPackageFragment packFrag= (JarPackageFragment) getPackageFragment(pkgName);
 				JarPackageFragmentInfo fragInfo= new JarPackageFragmentInfo();
 				int resLength= entries[NON_JAVA].size();
 				if (resLength == 0) {
-					packFrag.computeNonJavaResources(NO_STRINGS, fragInfo, jar.getName());
+					packFrag.computeNonJavaResources(CharOperation.NO_STRINGS, fragInfo, jar.getName());
 				} else {
 					String[] resNames= new String[resLength];
 					entries[NON_JAVA].toArray(resNames);
@@ -170,7 +141,7 @@
 		info.setChildren(children);
 		return true;
 	}
-/**
+	/**
 	 * Returns a new element info for this element.
 	 */
 	protected Object createElementInfo() {
@@ -198,6 +169,9 @@
 		}
 		return false;
 	}
+	public String getElementName() {
+		return this.jarPath.lastSegment();
+	}
 	/**
 	 * Returns the underlying ZipFile for this Jar package fragment root.
 	 *
@@ -217,14 +191,10 @@
 	 */
 	public Object[] getNonJavaResources() throws JavaModelException {
 		// We want to show non java resources of the default package at the root (see PR #1G58NB8)
-		return ((JarPackageFragment) this.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME)).storedNonJavaResources();
+		return ((JarPackageFragment) getPackageFragment(CharOperation.NO_STRINGS)).storedNonJavaResources();
 	}
-	/**
-	 * @see IPackageFragmentRoot
-	 */
-	public IPackageFragment getPackageFragment(String packageName) {
-
-		return new JarPackageFragment(this, packageName);
+	public PackageFragment getPackageFragment(String[] pkgName) {
+		return new JarPackageFragment(this, pkgName);
 	}
 	/**
 	 * @see IPackageFragmentRoot
@@ -263,6 +233,25 @@
 	public int hashCode() {
 		return this.jarPath.hashCode();
 	}
+	private String[] initPackageFragToTypes(HashtableOfArrayToObject packageFragToTypes, String entryName, int lastSeparator) {
+		String[] pkgName = Util.splitOn('/', entryName, 0, lastSeparator);
+		String[] existing = null;
+		int length = pkgName.length;
+		int existingLength = length;
+		while (existingLength >= 0) {
+			existing = (String[]) packageFragToTypes.getKey(pkgName, existingLength);
+			if (existing != null) break;
+			existingLength--;
+		}
+		JavaModelManager manager = JavaModelManager.getJavaModelManager();
+		for (int i = existingLength; i < length; i++) {
+			System.arraycopy(existing, 0, existing = new String[i+1], 0, i);
+			existing[i] = manager.intern(pkgName[i]);
+			packageFragToTypes.put(existing, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
+		}
+		
+		return existing;
+	}
 	/**
 	 * @see IPackageFragmentRoot
 	 */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
new file mode 100644
index 0000000..000cfa5
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import java.util.*;
+
+import org.eclipse.core.runtime.preferences.*;
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+
+/**
+ * JavaCore eclipse preferences initializer.
+ * Initially done in JavaCore.initializeDefaultPreferences which was deprecated
+ * with new eclipse preferences mechanism.
+ */
+public class JavaCorePreferenceInitializer extends AbstractPreferenceInitializer {
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+	 */
+	public void initializeDefaultPreferences() {
+
+		// Get options names set
+		HashSet optionNames = JavaModelManager.getJavaModelManager().optionNames;
+		
+		// Compiler settings
+		Map defaultOptionsMap = new CompilerOptions().getMap(); // compiler defaults
+		
+		// Override some compiler defaults
+		defaultOptionsMap.put(JavaCore.COMPILER_LOCAL_VARIABLE_ATTR, JavaCore.GENERATE);
+		defaultOptionsMap.put(JavaCore.COMPILER_CODEGEN_UNUSED_LOCAL, JavaCore.PRESERVE);
+		defaultOptionsMap.put(JavaCore.COMPILER_TASK_TAGS, JavaCore.DEFAULT_TASK_TAGS);
+		defaultOptionsMap.put(JavaCore.COMPILER_TASK_PRIORITIES, JavaCore.DEFAULT_TASK_PRIORITIES);
+		defaultOptionsMap.put(JavaCore.COMPILER_TASK_CASE_SENSITIVE, JavaCore.ENABLED);
+		defaultOptionsMap.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED);
+	
+		// Builder settings
+		defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, ""); //$NON-NLS-1$
+		defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_INVALID_CLASSPATH, JavaCore.ABORT); 
+		defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE, JavaCore.WARNING); 
+		defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER, JavaCore.CLEAN); 
+
+		// JavaCore settings
+		defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_ORDER, JavaCore.IGNORE); 
+		defaultOptionsMap.put(JavaCore.CORE_INCOMPLETE_CLASSPATH, JavaCore.ERROR); 
+		defaultOptionsMap.put(JavaCore.CORE_CIRCULAR_CLASSPATH, JavaCore.ERROR); 
+		defaultOptionsMap.put(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, JavaCore.IGNORE); 
+		defaultOptionsMap.put(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, JavaCore.ENABLED); 
+		defaultOptionsMap.put(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, JavaCore.ENABLED); 
+
+		// encoding setting comes from resource plug-in
+		optionNames.add(JavaCore.CORE_ENCODING);
+
+		// Formatter settings
+		formatterSettings(defaultOptionsMap, optionNames);
+
+		// CodeAssist settings
+		defaultOptionsMap.put(JavaCore.CODEASSIST_VISIBILITY_CHECK, JavaCore.DISABLED); //$NON-NLS-1$
+		defaultOptionsMap.put(JavaCore.CODEASSIST_IMPLICIT_QUALIFICATION, JavaCore.DISABLED); //$NON-NLS-1$
+		defaultOptionsMap.put(JavaCore.CODEASSIST_FIELD_PREFIXES, ""); //$NON-NLS-1$
+		defaultOptionsMap.put(JavaCore.CODEASSIST_STATIC_FIELD_PREFIXES, ""); //$NON-NLS-1$
+		defaultOptionsMap.put(JavaCore.CODEASSIST_LOCAL_PREFIXES, ""); //$NON-NLS-1$
+		defaultOptionsMap.put(JavaCore.CODEASSIST_ARGUMENT_PREFIXES, ""); //$NON-NLS-1$
+		defaultOptionsMap.put(JavaCore.CODEASSIST_FIELD_SUFFIXES, ""); //$NON-NLS-1$
+		defaultOptionsMap.put(JavaCore.CODEASSIST_STATIC_FIELD_SUFFIXES, ""); //$NON-NLS-1$
+		defaultOptionsMap.put(JavaCore.CODEASSIST_LOCAL_SUFFIXES, ""); //$NON-NLS-1$
+		defaultOptionsMap.put(JavaCore.CODEASSIST_ARGUMENT_SUFFIXES, ""); //$NON-NLS-1$
+		defaultOptionsMap.put(JavaCore.CODEASSIST_RESTRICTIONS_CHECK, JavaCore.DISABLED); //$NON-NLS-1$
+		
+		// Store default values to default preferences
+	 	IEclipsePreferences defaultPreferences = new DefaultScope().getNode(JavaCore.PLUGIN_ID);
+		for (Iterator iter = defaultOptionsMap.entrySet().iterator(); iter.hasNext();) {
+			Map.Entry entry = (Map.Entry) iter.next();
+			String optionName = (String) entry.getKey();
+			defaultPreferences.put(optionName, (String)entry.getValue());
+			optionNames.add(optionName);
+		}
+	}
+	
+	/**
+	 * Avoid depraction warnings on formatter settings
+	 * @deprecated
+	 */
+	private void formatterSettings(Map defaultOptionsMap, HashSet optionNames) {
+		Map codeFormatterOptionsMap = DefaultCodeFormatterConstants.getJavaConventionsSettings(); // code formatter defaults
+		for (Iterator iter = codeFormatterOptionsMap.entrySet().iterator(); iter.hasNext();) {
+			Map.Entry entry = (Map.Entry) iter.next();
+			String optionName = (String) entry.getKey();
+			defaultOptionsMap.put(optionName, entry.getValue());
+			optionNames.add(optionName);
+		}		
+		defaultOptionsMap.put(JavaCore.FORMATTER_NEWLINE_OPENING_BRACE, JavaCore.DO_NOT_INSERT); 
+		defaultOptionsMap.put(JavaCore.FORMATTER_NEWLINE_CONTROL, JavaCore.DO_NOT_INSERT);
+		defaultOptionsMap.put(JavaCore.FORMATTER_CLEAR_BLANK_LINES, JavaCore.PRESERVE_ONE); 
+		defaultOptionsMap.put(JavaCore.FORMATTER_NEWLINE_ELSE_IF, JavaCore.DO_NOT_INSERT);
+		defaultOptionsMap.put(JavaCore.FORMATTER_NEWLINE_EMPTY_BLOCK, JavaCore.INSERT); 
+		defaultOptionsMap.put(JavaCore.FORMATTER_LINE_SPLIT, "80"); //$NON-NLS-1$
+		defaultOptionsMap.put(JavaCore.FORMATTER_COMPACT_ASSIGNMENT, JavaCore.NORMAL); 
+		defaultOptionsMap.put(JavaCore.FORMATTER_TAB_CHAR, JavaCore.TAB); 
+		defaultOptionsMap.put(JavaCore.FORMATTER_TAB_SIZE, "4"); //$NON-NLS-1$ 
+		defaultOptionsMap.put(JavaCore.FORMATTER_SPACE_CASTEXPRESSION, JavaCore.INSERT); //$NON-NLS-1$ 
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
index 821f298..ee45232 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
@@ -42,16 +42,7 @@
 	public static final char JEM_IMPORTDECLARATION = '#';
 	public static final char JEM_COUNT = '!';
 	public static final char JEM_LOCALVARIABLE = '@';
-
-	/**
-	 * A count to uniquely identify this element in the case
-	 * that a duplicate named element exists. For example, if
-	 * there are two fields in a compilation unit with the
-	 * same name, the occurrence count is used to distinguish
-	 * them.  The occurrence count starts at 1 (thus the first 
-	 * occurrence is occurrence 1, not occurrence 0).
-	 */
-	public int occurrenceCount = 1;
+	public static final char JEM_TYPE_PARAMETER = ']';
 
 	/**
 	 * This element's parent, or <code>null</code> if this
@@ -59,29 +50,21 @@
 	 */
 	protected JavaElement parent;
 
-	/**
-	 * This element's name, or an empty <code>String</code> if this
-	 * element does not have a name.
-	 */
-	protected String name;
-
 	protected static final JavaElement[] NO_ELEMENTS = new JavaElement[0];
 	protected static final Object NO_INFO = new Object();
 	
 	/**
 	 * Constructs a handle for a java element with
-	 * the given parent element and name.
+	 * the given parent element.
 	 *
 	 * @param parent The parent of java element
-	 * @param name The name of java element
 	 *
 	 * @exception IllegalArgumentException if the type is not one of the valid
 	 *		Java element type constants
 	 *
 	 */
-	protected JavaElement(JavaElement parent, String name) throws IllegalArgumentException {
+	protected JavaElement(JavaElement parent) throws IllegalArgumentException {
 		this.parent = parent;
-		this.name = name;
 	}
 	/**
 	 * @see IOpenable
@@ -117,8 +100,7 @@
 	
 		// assume instanceof check is done in subclass
 		JavaElement other = (JavaElement) o;		
-		return this.occurrenceCount == other.occurrenceCount &&
-				this.name.equals(other.name) &&
+		return getElementName().equals(other.getElementName()) &&
 				this.parent.equals(other.parent);
 	}
 	/**
@@ -312,7 +294,7 @@
 	 * @see IAdaptable
 	 */
 	public String getElementName() {
-		return this.name;
+		return ""; //$NON-NLS-1$
 	}
 	/*
 	 * Creates a Java element handle from the given memento.
@@ -329,16 +311,6 @@
 		String token = memento.nextToken();
 		return getHandleFromMemento(token, memento, owner);
 	}
-	/*
-	 * Update the occurence count of the receiver and creates a Java element handle from the given memento.
-	 * The given working copy owner is used only for compilation unit handles.
-	 */
-	public IJavaElement getHandleUpdatingCountFromMemento(MementoTokenizer memento, WorkingCopyOwner owner) {
-		this.occurrenceCount = Integer.parseInt(memento.nextToken());
-		if (!memento.hasMoreTokens()) return this;
-		String token = memento.nextToken();
-		return getHandleFromMemento(token, memento, owner);
-	}
 	/**
 	 * @see IJavaElement
 	 */
@@ -349,14 +321,14 @@
 	 * @see JavaElement#getHandleMemento()
 	 */
 	public String getHandleMemento(){
-		StringBuffer buff= new StringBuffer(((JavaElement)getParent()).getHandleMemento());
+		StringBuffer buff = new StringBuffer();
+		getHandleMemento(buff);
+		return buff.toString();
+	}
+	protected void getHandleMemento(StringBuffer buff) {
+		((JavaElement)getParent()).getHandleMemento(buff);
 		buff.append(getHandleMementoDelimiter());
 		escapeMementoName(buff, getElementName());
-		if (this.occurrenceCount > 1) {
-			buff.append(JEM_COUNT);
-			buff.append(this.occurrenceCount);
-		}
-		return buff.toString();
 	}
 	/**
 	 * Returns the <code>char</code> that marks the start of this handles
@@ -528,7 +500,7 @@
 	 */
 	public int hashCode() {
 		if (this.parent == null) return super.hashCode();
-		return Util.combineHashCodes(this.name.hashCode(), this.parent.hashCode());
+		return Util.combineHashCodes(getElementName().hashCode(), this.parent.hashCode());
 	}
 	/**
 	 * Returns true if this element is an ancestor of the given element,
@@ -549,16 +521,19 @@
 		return false;
 	}
 	/**
-	 * @see IJavaElement
+	 * Creates and returns a new not present exception for this element.
 	 */
-	public boolean isStructureKnown() throws JavaModelException {
-		return ((JavaElementInfo)getElementInfo()).isStructureKnown();
+	public JavaModelException newNotPresentException() {
+		return new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
 	}
 	/**
-	 * Creates and returns and not present exception for this element.
+	 * Creates and returns a new Java model exception for this element with the given status.
 	 */
-	protected JavaModelException newNotPresentException() {
-		return new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
+	public JavaModelException newJavaModelException(IStatus status) {
+		if (status instanceof IJavaModelStatus)
+			return new JavaModelException((IJavaModelStatus) status);
+		else
+			return new JavaModelException(new JavaModelStatus(status.getSeverity(), status.getCode(), status.getMessage()));
 	}
 	/*
 	 * Opens an <code>Openable</code> that is known to be closed (no check for <code>isOpen()</code>).
@@ -684,9 +659,5 @@
 	 */
 	protected void toStringName(StringBuffer buffer) {
 		buffer.append(getElementName());
-		if (this.occurrenceCount > 1) {
-			buffer.append("#"); //$NON-NLS-1$
-			buffer.append(this.occurrenceCount);
-		}
 	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDeltaBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDeltaBuilder.java
index f2a9e32..a758050 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDeltaBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDeltaBuilder.java
@@ -142,6 +142,19 @@
 		this.delta.contentChanged();
 	}
 }
+private boolean equals(char[][][] first, char[][][] second) {
+	if (first == second)
+		return true;
+	if (first == null || second == null)
+		return false;
+	if (first.length != second.length)
+		return false;
+
+	for (int i = first.length; --i >= 0;)
+		if (!CharOperation.equals(first[i], second[i]))
+			return false;
+	return true;
+}
 /**
  * Finds elements which have been added or changed.
  */
@@ -216,9 +229,11 @@
 		if (((MemberElementInfo)oldInfo).getModifiers() != ((MemberElementInfo)newInfo).getModifiers()) {
 			this.delta.changed(newElement, IJavaElementDelta.F_MODIFIERS);
 		} else if (oldInfo instanceof SourceMethodElementInfo && newInfo instanceof SourceMethodElementInfo) {
-			if (!CharOperation.equals(
-					((SourceMethodElementInfo)oldInfo).getReturnTypeName(), 
-					((SourceMethodElementInfo)newInfo).getReturnTypeName())) {
+			SourceMethodElementInfo oldSourceMethodInfo = (SourceMethodElementInfo)oldInfo;
+			SourceMethodElementInfo newSourceMethodInfo = (SourceMethodElementInfo)newInfo;
+			if (!CharOperation.equals(oldSourceMethodInfo.getReturnTypeName(), newSourceMethodInfo.getReturnTypeName())
+					|| !CharOperation.equals(oldSourceMethodInfo.getTypeParameterNames(), newSourceMethodInfo.getTypeParameterNames())
+					|| !equals(oldSourceMethodInfo.getTypeParameterBounds(), newSourceMethodInfo.getTypeParameterBounds())) {
 				this.delta.changed(newElement, IJavaElementDelta.F_CONTENT);
 			}
 		} else if (oldInfo instanceof SourceFieldElementInfo && newInfo instanceof SourceFieldElementInfo) {
@@ -233,9 +248,13 @@
 		SourceTypeElementInfo oldSourceTypeInfo = (SourceTypeElementInfo)oldInfo;
 		SourceTypeElementInfo newSourceTypeInfo = (SourceTypeElementInfo)newInfo;
 		if (!CharOperation.equals(oldSourceTypeInfo.getSuperclassName(), newSourceTypeInfo.getSuperclassName()) 
-			|| !CharOperation.equals(oldSourceTypeInfo.getInterfaceNames(), newSourceTypeInfo.getInterfaceNames())) {
+				|| !CharOperation.equals(oldSourceTypeInfo.getInterfaceNames(), newSourceTypeInfo.getInterfaceNames())) {
 			this.delta.changed(newElement, IJavaElementDelta.F_SUPER_TYPES);
 		}
+		if (!CharOperation.equals(oldSourceTypeInfo.getTypeParameterNames(), newSourceTypeInfo.getTypeParameterNames())
+				|| !equals(oldSourceTypeInfo.getTypeParameterBounds(), newSourceTypeInfo.getTypeParameterBounds())) {
+			this.delta.changed(newElement, IJavaElementDelta.F_CONTENT);
+		}
 	}
 }
 /**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementInfo.java
index ed0dc11..38a4fda 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementInfo.java
@@ -26,12 +26,6 @@
 	protected IJavaElement[] children;
 
 	/**
-	 * Is the structure of this element known
-	 * @see IJavaElement#isStructureKnown()
-	 */
-	protected boolean isStructureKnown = false;
-
-	/**
 	 * Shared empty collection used for efficiency.
 	 */
 	static Object[] NO_NON_JAVA_RESOURCES = new Object[] {};	
@@ -83,12 +77,6 @@
 		return false;
 	}
 	/**
-	 * @see IJavaElement#isStructureKnown()
-	 */
-	public boolean isStructureKnown() {
-		return this.isStructureKnown;
-	}
-	/**
 	 * Returns an array with all the same elements as the specified array except for
 	 * the element to remove. Assumes that the deletion is contained in the array.
 	 */
@@ -115,11 +103,4 @@
 	public void setChildren(IJavaElement[] children) {
 		this.children = children;
 	}
-	/**
-	 * Sets whether the structure of this element known
-	 * @see IJavaElement#isStructureKnown()
-	 */
-	public void setIsStructureKnown(boolean newIsStructureKnown) {
-		this.isStructureKnown = newIsStructureKnown;
-	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java
index 193a5b4..d64ce12 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java
@@ -59,7 +59,7 @@
  * @exception Error if called more than once
  */
 protected JavaModel() throws Error {
-	super(null, "" /*workspace has empty name*/); //$NON-NLS-1$
+	super(null);
 }
 protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource)	/*throws JavaModelException*/ {
 
@@ -167,9 +167,8 @@
  */
 public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner owner) {
 	switch (token.charAt(0)) {
-		case JEM_COUNT:
-			return getHandleUpdatingCountFromMemento(memento, owner);
 		case JEM_JAVAPROJECT:
+			if (!memento.hasMoreTokens()) return this;
 			String projectName = memento.nextToken();
 			JavaElement project = (JavaElement)getJavaProject(projectName);
 			return project.getHandleFromMemento(memento, owner);
@@ -177,10 +176,10 @@
 	return null;
 }
 /**
- * @see JavaElement#getHandleMemento()
+ * @see JavaElement#getHandleMemento(StringBuffer)
  */
-public String getHandleMemento(){
-	return getElementName();
+protected void getHandleMemento(StringBuffer buff) {
+	buff.append(getElementName());
 }
 /**
  * Returns the <code>char</code> that marks the start of this handles
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelCache.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelCache.java
index c7699bc..1576469 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelCache.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelCache.java
@@ -9,7 +9,9 @@
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
+import java.text.NumberFormat;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
 
 import org.eclipse.jdt.core.IJavaElement;
@@ -18,8 +20,12 @@
  * The cache of java elements to their respective info.
  */
 public class JavaModelCache {
-	public static final int PKG_CACHE_SIZE = 500;
-	public static final int OPENABLE_CACHE_SIZE = 2000;
+	public static final int BASE_VALUE = 20;
+	public static final int DEFAULT_PROJECT_SIZE = 5;  // average 25552 bytes per project.
+	public static final int DEFAULT_ROOT_SIZE = BASE_VALUE*10; // average 2590 bytes per root -> maximum size : 25900*BASE_VALUE bytes
+	public static final int DEFAULT_PKG_SIZE = BASE_VALUE*100; // average 1782 bytes per pkg -> maximum size : 178200*BASE_VALUE bytes
+	public static final int DEFAULT_OPENABLE_SIZE = BASE_VALUE*100; // average 6629 bytes per openable (includes children) -> maximum size : 662900*BASE_VALUE bytes
+	public static final int DEFAULT_CHILDREN_SIZE = BASE_VALUE*100*20; // average 20 children per openable
 	
 	/**
 	 * Active Java Model Info
@@ -27,19 +33,24 @@
 	protected JavaModelInfo modelInfo;
 	
 	/**
-	 * Cache of open projects and package fragment roots.
+	 * Cache of open projects.
 	 */
-	protected Map projectAndRootCache;
+	protected HashMap projectCache;
+	
+	/**
+	 * Cache of open package fragment roots.
+	 */
+	protected ElementCache rootCache;
 	
 	/**
 	 * Cache of open package fragments
 	 */
-	protected Map pkgCache;
+	protected ElementCache pkgCache;
 
 	/**
 	 * Cache of open compilation unit and class files
 	 */
-	protected OverflowingLRUCache openableCache;
+	protected ElementCache openableCache;
 
 	/**
 	 * Cache of open children of openable Java Model Java elements
@@ -47,19 +58,66 @@
 	protected Map childrenCache;
 	
 public JavaModelCache() {
-	this.projectAndRootCache = new HashMap(50);
-	this.pkgCache = new HashMap(PKG_CACHE_SIZE);
-	this.openableCache = new ElementCache(OPENABLE_CACHE_SIZE);
-	this.childrenCache = new HashMap(OPENABLE_CACHE_SIZE*20); // average 20 chilren per openable
+	this.projectCache = new HashMap(DEFAULT_PROJECT_SIZE); // NB: Don't use a LRUCache for projects as they are constantly reopened (e.g. during delta processing)
+	this.rootCache = new ElementCache(DEFAULT_ROOT_SIZE);
+	this.pkgCache = new ElementCache(DEFAULT_PKG_SIZE);
+	this.openableCache = new ElementCache(DEFAULT_OPENABLE_SIZE);
+	this.childrenCache = new HashMap(DEFAULT_CHILDREN_SIZE);
 }
 
-public double openableFillingRatio() {
-	return this.openableCache.fillingRatio();
+/*
+ * Ensures there is enough room in each ElementCache to put the given new elements.
+ */
+protected void ensureSpaceLimit(Map newElements) {
+	int rootSize = 0;
+	IJavaElement project = null;
+	int pkgSize = 0;
+	IJavaElement root = null;
+	int openableSize = 0;
+	IJavaElement pkg = null;
+	Iterator iterator = newElements.keySet().iterator();
+	while (iterator.hasNext()) {
+		IJavaElement element = (IJavaElement) iterator.next();
+		switch (element.getElementType()) {
+			case IJavaElement.PACKAGE_FRAGMENT_ROOT:
+				project = element.getParent();
+				rootSize++;
+				break;
+			case IJavaElement.PACKAGE_FRAGMENT:
+				root = element.getParent();
+				pkgSize++;
+				break;
+			case IJavaElement.COMPILATION_UNIT:
+			case IJavaElement.CLASS_FILE:
+				pkg = element.getParent();
+				openableSize++;
+				break;
+		}
+	}
+	this.rootCache.ensureSpaceLimit(rootSize, project);
+	this.pkgCache.ensureSpaceLimit(pkgSize, root);
+	this.openableCache.ensureSpaceLimit(openableSize, pkg);
 }
-public int pkgSize() {
-	return this.pkgCache.size();
+
+/*
+ * The given element is being removed.
+ * Ensures that the corresponding children cache's space limit is reset if this was the parent
+ * that increased the space limit.
+ */
+protected void resetSpaceLimit(IJavaElement element) {
+	switch (element.getElementType()) {
+		case IJavaElement.JAVA_PROJECT:
+			this.rootCache.resetSpaceLimit(DEFAULT_ROOT_SIZE, element);
+			break;
+		case IJavaElement.PACKAGE_FRAGMENT_ROOT:
+			this.pkgCache.resetSpaceLimit(DEFAULT_PKG_SIZE, element);
+			break;
+		case IJavaElement.PACKAGE_FRAGMENT:
+			this.openableCache.resetSpaceLimit(DEFAULT_OPENABLE_SIZE, element);
+			break;
+	}
 }
-	
+		
 /**
  *  Returns the info for the element.
  */
@@ -68,8 +126,9 @@
 		case IJavaElement.JAVA_MODEL:
 			return this.modelInfo;
 		case IJavaElement.JAVA_PROJECT:
+			return this.projectCache.get(element);
 		case IJavaElement.PACKAGE_FRAGMENT_ROOT:
-			return this.projectAndRootCache.get(element);
+			return this.rootCache.get(element);
 		case IJavaElement.PACKAGE_FRAGMENT:
 			return this.pkgCache.get(element);
 		case IJavaElement.COMPILATION_UNIT:
@@ -89,10 +148,11 @@
 		case IJavaElement.JAVA_MODEL:
 			return this.modelInfo;
 		case IJavaElement.JAVA_PROJECT:
+			return this.projectCache.get(element);
 		case IJavaElement.PACKAGE_FRAGMENT_ROOT:
-			return this.projectAndRootCache.get(element);
+			return this.rootCache.peek(element);
 		case IJavaElement.PACKAGE_FRAGMENT:
-			return this.pkgCache.get(element);
+			return this.pkgCache.peek(element);
 		case IJavaElement.COMPILATION_UNIT:
 		case IJavaElement.CLASS_FILE:
 			return this.openableCache.peek(element);
@@ -110,8 +170,10 @@
 			this.modelInfo = (JavaModelInfo) info;
 			break;
 		case IJavaElement.JAVA_PROJECT:
+			this.projectCache.put(element, info);
+			break;
 		case IJavaElement.PACKAGE_FRAGMENT_ROOT:
-			this.projectAndRootCache.put(element, info);
+			this.rootCache.put(element, info);
 			break;
 		case IJavaElement.PACKAGE_FRAGMENT:
 			this.pkgCache.put(element, info);
@@ -133,8 +195,10 @@
 			this.modelInfo = null;
 			break;
 		case IJavaElement.JAVA_PROJECT:
+			this.projectCache.remove(element);
+			break;
 		case IJavaElement.PACKAGE_FRAGMENT_ROOT:
-			this.projectAndRootCache.remove(element);
+			this.rootCache.remove(element);
 			break;
 		case IJavaElement.PACKAGE_FRAGMENT:
 			this.pkgCache.remove(element);
@@ -147,4 +211,24 @@
 			this.childrenCache.remove(element);
 	}
 }
+public String toStringFillingRation(String prefix) {
+	StringBuffer buffer = new StringBuffer();
+	buffer.append(prefix);
+	buffer.append("Project cache: "); //$NON-NLS-1$
+	buffer.append(this.projectCache.size());
+	buffer.append(" projects\n"); //$NON-NLS-1$
+	buffer.append(prefix);
+	buffer.append("Root cache: "); //$NON-NLS-1$
+	buffer.append(NumberFormat.getInstance().format(this.rootCache.fillingRatio()));
+	buffer.append("%\n"); //$NON-NLS-1$
+	buffer.append(prefix);
+	buffer.append("Package cache: "); //$NON-NLS-1$
+	buffer.append(NumberFormat.getInstance().format(this.pkgCache.fillingRatio()));
+	buffer.append("%\n"); //$NON-NLS-1$
+	buffer.append(prefix);
+	buffer.append("Openable cache: "); //$NON-NLS-1$
+	buffer.append(NumberFormat.getInstance().format(this.openableCache.fillingRatio()));
+	buffer.append("%\n"); //$NON-NLS-1$
+	return buffer.toString();
+}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
index 5b7f53f..d278e17 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
@@ -11,7 +11,6 @@
 package org.eclipse.jdt.internal.core;
 
 import java.io.*;
-import java.text.NumberFormat;
 import java.util.*;
 import java.util.zip.ZipFile;
 
@@ -21,18 +20,22 @@
 
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
 import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.IProblem;
-import org.eclipse.jdt.core.search.SearchEngine;
 import org.eclipse.jdt.internal.codeassist.CompletionEngine;
 import org.eclipse.jdt.internal.codeassist.SelectionEngine;
 import org.eclipse.jdt.internal.compiler.Compiler;
+import org.eclipse.jdt.internal.compiler.util.WeakHashSet;
 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.SearchBasicEngine;
 import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
 import org.eclipse.jdt.internal.core.util.Util;
+import org.osgi.service.prefs.BackingStoreException;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
@@ -73,6 +76,12 @@
 	 * A HashSet that contains the IJavaProject whose classpath is being resolved.
 	 */
 	private ThreadLocal classpathsBeingResolved = new ThreadLocal();
+	
+	/*
+	 * A pool of symbols used in the Java model.
+	 * Used as a replacement for String#intern() that could prevent garbage collection of strings on some VMs.
+	 */
+	private WeakHashSet symbols = new WeakHashSet(5);
 
 	public final static String CP_VARIABLE_PREFERENCES_PREFIX = JavaCore.PLUGIN_ID+".classpathVariable."; //$NON-NLS-1$
 	public final static String CP_CONTAINER_PREFERENCES_PREFIX = JavaCore.PLUGIN_ID+".classpathContainer."; //$NON-NLS-1$
@@ -117,6 +126,7 @@
 	private static final String POST_ACTION_DEBUG = JavaCore.PLUGIN_ID + "/debug/postaction" ; //$NON-NLS-1$
 	private static final String BUILDER_DEBUG = JavaCore.PLUGIN_ID + "/debug/builder" ; //$NON-NLS-1$
 	private static final String COMPLETION_DEBUG = JavaCore.PLUGIN_ID + "/debug/completion" ; //$NON-NLS-1$
+	private static final String RESOLUTION_DEBUG = JavaCore.PLUGIN_ID + "/debug/resolution" ; //$NON-NLS-1$
 	private static final String SELECTION_DEBUG = JavaCore.PLUGIN_ID + "/debug/selection" ; //$NON-NLS-1$
 	private static final String SEARCH_DEBUG = JavaCore.PLUGIN_ID + "/debug/search" ; //$NON-NLS-1$
 
@@ -318,7 +328,7 @@
 	
 		if (file.getFileExtension() != null) {
 			String name = file.getName();
-			if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(name))
+			if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(name))
 				return createCompilationUnitFrom(file, project);
 			if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(name))
 				return createClassFileFrom(file, project);
@@ -371,8 +381,8 @@
 		if (pkg == null) {
 			// fix for 1FVS7WE
 			// not on classpath - make the root its folder, and a default package
-			IPackageFragmentRoot root = project.getPackageFragmentRoot(file.getParent());
-			pkg = root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
+			PackageFragmentRoot root = (PackageFragmentRoot) project.getPackageFragmentRoot(file.getParent());
+			pkg = root.getPackageFragment(CharOperation.NO_STRINGS);
 		}
 		return pkg.getClassFile(file.getName());
 	}
@@ -446,7 +456,7 @@
 		IPath resourcePath = resource.getFullPath();
 		try {
 			IClasspathEntry[] entries = 
-				org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(resourcePath.lastSegment())
+				org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(resourcePath.lastSegment())
 					? project.getRawClasspath() // JAVA file can only live inside SRC folder (on the raw path)
 					: ((JavaProject)project).getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
 				
@@ -460,7 +470,7 @@
 					// allow creation of package fragment if it contains a .java file that is included
 					if (!Util.isExcluded(resource, ((ClasspathEntry)entry).fullInclusionPatternChars(), ((ClasspathEntry)entry).fullExclusionPatternChars())) {
 						// given we have a resource child of the root, it cannot be a JAR pkg root
-						IPackageFragmentRoot root = ((JavaProject) project).getFolderPackageFragmentRoot(rootPath);
+						PackageFragmentRoot root =(PackageFragmentRoot) ((JavaProject) project).getFolderPackageFragmentRoot(rootPath);
 						if (root == null) return null;
 						IPath pkgPath = resourcePath.removeFirstSegments(rootPath.segmentCount());
 	
@@ -469,8 +479,8 @@
 							// is the file name in the package
 							pkgPath = pkgPath.removeLastSegments(1);
 						}
-						String pkgName = Util.packageName(pkgPath);
-						if (pkgName == null || JavaConventions.validatePackageName(pkgName).getSeverity() == IStatus.ERROR) {
+						String[] pkgName = pkgPath.segments();
+						if (pkgName == null || JavaConventions.validatePackageName(Util.packageName(pkgPath)).getSeverity() == IStatus.ERROR) {
 							return null;
 						}
 						return root.getPackageFragment(pkgName);
@@ -536,7 +546,8 @@
 		public IClasspathEntry[] resolvedClasspath;
 		public Map resolvedPathToRawEntries; // reverse map from resolved path to raw entries
 		public IPath outputLocation;
-		public Preferences preferences;
+		
+		public IEclipsePreferences preferences;
 		
 		public PerProjectInfo(IProject project) {
 
@@ -616,7 +627,7 @@
 		public String toString() {
 			StringBuffer buffer = new StringBuffer();
 			buffer.append("Info for "); //$NON-NLS-1$
-			buffer.append(((JavaElement)workingCopy).toStringWithAncestors());
+			buffer.append(((JavaElement)this.workingCopy).toStringWithAncestors());
 			buffer.append("\nUse count = "); //$NON-NLS-1$
 			buffer.append(this.useCount);
 			buffer.append("\nProblem requestor:\n  "); //$NON-NLS-1$
@@ -639,13 +650,12 @@
 	/**
 	 * Update the classpath variable cache
 	 */
-	public static class PluginPreferencesListener implements Preferences.IPropertyChangeListener {
+	public static class EclipsePreferencesListener implements IEclipsePreferences.IPreferenceChangeListener {
 		/**
-		 * @see org.eclipse.core.runtime.Preferences.IPropertyChangeListener#propertyChange(Preferences.PropertyChangeEvent)
+		 * @see org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener#preferenceChange(org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent)
 		 */
-		public void propertyChange(Preferences.PropertyChangeEvent event) {
-
-			String propertyName = event.getProperty();
+		public void preferenceChange(IEclipsePreferences.PreferenceChangeEvent event) {
+			String propertyName = event.getKey();
 			if (propertyName.startsWith(CP_VARIABLE_PREFERENCES_PREFIX)) {
 				String varName = propertyName.substring(CP_VARIABLE_PREFERENCES_PREFIX.length());
 				String newValue = (String)event.getNewValue();
@@ -729,8 +739,11 @@
 			option = Platform.getDebugOption(POST_ACTION_DEBUG);
 			if(option != null) JavaModelOperation.POST_ACTION_VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
 
+			option = Platform.getDebugOption(RESOLUTION_DEBUG);
+			if(option != null) NameLookup.VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+
 			option = Platform.getDebugOption(SEARCH_DEBUG);
-			if(option != null) SearchEngine.VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+			if(option != null) SearchBasicEngine.VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
 
 			option = Platform.getDebugOption(SELECTION_DEBUG);
 			if(option != null) SelectionEngine.DEBUG = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
@@ -759,7 +772,7 @@
 			deltaBuilder = new JavaElementDeltaBuilder(workingCopy);
 		}
 		PerWorkingCopyInfo info = null;
-		synchronized(perWorkingCopyInfos) {
+		synchronized(this.perWorkingCopyInfos) {
 			WorkingCopyOwner owner = workingCopy.owner;
 			Map workingCopyToInfos = (Map)this.perWorkingCopyInfos.get(owner);
 			if (workingCopyToInfos == null) return -1;
@@ -870,7 +883,7 @@
 	 * Returns the handle to the active Java Model.
 	 */
 	public final JavaModel getJavaModel() {
-		return javaModel;
+		return this.javaModel;
 	}
 
 	/**
@@ -906,11 +919,11 @@
 	 * Returns the per-project info for the given project. If specified, create the info if the info doesn't exist.
 	 */
 	public PerProjectInfo getPerProjectInfo(IProject project, boolean create) {
-		synchronized(perProjectInfos) { // use the perProjectInfo collection as its own lock
-			PerProjectInfo info= (PerProjectInfo) perProjectInfos.get(project);
+		synchronized(this.perProjectInfos) { // use the perProjectInfo collection as its own lock
+			PerProjectInfo info= (PerProjectInfo) this.perProjectInfos.get(project);
 			if (info == null && create) {
 				info= new PerProjectInfo(project);
-				perProjectInfos.put(project, info);
+				this.perProjectInfos.put(project, info);
 			}
 			return info;
 		}
@@ -939,7 +952,7 @@
 	 * Returns null if it doesn't exist and not create.
 	 */
 	public PerWorkingCopyInfo getPerWorkingCopyInfo(CompilationUnit workingCopy,boolean create, boolean recordUsage, IProblemRequestor problemRequestor) {
-		synchronized(perWorkingCopyInfos) { // use the perWorkingCopyInfo collection as its own lock
+		synchronized(this.perWorkingCopyInfos) { // use the perWorkingCopyInfo collection as its own lock
 			WorkingCopyOwner owner = workingCopy.owner;
 			Map workingCopyToInfos = (Map)this.perWorkingCopyInfos.get(owner);
 			if (workingCopyToInfos == null && create) {
@@ -1089,11 +1102,11 @@
 	 * Returns null if it has none.
 	 */
 	public ICompilationUnit[] getWorkingCopies(WorkingCopyOwner owner, boolean addPrimary) {
-		synchronized(perWorkingCopyInfos) {
+		synchronized(this.perWorkingCopyInfos) {
 			ICompilationUnit[] primaryWCs = addPrimary && owner != DefaultWorkingCopyOwner.PRIMARY 
 				? getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, false) 
 				: null;
-			Map workingCopyToInfos = (Map)perWorkingCopyInfos.get(owner);
+			Map workingCopyToInfos = (Map)this.perWorkingCopyInfos.get(owner);
 			if (workingCopyToInfos == null) return primaryWCs;
 			int primaryLength = primaryWCs == null ? 0 : primaryWCs.length;
 			int size = workingCopyToInfos.size(); // note size is > 0 otherwise pathToPerWorkingCopyInfos would be null
@@ -1331,6 +1344,23 @@
 		return container;
 	}
 	
+	public synchronized String intern(String s) {
+		return (String) this.symbols.add(s);
+		
+		// Note1: String#intern() cannot be used as on some VMs this prevents the string from being garbage collected
+		// Note 2: Instead of using a WeakHashset, one could use a WeakHashMap with the following implementation
+		// 			   This would costs more per entry (one Entry object and one WeakReference more))
+		
+		/*
+		WeakReference reference = (WeakReference) this.symbols.get(s);
+		String existing;
+		if (reference != null && (existing = (String) reference.get()) != null)
+			return existing;
+		this.symbols.put(s, new WeakReference(s));
+		return s;
+		*/	
+	}
+	
 	private HashSet getClasspathBeingResolved() {
 	    HashSet result = (HashSet) this.classpathsBeingResolved.get();
 	    if (result == null) {
@@ -1402,23 +1432,31 @@
 		}
 		
 		// load variables and containers from preferences into cache
-		Preferences preferences = JavaCore.getPlugin().getPluginPreferences();
+		IEclipsePreferences preferences = JavaCore.getInstancePreferences();
 
 		// only get variable from preferences not set to their default
-		String[] propertyNames = preferences.propertyNames();
-		int variablePrefixLength = CP_VARIABLE_PREFERENCES_PREFIX.length();
-		for (int i = 0; i < propertyNames.length; i++){
-			String propertyName = propertyNames[i];
-			if (propertyName.startsWith(CP_VARIABLE_PREFERENCES_PREFIX)){
-				String varName = propertyName.substring(variablePrefixLength);
-				IPath varPath = new Path(preferences.getString(propertyName).trim());
-				
-				this.variables.put(varName, varPath); 
-				this.previousSessionVariables.put(varName, varPath);
+		try {
+			String[] propertyNames = preferences.keys();
+			int variablePrefixLength = CP_VARIABLE_PREFERENCES_PREFIX.length();
+			for (int i = 0; i < propertyNames.length; i++){
+				String propertyName = propertyNames[i];
+				if (propertyName.startsWith(CP_VARIABLE_PREFERENCES_PREFIX)){
+					String varName = propertyName.substring(variablePrefixLength);
+					String propertyValue = preferences.get(propertyName, null);
+					if (propertyValue != null) {
+						IPath varPath = new Path(propertyValue.trim());
+						this.variables.put(varName, varPath); 
+						this.previousSessionVariables.put(varName, varPath);
+					}
+				}
+				if (propertyName.startsWith(CP_CONTAINER_PREFERENCES_PREFIX)){
+					String propertyValue = preferences.get(propertyName, null);
+					if (propertyValue != null)
+						recreatePersistedContainer(propertyName, propertyValue, true/*add to container values*/);
+				}
 			}
-			if (propertyName.startsWith(CP_CONTAINER_PREFERENCES_PREFIX)){
-				recreatePersistedContainer(propertyName, preferences.getString(propertyName), true/*add to container values*/);
-			}
+		} catch (BackingStoreException e1) {
+			// TODO (frederic) see if it's necessary to report this failure...
 		}
 		// override persisted values for variables which have a registered initializer
 		String[] registeredVariables = getRegisteredVariableNames();
@@ -1472,7 +1510,10 @@
 				}
 			}
 		}
-	
+		
+		// ensure that the elements that are being added have enough room
+		this.cache.ensureSpaceLimit(newElements);
+		
 		Iterator iterator = newElements.keySet().iterator();
 		while (iterator.hasNext()) {
 			IJavaElement element = (IJavaElement)iterator.next();
@@ -1577,7 +1618,27 @@
 			boolean wasVerbose = false;
 			try {
 				if (VERBOSE) {
-					System.out.println("CLOSING Element ("+ Thread.currentThread()+"): " + element.toStringWithAncestors());  //$NON-NLS-1$//$NON-NLS-2$
+					String elementType;
+					switch (element.getElementType()) {
+						case IJavaElement.JAVA_PROJECT:
+							elementType = "project"; //$NON-NLS-1$
+							break;
+						case IJavaElement.PACKAGE_FRAGMENT_ROOT:
+							elementType = "root"; //$NON-NLS-1$
+							break;
+						case IJavaElement.PACKAGE_FRAGMENT:
+							elementType = "package"; //$NON-NLS-1$
+							break;
+						case IJavaElement.CLASS_FILE:
+							elementType = "class file"; //$NON-NLS-1$
+							break;
+						case IJavaElement.COMPILATION_UNIT:
+							elementType = "compilation unit"; //$NON-NLS-1$
+							break;
+						default:
+							elementType = "element"; //$NON-NLS-1$
+					}
+					System.out.println(Thread.currentThread() + " CLOSING "+ elementType + " " + element.toStringWithAncestors());  //$NON-NLS-1$//$NON-NLS-2$
 					wasVerbose = true;
 					VERBOSE = false;
 				}
@@ -1590,9 +1651,9 @@
 					}
 				}
 				this.cache.removeInfo(element);
+				this.cache.resetSpaceLimit(element);
 				if (wasVerbose) {
-					System.out.println("-> Package cache size = " + this.cache.pkgSize()); //$NON-NLS-1$
-					System.out.println("-> Openable cache filling ratio = " + NumberFormat.getInstance().format(this.cache.openableFillingRatio()) + "%"); //$NON-NLS-1$//$NON-NLS-2$
+					System.out.println(this.cache.toStringFillingRation("-> ")); //$NON-NLS-1$
 				}
 			} finally {
 				JavaModelManager.VERBOSE = wasVerbose;
@@ -1603,11 +1664,24 @@
 	}	
 
 	public void removePerProjectInfo(JavaProject javaProject) {
-		synchronized(perProjectInfos) { // use the perProjectInfo collection as its own lock
+		synchronized(this.perProjectInfos) { // use the perProjectInfo collection as its own lock
 			IProject project = javaProject.getProject();
-			PerProjectInfo info= (PerProjectInfo) perProjectInfos.get(project);
+			PerProjectInfo info= (PerProjectInfo) this.perProjectInfos.get(project);
 			if (info != null) {
-				perProjectInfos.remove(project);
+				this.perProjectInfos.remove(project);
+			}
+		}
+	}
+
+	/*
+	 * Reset project preferences stored in info cache.
+	 */
+	public void resetProjectPreferences(JavaProject javaProject) {
+		synchronized(this.perProjectInfos) { // use the perProjectInfo collection as its own lock
+			IProject project = javaProject.getProject();
+			PerProjectInfo info= (PerProjectInfo) this.perProjectInfos.get(project);
+			if (info != null) {
+				info.preferences = null;
 			}
 		}
 	}
@@ -1689,7 +1763,6 @@
 	public void saving(ISaveContext context) throws CoreException {
 		
 	    // save container values on snapshot/full save
-		Preferences preferences = JavaCore.getPlugin().getPluginPreferences();
 		IJavaProject[] projects = getJavaModel().getJavaProjects();
 		for (int i = 0, length = projects.length; i < length; i++) {
 		    IJavaProject project = projects[i];
@@ -1703,16 +1776,25 @@
 				String containerString = CP_ENTRY_IGNORE;
 				try {
 					if (container != null) {
-						containerString = ((JavaProject)project).encodeClasspath(container.getClasspathEntries(), null, false);
+						containerString = ((JavaProject)project).encodeClasspath(
+								container.getClasspathEntries(), 
+								null, 
+								false);
 					}
 				} catch(JavaModelException e){
 					// could not encode entry: leave it as CP_ENTRY_IGNORE
 				}
-				preferences.setDefault(containerKey, CP_ENTRY_IGNORE); // use this default to get rid of removed ones
-				preferences.setValue(containerKey, containerString);
+				JavaCore.getDefaultPreferences().put(containerKey, CP_ENTRY_IGNORE); // TODO (frederic) verify if this is really necessary...
+				JavaCore.getInstancePreferences().put(containerKey, containerString);
 			}
 		}
-		JavaCore.getPlugin().savePluginPreferences();
+		try {
+			JavaCore.getInstancePreferences().flush();
+		} catch (BackingStoreException e) {
+			// TODO (frederic) see if it's necessary to report this exception
+			// IStatus status = new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, IStatus.ERROR, "Problems while saving context", e); //$NON-NLS-1$
+			// throw new CoreException(status);
+		}
 		
 		if (context.getKind() == ISaveContext.FULL_SAVE) {
 			// will need delta since this save (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=38658)
@@ -1735,7 +1817,7 @@
 		}
 
 		ArrayList vStats= null; // lazy initialized
-		for (Iterator iter =  perProjectInfos.values().iterator(); iter.hasNext();) {
+		for (Iterator iter =  this.perProjectInfos.values().iterator(); iter.hasNext();) {
 			try {
 				PerProjectInfo info = (PerProjectInfo) iter.next();
 				saveState(info, context);
@@ -1971,7 +2053,7 @@
 								affectedProject
 									.setRawClasspath(
 										affectedProject.getRawClasspath(),
-										SetClasspathOperation.ReuseOutputLocation,
+										SetClasspathOperation.REUSE_PATH,
 										null, // don't call beginTask on the monitor (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=3717)
 										canChangeResources, 
 										(IClasspathEntry[]) affectedProjectClasspaths.get(affectedProject),
@@ -2044,11 +2126,16 @@
 			this.previousSessionVariables.remove(variableName);
 		}
 
-		Preferences preferences = JavaCore.getPlugin().getPluginPreferences();
 		String variableKey = CP_VARIABLE_PREFERENCES_PREFIX+variableName;
 		String variableString = variablePath == null ? CP_ENTRY_IGNORE : variablePath.toString();
-		preferences.setDefault(variableKey, CP_ENTRY_IGNORE); // use this default to get rid of removed ones
-		preferences.setValue(variableKey, variableString);
-		JavaCore.getPlugin().savePluginPreferences();
+		JavaCore.getDefaultPreferences().put(variableKey, CP_ENTRY_IGNORE); // TODO (frederic) verify if this is really necessary...
+		JavaCore.getInstancePreferences().put(variableKey, variableString);
+		try {
+			JavaCore.getInstancePreferences().flush();
+		} catch (BackingStoreException e) {
+			// TODO (frederic) see if it's necessary to report this exception
+//			IStatus status = new Status(IStatus.ERROR, Platform.PI_RUNTIME, IStatus.ERROR, "Problems while saving context", e); //$NON-NLS-1$
+//			throw new CoreException(status);
+		}
 	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelStatus.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelStatus.java
index 8ccf7cb..91eea48 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelStatus.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelStatus.java
@@ -193,6 +193,9 @@
 				case ELEMENT_DOES_NOT_EXIST:
 					return Util.bind("element.doesNotExist",((JavaElement)elements[0]).toStringWithAncestors()); //$NON-NLS-1$
 
+				case ELEMENT_NOT_ON_CLASSPATH:
+					return Util.bind("element.notOnClasspath",((JavaElement)elements[0]).toStringWithAncestors()); //$NON-NLS-1$
+
 				case EVALUATION_ERROR:
 					return Util.bind("status.evaluationError", string); //$NON-NLS-1$
 
@@ -250,8 +253,7 @@
 				case NAME_COLLISION:
 					if (elements != null && elements.length > 0) {
 						IJavaElement element = elements[0];
-						String name = element.getElementName();
-						if (element instanceof IPackageFragment && name.equals(IPackageFragment.DEFAULT_PACKAGE_NAME)) {
+						if (element instanceof PackageFragment && ((PackageFragment) element).isDefaultPackage()) {
 							return Util.bind("operation.cannotRenameDefaultPackage"); //$NON-NLS-1$
 						}
 					}
@@ -401,7 +403,8 @@
 	 * @see IJavaModelStatus#isDoesNotExist()
 	 */
 	public boolean isDoesNotExist() {
-		return getCode() == ELEMENT_DOES_NOT_EXIST;
+		int code = getCode();
+		return code == ELEMENT_DOES_NOT_EXIST || code == ELEMENT_NOT_ON_CLASSPATH;
 	}
 	/**
 	 * @see IStatus#isMultiStatus()
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
index 8cd77f4..526681f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
@@ -10,16 +10,14 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.io.*;
 import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.StringReader;
 import java.util.ArrayList;
@@ -28,11 +26,9 @@
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.Map;
-
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
-
 import org.eclipse.core.resources.ICommand;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
@@ -43,6 +39,7 @@
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IWorkspace;
 import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ProjectScope;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
@@ -50,6 +47,8 @@
 import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Preferences;
 import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IScopeContext;
 import org.eclipse.jdt.core.IClasspathContainer;
 import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.ICompilationUnit;
@@ -66,14 +65,15 @@
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.WorkingCopyOwner;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.eval.IEvaluationContext;
-import org.eclipse.jdt.internal.codeassist.ISearchableNameEnvironment;
 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.eval.EvaluationContextWrapper;
 import org.eclipse.jdt.internal.core.util.MementoTokenizer;
 import org.eclipse.jdt.internal.core.util.Util;
 import org.eclipse.jdt.internal.eval.EvaluationContext;
+import org.osgi.service.prefs.BackingStoreException;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
@@ -101,6 +101,16 @@
 public class JavaProject
 	extends Openable
 	implements IJavaProject, IProjectNature, SuffixConstants {
+	
+	/**
+	 * Name of file containing project classpath
+	 */
+	public static final String CLASSPATH_FILENAME = ".classpath";  //$NON-NLS-1$
+	
+	/**
+	 * Value of the project's raw classpath if the .classpath file contains invalid entries.
+	 */
+	public static final IClasspathEntry[] INVALID_CLASSPATH = new IClasspathEntry[0];
 
 	/**
 	 * Whether the underlying file system is case sensitive.
@@ -113,31 +123,23 @@
 	protected static final String[] NO_PREREQUISITES = new String[0];
 
 	/**
-	 * The platform project this <code>IJavaProject</code> is based on
-	 */
-	protected IProject project;
-	
-	/**
-	 * Name of file containing project classpath
-	 */
-	public static final String CLASSPATH_FILENAME = ".classpath";  //$NON-NLS-1$
-
-	/**
 	 * Name of file containing custom project preferences
+	 * @deprecated WARNING Visibility will be reduce to private before M9
+	 * 	If you use this variable, change your implementation to avoid future compilation error...
+	 * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=59258">bug 59258</a>
+	 * TODO (frederic) set visibility from public to private
 	 */
 	public static final String PREF_FILENAME = ".jprefs";  //$NON-NLS-1$
 	
-	/**
-	 * Value of the project's raw classpath if the .classpath file contains invalid entries.
-	 */
-	public static final IClasspathEntry[] INVALID_CLASSPATH = new IClasspathEntry[0];
-
-	private static final String CUSTOM_DEFAULT_OPTION_VALUE = "#\r\n\r#custom-non-empty-default-value#\r\n\r#"; //$NON-NLS-1$
-	
 	/*
 	 * Value of project's resolved classpath while it is being resolved
 	 */
 	private static final IClasspathEntry[] RESOLUTION_IN_PROGRESS = new IClasspathEntry[0];
+
+	/**
+	 * The platform project this <code>IJavaProject</code> is based on
+	 */
+	protected IProject project;
 	
 	/**
 	 * Returns a canonicalized path from the given external path.
@@ -218,6 +220,80 @@
 //		}
 		return result;
 	}
+	
+	/**
+	 * Returns true if the given project is accessible and it has
+	 * a java nature, otherwise false.
+	 * @param project IProject
+	 * @return boolean
+	 */
+	public static boolean hasJavaNature(IProject project) { 
+		try {
+			return project.hasNature(JavaCore.NATURE_ID);
+		} catch (CoreException e) {
+			// project does not exist or is not open
+		}
+		return false;
+	}
+
+	/**
+	 * Update cycle markers for all java projects
+	 * @param preferredClasspaths Map
+	 * @throws JavaModelException
+	 */
+	public static void updateAllCycleMarkers(Map preferredClasspaths) throws JavaModelException {
+
+		//long start = System.currentTimeMillis();
+
+		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+		IProject[] rscProjects = workspaceRoot.getProjects();
+		int length = rscProjects.length;
+		JavaProject[] projects = new JavaProject[length];
+				
+		HashSet cycleParticipants = new HashSet();
+		HashSet traversed = new HashSet();
+		
+		// compute cycle participants
+		ArrayList prereqChain = new ArrayList();
+		for (int i = 0; i < length; i++){
+			if (hasJavaNature(rscProjects[i])) {
+				JavaProject project = (projects[i] = (JavaProject)JavaCore.create(rscProjects[i]));
+				if (!traversed.contains(project.getPath())){
+					prereqChain.clear();
+					project.updateCycleParticipants(prereqChain, cycleParticipants, workspaceRoot, traversed, preferredClasspaths);
+				}
+			}
+		}
+		//System.out.println("updateAllCycleMarkers: " + (System.currentTimeMillis() - start) + " ms");
+
+		for (int i = 0; i < length; i++){
+			JavaProject project = projects[i];
+			if (project != null) {
+				if (cycleParticipants.contains(project.getPath())){
+					IMarker cycleMarker = project.getCycleMarker();
+					String circularCPOption = project.getOption(JavaCore.CORE_CIRCULAR_CLASSPATH, true);
+					int circularCPSeverity = JavaCore.ERROR.equals(circularCPOption) ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING;
+					if (cycleMarker != null) {
+						// update existing cycle marker if needed
+						try {
+							int existingSeverity = ((Integer)cycleMarker.getAttribute(IMarker.SEVERITY)).intValue();
+							if (existingSeverity != circularCPSeverity) {
+								cycleMarker.setAttribute(IMarker.SEVERITY, circularCPSeverity);
+							}
+						} catch (CoreException e) {
+							throw new JavaModelException(e);
+						}
+					} else {
+						// create new marker
+						project.createClasspathProblemMarker(
+							new JavaModelStatus(IJavaModelStatusConstants.CLASSPATH_CYCLE, project)); 
+					}
+				} else {
+					project.flushClasspathProblemMarkers(true, false);
+				}			
+			}
+		}
+	}
 
 	/**
 	 * Constructor needed for <code>IProject.getNature()</code> and <code>IProject.addNature()</code>.
@@ -225,11 +301,11 @@
 	 * @see #setProject(IProject)
 	 */
 	public JavaProject() {
-		super(null, null);
+		super(null);
 	}
 
 	public JavaProject(IProject project, JavaElement parent) {
-		super(parent, project.getName());
+		super(parent);
 		this.project = project;
 	}
 
@@ -266,7 +342,7 @@
 		IClasspathEntry[] resolvedClasspath = getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
 
 		// compute the pkg fragment roots
-		info.setChildren(computePackageFragmentRoots(resolvedClasspath, false));	
+		info.setChildren(computePackageFragmentRoots(resolvedClasspath, false, null /*no reverse map*/));	
 		
 		// remember the timestamps of external libraries the first time they are looked up
 		for (int i = 0, length = resolvedClasspath.length; i < length; i++) {
@@ -309,7 +385,7 @@
 		IClasspathEntry[] classpath = getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
 		IPackageFragmentRoot[] oldRoots = info.allPkgFragmentRootsCache;
 		if (oldRoots != null) {
-			IPackageFragmentRoot[] newRoots = computePackageFragmentRoots(classpath, true);
+			IPackageFragmentRoot[] newRoots = computePackageFragmentRoots(classpath, true, null /*no reverse map*/);
 			checkIdentical: { // compare all pkg fragment root lists
 				if (oldRoots.length == newRoots.length){
 					for (int i = 0, length = oldRoots.length; i < length; i++){
@@ -324,17 +400,17 @@
 		info.resetCaches(); // discard caches (hold onto roots and pkg fragments)
 		info.setNonJavaResources(null);
 		info.setChildren(
-			computePackageFragmentRoots(classpath, false));		
+			computePackageFragmentRoots(classpath, false, null /*no reverse map*/));		
 	}
 	
 
 
 	/**
 	 * Internal computation of an expanded classpath. It will eliminate duplicates, and produce copies
-	 * of exported classpath entries to avoid possible side-effects ever after.
+	 * of exported or restricted classpath entries to avoid possible side-effects ever after.
 	 */			
 	private void computeExpandedClasspath(
-		JavaProject initialProject, 
+		ClasspathEntry referringEntry,
 		boolean ignoreUnresolvedVariable,
 		boolean generateMarkerOnError,
 		HashSet rootIDs,
@@ -352,11 +428,11 @@
 		IPath preferredOutput = preferredOutputs != null ? (IPath)preferredOutputs.get(this) : null;
 		IClasspathEntry[] immediateClasspath = 
 			preferredClasspath != null 
-				? getResolvedClasspath(preferredClasspath, preferredOutput, ignoreUnresolvedVariable, generateMarkerOnError, null)
+				? getResolvedClasspath(preferredClasspath, preferredOutput, ignoreUnresolvedVariable, generateMarkerOnError, null /*no reverse map*/)
 				: getResolvedClasspath(ignoreUnresolvedVariable, generateMarkerOnError, false/*don't returnResolutionInProgress*/);
 			
 		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
-		boolean isInitialProject = this.equals(initialProject);
+		boolean isInitialProject = referringEntry == null;
 		for (int i = 0, length = immediateClasspath.length; i < length; i++){
 			ClasspathEntry entry = (ClasspathEntry) immediateClasspath[i];
 			if (isInitialProject || entry.isExported()){
@@ -364,18 +440,19 @@
 				if (rootIDs.contains(rootID)) {
 					continue;
 				}
-				
-				accumulatedEntries.add(entry);
+				// combine restrictions along the project chain
+				ClasspathEntry combinedEntry = entry.combineWith(referringEntry);
+				accumulatedEntries.add(combinedEntry);
 				
 				// recurse in project to get all its indirect exports (only consider exported entries from there on)				
 				if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
 					IResource member = workspaceRoot.findMember(entry.getPath()); 
 					if (member != null && member.getType() == IResource.PROJECT){ // double check if bound to project (23977)
 						IProject projRsc = (IProject) member;
-						if (JavaProject.hasJavaNature(projRsc)) {				
+						if (JavaProject.hasJavaNature(projRsc)) {
 							JavaProject javaProject = (JavaProject) JavaCore.create(projRsc);
 							javaProject.computeExpandedClasspath(
-								initialProject, 
+								combinedEntry, 
 								ignoreUnresolvedVariable, 
 								false /* no marker when recursing in prereq*/,
 								rootIDs,
@@ -390,31 +467,6 @@
 			}			
 		}
 	}
-	
-	/**
-	 * Returns (local/all) the package fragment roots identified by the given project's classpath.
-	 * Note: this follows project classpath references to find required project contributions,
-	 * eliminating duplicates silently.
-	 * Only works with resolved entries
-	 * @param resolvedClasspath IClasspathEntry[]
-	 * @param retrieveExportedRoots boolean
-	 * @return IPackageFragmentRoot[]
-	 * @throws JavaModelException
-	 */
-	public IPackageFragmentRoot[] computePackageFragmentRoots(IClasspathEntry[] resolvedClasspath, boolean retrieveExportedRoots) throws JavaModelException {
-
-		ObjectVector accumulatedRoots = new ObjectVector();
-		computePackageFragmentRoots(
-			resolvedClasspath, 
-			accumulatedRoots, 
-			new HashSet(5), // rootIDs
-			true, // inside original project
-			true, // check existency
-			retrieveExportedRoots);
-		IPackageFragmentRoot[] rootArray = new IPackageFragmentRoot[accumulatedRoots.size()];
-		accumulatedRoots.copyInto(rootArray);
-		return rootArray;
-	}
 
 	/**
 	 * Computes the package fragment roots identified by the given entry.
@@ -427,7 +479,8 @@
 			return 
 				computePackageFragmentRoots(
 					new IClasspathEntry[]{ resolvedEntry }, 
-					false // don't retrieve exported roots
+					false, // don't retrieve exported roots
+					null /* no reverse map */
 				);
 		} catch (JavaModelException e) {
 			return new IPackageFragmentRoot[] {};
@@ -441,7 +494,7 @@
 	 * @param resolvedEntry IClasspathEntry
 	 * @param accumulatedRoots ObjectVector
 	 * @param rootIDs HashSet
-	 * @param insideOriginalProject boolean
+	 * @param referringEntry the CP entry (project) referring to this entry, or null if initial project
 	 * @param checkExistency boolean
 	 * @param retrieveExportedRoots boolean
 	 * @throws JavaModelException
@@ -450,9 +503,10 @@
 		IClasspathEntry resolvedEntry,
 		ObjectVector accumulatedRoots, 
 		HashSet rootIDs, 
-		boolean insideOriginalProject,
+		IClasspathEntry referringEntry,
 		boolean checkExistency,
-		boolean retrieveExportedRoots) throws JavaModelException {
+		boolean retrieveExportedRoots,
+		Map rootToResolvedEntries) throws JavaModelException {
 			
 		String rootID = ((ClasspathEntry)resolvedEntry).rootID();
 		if (rootIDs.contains(rootID)) return;
@@ -460,6 +514,7 @@
 		IPath projectPath = this.project.getFullPath();
 		IPath entryPath = resolvedEntry.getPath();
 		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+		IPackageFragmentRoot root = null;
 		
 		switch(resolvedEntry.getEntryKind()){
 			
@@ -472,16 +527,10 @@
 						if (target == null) return;
 	
 						if (target instanceof IFolder || target instanceof IProject){
-							accumulatedRoots.add(
-								getPackageFragmentRoot((IResource)target));
-							rootIDs.add(rootID);
+							root = getPackageFragmentRoot((IResource)target);
 						}
 					} else {
-						IPackageFragmentRoot root = getFolderPackageFragmentRoot(entryPath);
-						if (root != null) {
-							accumulatedRoots.add(root);
-							rootIDs.add(rootID);
-						}
+						root = getFolderPackageFragmentRoot(entryPath);
 					}
 				}
 				break;
@@ -489,7 +538,7 @@
 			// internal/external JAR or folder
 			case IClasspathEntry.CPE_LIBRARY :
 			
-				if (!insideOriginalProject && !resolvedEntry.isExported()) return;
+				if (referringEntry != null  && !resolvedEntry.isExported()) return;
 				
 				if (checkExistency) {
 					Object target = JavaModel.getTarget(workspaceRoot, entryPath, checkExistency);
@@ -497,26 +546,15 @@
 	
 					if (target instanceof IResource){
 						// internal target
-						IResource resource = (IResource) target;
-						IPackageFragmentRoot root = getPackageFragmentRoot(resource);
-						if (root != null) {
-							accumulatedRoots.add(root);
-							rootIDs.add(rootID);
-						}
+						root = getPackageFragmentRoot((IResource) target);
 					} else {
 						// external target - only JARs allowed
 						if (((java.io.File)target).isFile() && (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(entryPath.lastSegment()))) {
-							accumulatedRoots.add(
-								new JarPackageFragmentRoot(entryPath, this));
-							rootIDs.add(rootID);
+							root = new JarPackageFragmentRoot(entryPath, this);
 						}
 					}
 				} else {
-					IPackageFragmentRoot root = getPackageFragmentRoot(entryPath);
-					if (root != null) {
-						accumulatedRoots.add(root);
-						rootIDs.add(rootID);
-					}
+					root = getPackageFragmentRoot(entryPath);
 				}
 				break;
 
@@ -524,7 +562,7 @@
 			case IClasspathEntry.CPE_PROJECT :
 
 				if (!retrieveExportedRoots) return;
-				if (!insideOriginalProject && !resolvedEntry.isExported()) return;
+				if (referringEntry != null && !resolvedEntry.isExported()) return;
 
 				IResource member = workspaceRoot.findMember(entryPath);
 				if (member != null && member.getType() == IResource.PROJECT){// double check if bound to project (23977)
@@ -536,13 +574,48 @@
 							requiredProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/), 
 							accumulatedRoots, 
 							rootIDs, 
-							false, 
+							rootToResolvedEntries == null ? resolvedEntry : ((ClasspathEntry)resolvedEntry).combineWith(referringEntry), // only combine if need to build the reverse map 
 							checkExistency, 
-							retrieveExportedRoots);
+							retrieveExportedRoots,
+							rootToResolvedEntries);
 					}
 				break;
 			}
 		}
+		if (root != null) {
+			accumulatedRoots.add(root);
+			rootIDs.add(rootID);
+			if (rootToResolvedEntries != null) rootToResolvedEntries.put(root, ((ClasspathEntry)resolvedEntry).combineWith(referringEntry));
+		}
+	}
+	
+	/**
+	 * Returns (local/all) the package fragment roots identified by the given project's classpath.
+	 * Note: this follows project classpath references to find required project contributions,
+	 * eliminating duplicates silently.
+	 * Only works with resolved entries
+	 * @param resolvedClasspath IClasspathEntry[]
+	 * @param retrieveExportedRoots boolean
+	 * @return IPackageFragmentRoot[]
+	 * @throws JavaModelException
+	 */
+	public IPackageFragmentRoot[] computePackageFragmentRoots(
+					IClasspathEntry[] resolvedClasspath, 
+					boolean retrieveExportedRoots,
+					Map rootToResolvedEntries) throws JavaModelException {
+
+		ObjectVector accumulatedRoots = new ObjectVector();
+		computePackageFragmentRoots(
+			resolvedClasspath, 
+			accumulatedRoots, 
+			new HashSet(5), // rootIDs
+			null, // inside original project
+			true, // check existency
+			retrieveExportedRoots,
+			rootToResolvedEntries);
+		IPackageFragmentRoot[] rootArray = new IPackageFragmentRoot[accumulatedRoots.size()];
+		accumulatedRoots.copyInto(rootArray);
+		return rootArray;
 	}
 
 	/**
@@ -553,7 +626,7 @@
 	 * @param resolvedClasspath IClasspathEntry[]
 	 * @param accumulatedRoots ObjectVector
 	 * @param rootIDs HashSet
-	 * @param insideOriginalProject boolean
+	 * @param referringEntry project entry referring to this CP or null if initial project
 	 * @param checkExistency boolean
 	 * @param retrieveExportedRoots boolean
 	 * @throws JavaModelException
@@ -562,11 +635,12 @@
 		IClasspathEntry[] resolvedClasspath,
 		ObjectVector accumulatedRoots, 
 		HashSet rootIDs, 
-		boolean insideOriginalProject,
+		IClasspathEntry referringEntry,
 		boolean checkExistency,
-		boolean retrieveExportedRoots) throws JavaModelException {
+		boolean retrieveExportedRoots,
+		Map rootToResolvedEntries) throws JavaModelException {
 
-		if (insideOriginalProject){
+		if (referringEntry == null){
 			rootIDs.add(rootID());
 		}	
 		for (int i = 0, length = resolvedClasspath.length; i < length; i++){
@@ -574,9 +648,10 @@
 				resolvedClasspath[i],
 				accumulatedRoots,
 				rootIDs,
-				insideOriginalProject,
+				referringEntry,
 				checkExistency,
-				retrieveExportedRoots);
+				retrieveExportedRoots,
+				rootToResolvedEntries);
 		}
 	}
 
@@ -646,7 +721,7 @@
 					return !org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(fullPath.lastSegment());
 				case IClasspathEntry.CPE_LIBRARY:
 					// .java files are not visible in library folders
-					return !org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(fullPath.lastSegment());
+					return !org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(fullPath.lastSegment());
 			}
 		}
 		if (innerMostOutput != null) {
@@ -857,7 +932,7 @@
 			OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
 			XMLWriter xmlWriter = new XMLWriter(writer);
 			
-			xmlWriter.startTag("classpath", indent); //$NON-NLS-1$
+			xmlWriter.startTag(ClasspathEntry.TAG_CLASSPATH, indent);
 			for (int i = 0; i < classpath.length; ++i) {
 				((ClasspathEntry)classpath[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true);
 			}
@@ -866,12 +941,12 @@
 				outputLocation = outputLocation.removeFirstSegments(1);
 				outputLocation = outputLocation.makeRelative();
 				HashMap parameters = new HashMap();
-				parameters.put("kind", ClasspathEntry.kindToString(ClasspathEntry.K_OUTPUT));//$NON-NLS-1$
-				parameters.put("path", String.valueOf(outputLocation));//$NON-NLS-1$
-				xmlWriter.printTag("classpathentry", parameters, indent, true, true);//$NON-NLS-1$
+				parameters.put(ClasspathEntry.TAG_KIND, ClasspathEntry.kindToString(ClasspathEntry.K_OUTPUT));
+				parameters.put(ClasspathEntry.TAG_PATH, String.valueOf(outputLocation));
+				xmlWriter.printTag(ClasspathEntry.TAG_CLASSPATHENTRY, parameters, indent, true, true);
 			}
 	
-			xmlWriter.endTag("classpath", indent);//$NON-NLS-1$
+			xmlWriter.endTag(ClasspathEntry.TAG_CLASSPATH, indent);
 			writer.flush();
 			writer.close();
 			return s.toString("UTF8");//$NON-NLS-1$
@@ -897,8 +972,7 @@
 			return false;
 	
 		JavaProject other = (JavaProject) o;
-		return this.project.equals(other.getProject())
-			&& this.occurrenceCount == other.occurrenceCount;
+		return this.project.equals(other.getProject());
 	}
 
 	public boolean exists() {
@@ -944,8 +1018,7 @@
 					// default to the first one
 					return pkgFragments[0];
 				}
-			} else if (
-				extension.equalsIgnoreCase(EXTENSION_java)
+			} else if (Util.isJavaLikeFileName(path.lastSegment())
 					|| extension.equalsIgnoreCase(EXTENSION_class)) {
 				IPath packagePath = path.removeLastSegments(1);
 				String packageName = packagePath.toString().replace(IPath.SEPARATOR, '.');
@@ -963,7 +1036,7 @@
 				IType type = lookup.findType(
 					qualifiedName,
 					false,
-					NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
+					NameLookup.ACCEPT_ALL);
 
 				if (type != null) {
 					return type.getParent();
@@ -1041,7 +1114,8 @@
 					return 
 						computePackageFragmentRoots(
 							getResolvedClasspath(new IClasspathEntry[] {entry}, null, true, false, null/*no reverse map*/), 
-							false); // don't retrieve exported roots
+							false, // don't retrieve exported roots
+							null); /*no reverse map*/
 				}
 			}
 		} catch (JavaModelException e) {
@@ -1056,31 +1130,6 @@
 	public IType findType(String fullyQualifiedName) throws JavaModelException {
 		return findType(fullyQualifiedName, DefaultWorkingCopyOwner.PRIMARY);
 	}
-
-	/**
-	 * @see IJavaProject#findType(String, WorkingCopyOwner)
-	 */
-	public IType findType(String fullyQualifiedName, WorkingCopyOwner owner) throws JavaModelException {
-		
-		NameLookup lookup = newNameLookup(owner);
-		IType type = lookup.findType(
-			fullyQualifiedName,
-			false,
-			NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
-		if (type == null) {
-			// try to find enclosing type
-			int lastDot = fullyQualifiedName.lastIndexOf('.');
-			if (lastDot == -1) return null;
-			type = this.findType(fullyQualifiedName.substring(0, lastDot));
-			if (type != null) {
-				type = type.getType(fullyQualifiedName.substring(lastDot+1));
-				if (!type.exists()) {
-					return null;
-				}
-			}
-		}
-		return type;
-	}
 	
 	/**
 	 * @see IJavaProject#findType(String, String)
@@ -1098,8 +1147,33 @@
 			typeQualifiedName, 
 			packageName,
 			false,
-			NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
+			NameLookup.ACCEPT_ALL);
 	}	
+
+	/**
+	 * @see IJavaProject#findType(String, WorkingCopyOwner)
+	 */
+	public IType findType(String fullyQualifiedName, WorkingCopyOwner owner) throws JavaModelException {
+		
+		NameLookup lookup = newNameLookup(owner);
+		IType type = lookup.findType(
+			fullyQualifiedName,
+			false,
+			NameLookup.ACCEPT_ALL);
+		if (type == null) {
+			// try to find enclosing type
+			int lastDot = fullyQualifiedName.lastIndexOf('.');
+			if (lastDot == -1) return null;
+			type = this.findType(fullyQualifiedName.substring(0, lastDot));
+			if (type != null) {
+				type = type.getType(fullyQualifiedName.substring(lastDot+1));
+				if (!type.exists()) {
+					return null;
+				}
+			}
+		}
+		return type;
+	}
 	
 	/**
 	 * Remove all markers denoting classpath problems
@@ -1175,7 +1249,7 @@
 
 			// will force an update of the classpath/output location based on the file information
 			// extract out the output location
-			IPath outputLocation = null;
+			IPath outputLocation = SetClasspathOperation.REUSE_PATH; 
 			if (fileEntries != null && fileEntries.length > 0) {
 				IClasspathEntry entry = fileEntries[fileEntries.length - 1];
 				if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
@@ -1185,15 +1259,10 @@
 					fileEntries = copy;
 				}
 			}
-			// restore output location				
-			if (outputLocation == null) {
-				outputLocation = SetClasspathOperation.ReuseOutputLocation;
-				// clean mode will also default to reusing current one
-			}
 			IClasspathEntry[] oldResolvedClasspath = info.resolvedClasspath;
 			setRawClasspath(
 				fileEntries, 
-				outputLocation, 
+				outputLocation,
 				monitor, 
 				!ResourcesPlugin.getWorkspace().isTreeLocked(), // canChangeResource
 				oldResolvedClasspath != null ? oldResolvedClasspath : getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/),
@@ -1236,13 +1305,37 @@
 		}
 	}	
 
+	/** 
+	 * Returns the set of patterns corresponding to this project visibility given rules
+	 * @return an array of IPath or null if none
+	 */
+	public IPath[] getAccessRestrictions(String optionName) {
+		String sequence = getOption(optionName, true); // inherit from workspace
+		if (sequence == null || sequence.length() == 0) return null;
+		IPath[] rules = null;
+		char[][] patterns = CharOperation.splitOn('|', sequence.toCharArray());
+		int patternCount;
+		if ((patternCount  = patterns.length) > 0) {
+			rules = new IPath[patternCount];
+			for (int j = 0; j < patterns.length; j++){
+				rules[j] = new Path(new String(patterns[j]));
+			}
+		}
+		return rules;
+	}
+
 	/**
 	 * @see IJavaProject
 	 */
 	public IPackageFragmentRoot[] getAllPackageFragmentRoots()
 		throws JavaModelException {
 
-		return computePackageFragmentRoots(getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/), true/*retrieveExportedRoots*/);
+		return getAllPackageFragmentRoots(null /*no reverse map*/);
+	}
+	
+	public IPackageFragmentRoot[] getAllPackageFragmentRoots(Map rootToResolvedEntries) throws JavaModelException {
+
+		return computePackageFragmentRoots(getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/), true/*retrieveExportedRoots*/, rootToResolvedEntries);
 	}
 
 	/**
@@ -1286,6 +1379,40 @@
 	}
 
 	/**
+	 * Returns the project custom preference pool.
+	 * Project preferences may include custom encoding.
+	 * @return IEclipsePreferences
+	 */	
+	public IEclipsePreferences getEclipsePreferences(){
+		if (!JavaProject.hasJavaNature(this.project)) return null;
+		// Get cached preferences if exist
+		JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(this.project, true);
+		if (perProjectInfo.preferences != null) return perProjectInfo.preferences;
+		// Init project preferences
+		IScopeContext context = new ProjectScope(getProject());
+		final IEclipsePreferences eclipsePreferences = context.getNode(JavaCore.PLUGIN_ID);
+		updatePreferences(eclipsePreferences);
+		perProjectInfo.preferences = eclipsePreferences;
+		// Listen to node removal from parent in order to reset cache (see bug 68993)
+		IEclipsePreferences.INodeChangeListener listener = new IEclipsePreferences.INodeChangeListener() {
+			public void added(IEclipsePreferences.NodeChangeEvent event) {
+				// do nothing
+			}
+			public void removed(IEclipsePreferences.NodeChangeEvent event) {
+				if (event.getChild() == eclipsePreferences) {
+					JavaModelManager.getJavaModelManager().resetProjectPreferences(JavaProject.this);
+				}
+			}
+		};
+		((IEclipsePreferences) eclipsePreferences.parent()).addNodeChangeListener(listener);
+		return eclipsePreferences;
+	}
+
+	public String getElementName() {
+		return this.project.getName();
+	}
+	
+	/**
 	 * @see IJavaElement
 	 */
 	public int getElementType() {
@@ -1323,7 +1450,7 @@
 		Map preferredOutputs) throws JavaModelException {
 	
 		ObjectVector accumulatedEntries = new ObjectVector();		
-		computeExpandedClasspath(this, ignoreUnresolvedVariable, generateMarkerOnError, new HashSet(5), accumulatedEntries, preferredClasspaths, preferredOutputs);
+		computeExpandedClasspath(null, ignoreUnresolvedVariable, generateMarkerOnError, new HashSet(5), accumulatedEntries, preferredClasspaths, preferredOutputs);
 		
 		IClasspathEntry[] expandedPath = new IClasspathEntry[accumulatedEntries.size()];
 		accumulatedEntries.copyInto(expandedPath);
@@ -1331,13 +1458,23 @@
 		return expandedPath;
 	}
 
+	/**
+	 * The path is known to match a source/library folder entry.
+	 * @param path IPath
+	 * @return IPackageFragmentRoot
+	 */
+	public IPackageFragmentRoot getFolderPackageFragmentRoot(IPath path) {
+		if (path.segmentCount() == 1) { // default project root
+			return getPackageFragmentRoot(this.project);
+		}
+		return getPackageFragmentRoot(this.project.getWorkspace().getRoot().getFolder(path));
+	}
+
 	/*
 	 * @see JavaElement
 	 */
 	public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner owner) {
 		switch (token.charAt(0)) {
-			case JEM_COUNT:
-				return getHandleUpdatingCountFromMemento(memento, owner);
 			case JEM_PACKAGEFRAGMENTROOT:
 				String rootPath = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
 				token = null;
@@ -1407,11 +1544,11 @@
 		
 		String propertyName = optionName;
 		if (JavaModelManager.getJavaModelManager().optionNames.contains(propertyName)){
-			Preferences preferences = getPreferences();
-			if (preferences == null || preferences.isDefault(propertyName)) {
-				return inheritJavaCoreOptions ? JavaCore.getOption(propertyName) : null;
-			}
-			return preferences.getString(propertyName).trim();
+			IEclipsePreferences preferences = getEclipsePreferences();
+			String javaCoreDefault = inheritJavaCoreOptions ? JavaCore.getOption(propertyName) : null;
+			if (preferences == null) return javaCoreDefault;
+			String value = preferences.get(propertyName, javaCoreDefault);
+			return value == null ? null : value.trim();
 		}
 		return null;
 	}
@@ -1424,21 +1561,25 @@
 		// initialize to the defaults from JavaCore options pool
 		Map options = inheritJavaCoreOptions ? JavaCore.getOptions() : new Hashtable(5);
 
-		Preferences preferences = getPreferences();
+		IEclipsePreferences preferences = getEclipsePreferences();
 		if (preferences == null) return options; // cannot do better (non-Java project)
 		HashSet optionNames = JavaModelManager.getJavaModelManager().optionNames;
 		
 		// project cannot hold custom preferences set to their default, as it uses CUSTOM_DEFAULT_OPTION_VALUE
 
 		// get custom preferences not set to their default
-		String[] propertyNames = preferences.propertyNames();
-		for (int i = 0; i < propertyNames.length; i++){
-			String propertyName = propertyNames[i];
-			String value = preferences.getString(propertyName).trim();
-			if (optionNames.contains(propertyName)){
-				options.put(propertyName, value);
-			}
-		}		
+		try {
+			String[] propertyNames = preferences.keys();
+			for (int i = 0; i < propertyNames.length; i++){
+				String propertyName = propertyNames[i];
+				String value = preferences.get(propertyName, null);
+				if (value != null && optionNames.contains(propertyName)){
+					options.put(propertyName, value.trim());
+				}
+			}		
+		} catch (BackingStoreException e) {
+			// nothing to do
+		}
 
 		return options;
 	}
@@ -1489,8 +1630,10 @@
 			case 0:
 				return null;
 			case 1:
-				// default root
-				return getPackageFragmentRoot(this.project);
+				if (path.equals(getPath())) { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=75814
+					// default root
+					return getPackageFragmentRoot(this.project);
+				}
 			default:
 				// a path ending with .jar/.zip is still ambiguous and could still resolve to a source/lib folder 
 				// thus will try to guess based on existing resource
@@ -1505,18 +1648,6 @@
 				}
 		}
 	}
-
-	/**
-	 * The path is known to match a source/library folder entry.
-	 * @param path IPath
-	 * @return IPackageFragmentRoot
-	 */
-	public IPackageFragmentRoot getFolderPackageFragmentRoot(IPath path) {
-		if (path.segmentCount() == 1) { // default project root
-			return getPackageFragmentRoot(this.project);
-		}
-		return getPackageFragmentRoot(this.project.getWorkspace().getRoot().getFolder(path));
-	}
 	
 	/**
 	 * @see IJavaProject
@@ -1531,9 +1662,9 @@
 					return null;
 				}
 			case IResource.FOLDER:
-				return new PackageFragmentRoot(resource, this, resource.getName());
+				return new PackageFragmentRoot(resource, this);
 			case IResource.PROJECT:
-				return new PackageFragmentRoot(resource, this, ""); //$NON-NLS-1$
+				return new PackageFragmentRoot(resource, this); //$NON-NLS-1$
 			default:
 				return null;
 		}
@@ -1647,20 +1778,23 @@
 	public JavaModelManager.PerProjectInfo getPerProjectInfo() throws JavaModelException {
 		return JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(this.project);
 	}
-	
-	/**
-	 * @see IJavaProject#getProject()
-	 */
-	public IProject getProject() {
-		return this.project;
-	}
+
+	private IPath getPluginWorkingLocation() {
+		return this.project.getWorkingLocation(JavaCore.PLUGIN_ID);
+	}	
 
 	/**
 	 * Returns the project custom preference pool.
 	 * Project preferences may include custom encoding.
 	 * @return Preferences
-	 */	
+	 * @deprecated WARNING:  this method do nothing from now and will be removed soon!
+	 * 	If you use it, switch as soon as possible to new preferences API by using 
+	 * 	{@link #getEclipsePreferences()} to avoid future compilation error...
+	 * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=59258">bug 59258</a>
+	 * TODO (frederic) remove for 3.1...
+	 */
 	public Preferences getPreferences(){
+		/*
 		if (!JavaProject.hasJavaNature(this.project)) return null;
 		JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(this.project, true);
 		Preferences preferences =  perProjectInfo.preferences;
@@ -1669,6 +1803,15 @@
 		if (preferences == null) preferences = new Preferences();
 		perProjectInfo.preferences = preferences;
 		return preferences;
+		*/
+		return new Preferences();
+	}
+
+	/**
+	 * @see IJavaProject#getProject()
+	 */
+	public IProject getProject() {
+		return this.project;
 	}
 
 	/**
@@ -1789,7 +1932,7 @@
 				}
 			}
 		}
-		Map reverseMap = perProjectInfo == null ? null : new HashMap(5);
+		Map rawReverseMap = perProjectInfo == null ? null : new HashMap(5);
 		IClasspathEntry[] resolvedPath = null;
 		boolean nullOldResolvedCP = perProjectInfo != null && perProjectInfo.resolvedClasspath == null;
 		try {
@@ -1800,7 +1943,7 @@
 				generateMarkerOnError ? getOutputLocation() : null, 
 				ignoreUnresolvedEntry, 
 				generateMarkerOnError,
-				reverseMap);
+				rawReverseMap);
 		} finally {
 			if (nullOldResolvedCP) perProjectInfo.resolvedClasspath = null;
 		}
@@ -1817,7 +1960,7 @@
 			}
 
 			perProjectInfo.resolvedClasspath = resolvedPath;
-			perProjectInfo.resolvedPathToRawEntries = reverseMap;
+			perProjectInfo.resolvedPathToRawEntries = rawReverseMap;
 			manager.setClasspathBeingResolved(this, false);
 		}
 		return resolvedPath;
@@ -1829,7 +1972,7 @@
 	 * @param projectOutputLocation IPath
 	 * @param ignoreUnresolvedEntry boolean
 	 * @param generateMarkerOnError boolean
-	 * @param reverseMap Map
+	 * @param rawReverseMap Map
 	 * @return IClasspathEntry[] 
 	 * @throws JavaModelException
 	 */
@@ -1838,7 +1981,7 @@
 		IPath projectOutputLocation, // only set if needing full classpath validation (and markers)
 		boolean ignoreUnresolvedEntry, // if unresolved entries are met, should it trigger initializations
 		boolean generateMarkerOnError,
-		Map reverseMap) // can be null if not interested in reverse mapping
+		Map rawReverseMap) // can be null if not interested in reverse mapping
 		throws JavaModelException {
 
 		IJavaModelStatus status;
@@ -1878,7 +2021,9 @@
 					if (resolvedEntry == null) {
 						if (!ignoreUnresolvedEntry) throw new JavaModelException(status);
 					} else {
-						if (reverseMap != null && reverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) reverseMap.put(resolvedPath , rawEntry);
+						if (rawReverseMap != null) {
+							if (rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) rawReverseMap.put(resolvedPath , rawEntry);
+						}
 						resolvedEntries.add(resolvedEntry);
 					}
 					break; 
@@ -1896,27 +2041,25 @@
 
 					// container was bound
 					for (int j = 0, containerLength = containerEntries.length; j < containerLength; j++){
-						IClasspathEntry cEntry = containerEntries[j];
+						ClasspathEntry cEntry = (ClasspathEntry)containerEntries[j];
 						if (generateMarkerOnError) {
 							IJavaModelStatus containerStatus = ClasspathEntry.validateClasspathEntry(this, cEntry, false, true /*recurse*/);
 							if (!containerStatus.isOK()) createClasspathProblemMarker(containerStatus);
 						}
-						// if container is exported, then its nested entries must in turn be exported  (21749)
-						if (rawEntry.isExported()){
-							cEntry = new ClasspathEntry(cEntry.getContentKind(),
-								cEntry.getEntryKind(), cEntry.getPath(),
-								cEntry.getInclusionPatterns(), cEntry.getExclusionPatterns(), 
-								cEntry.getSourceAttachmentPath(), cEntry.getSourceAttachmentRootPath(), 
-								cEntry.getOutputLocation(), true); // duplicate container entry for tagging it as exported
+						// if container is exported or restricted, then its nested entries must in turn be exported  (21749) and/or propagate restrictions
+						cEntry = cEntry.combineWith(rawEntry);
+						if (rawReverseMap != null) {
+							if (rawReverseMap.get(resolvedPath = cEntry.getPath()) == null) rawReverseMap.put(resolvedPath , rawEntry);
 						}
-						if (reverseMap != null && reverseMap.get(resolvedPath = cEntry.getPath()) == null) reverseMap.put(resolvedPath, rawEntry);
 						resolvedEntries.add(cEntry);
 					}
 					break;
 										
 				default :
 
-					if (reverseMap != null && reverseMap.get(resolvedPath = rawEntry.getPath()) == null) reverseMap.put(resolvedPath, rawEntry);
+					if (rawReverseMap != null) {
+						if (rawReverseMap.get(resolvedPath = rawEntry.getPath()) == null) rawReverseMap.put(resolvedPath , rawEntry);
+					}
 					resolvedEntries.add(rawEntry);
 				
 			}					
@@ -1955,7 +2098,14 @@
 		String property = null;
 		IFile rscFile = this.project.getFile(key);
 		if (rscFile.exists()) {
-			property = new String(Util.getResourceContentsAsByteArray(rscFile));
+			byte[] bytes = Util.getResourceContentsAsByteArray(rscFile);
+			try {
+				property = new String(bytes, "UTF-8"); //$NON-NLS-1$ // .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);
+			}
 		}
 		return property;
 	}
@@ -1967,7 +2117,7 @@
 
 		return null;
 	}
-
+	
 	/**
 	 * @see IJavaElement
 	 */
@@ -2002,21 +2152,6 @@
 	public int hashCode() {
 		return this.project.hashCode();
 	}
-
-	/**
-	 * Returns true if the given project is accessible and it has
-	 * a java nature, otherwise false.
-	 * @param project IProject
-	 * @return boolean
-	 */
-	public static boolean hasJavaNature(IProject project) { 
-		try {
-			return project.hasNature(JavaCore.NATURE_ID);
-		} catch (CoreException e) {
-			// project does not exist or is not open
-		}
-		return false;
-	}
 	
 	/**
 	 * Answers true if the project potentially contains any source. A project which has no source is immutable.
@@ -2050,25 +2185,26 @@
 	 */
 	public boolean isClasspathEqualsTo(IClasspathEntry[] newClasspath, IPath newOutputLocation, IClasspathEntry[] otherClasspathWithOutput) {
 
-		if (otherClasspathWithOutput != null && otherClasspathWithOutput.length > 0) {
+		if (otherClasspathWithOutput == null || otherClasspathWithOutput.length == 0)
+			return false;
 
-			int length = otherClasspathWithOutput.length;
-			if (length == newClasspath.length + 1) {
+		int length = otherClasspathWithOutput.length;
+		if (length != newClasspath.length + 1) 
 				// output is amongst file entries (last one)
-
-				// compare classpath entries
-				for (int i = 0; i < length - 1; i++) {
-					if (!otherClasspathWithOutput[i].equals(newClasspath[i]))
-						return false;
-				}
-				// compare binary outputs
-				IClasspathEntry output = otherClasspathWithOutput[length - 1];
-				if (output.getContentKind() == ClasspathEntry.K_OUTPUT
-						&& output.getPath().equals(newOutputLocation))
-					return true;
-			}
+				return false;
+		
+		
+		// compare classpath entries
+		for (int i = 0; i < length - 1; i++) {
+			if (!otherClasspathWithOutput[i].equals(newClasspath[i]))
+				return false;
 		}
-		return false;
+		// compare binary outputs
+		IClasspathEntry output = otherClasspathWithOutput[length - 1];
+		if (output.getContentKind() != ClasspathEntry.K_OUTPUT
+				|| !output.getPath().equals(newOutputLocation))
+			return false;
+		return true;
 	}
 	
 
@@ -2145,19 +2281,17 @@
 		return false;
 	}
 
-	private IPath getPluginWorkingLocation() {
-		return this.project.getWorkingLocation(JavaCore.PLUGIN_ID);
-	}	
-
-	/*
+	/**
 	 * load preferences from a shareable format (VCM-wise)
+	 * @deprecated WARNING, visibility of this method will be decreased soon
+	 * 	to private and won't be usable in the future.
+	 * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=59258">bug 59258</a>
+	 * TODO (frederic) set visibility from public to private
 	 */
 	 public Preferences loadPreferences() {
 	 	
 	 	Preferences preferences = new Preferences();
-	 	
-//		File prefFile = this.project.getLocation().append(PREF_FILENAME).toFile();
-		IPath projectMetaLocation = getPluginWorkingLocation();
+	 	IPath projectMetaLocation = getPluginWorkingLocation();
 		if (projectMetaLocation != null) {
 			File prefFile = projectMetaLocation.append(PREF_FILENAME).toFile();
 			if (prefFile.exists()) { // load preferences from file
@@ -2165,7 +2299,6 @@
 				try {
 					in = new BufferedInputStream(new FileInputStream(prefFile));
 					preferences.load(in);
-					return preferences;
 				} catch (IOException e) { // problems loading preference store - quietly ignore
 				} finally {
 					if (in != null) {
@@ -2175,11 +2308,14 @@
 						}
 					}
 				}
+				// one shot read, delete old preferences
+				prefFile.delete();
+				return preferences;
 			}
 		}
 		return null;
 	 }
-	 
+
 	/**
 	 * @see IJavaProject#newEvaluationContext()
 	 */
@@ -2192,12 +2328,7 @@
 	 * Returns a new name lookup. This name lookup first looks in the given working copies.
 	 */
 	public NameLookup newNameLookup(ICompilationUnit[] workingCopies) throws JavaModelException {
-
-		JavaProjectElementInfo info = getJavaProjectElementInfo();
-		// lock on the project info to avoid race condition while computing the pkg fragment roots and package fragment caches
-		synchronized(info){
-			return new NameLookup(info.getAllPackageFragmentRoots(this), info.getAllPackageFragments(this), workingCopies);
-		}
+		return getJavaProjectElementInfo().newNameLookup(this, workingCopies);
 	}
 
 	/*
@@ -2213,7 +2344,7 @@
 	/*
 	 * Returns a new search name environment for this project. This name environment first looks in the given working copies.
 	 */
-	public ISearchableNameEnvironment newSearchableNameEnvironment(ICompilationUnit[] workingCopies) throws JavaModelException {
+	public SearchableEnvironment newSearchableNameEnvironment(ICompilationUnit[] workingCopies) throws JavaModelException {
 		return new SearchableEnvironment(this, workingCopies);
 	}
 
@@ -2221,7 +2352,7 @@
 	 * Returns a new search name environment for this project. This name environment first looks in the working copies
 	 * of the given owner.
 	 */
-	public ISearchableNameEnvironment newSearchableNameEnvironment(WorkingCopyOwner owner) throws JavaModelException {
+	public SearchableEnvironment newSearchableNameEnvironment(WorkingCopyOwner owner) throws JavaModelException {
 		return new SearchableEnvironment(this, owner);
 	}
 
@@ -2448,49 +2579,6 @@
 			throw new JavaModelException(e);
 		}
 	}
-	/**
-	 * Save project custom preferences to shareable file (.jprefs)
-	 */
-	private void savePreferences(Preferences preferences) {
-		
-		if (!JavaProject.hasJavaNature(this.project)) return; // ignore
-		
-		if (preferences == null || (!preferences.needsSaving() && preferences.propertyNames().length != 0)) {
-			// nothing to save
-			return;
-		}
-	
-		// preferences need to be saved
-		// the preferences file is located in the plug-in's state area
-		// at a well-known name (.jprefs)
-//		File prefFile = this.project.getLocation().append(PREF_FILENAME).toFile();
-		File prefFile = getPluginWorkingLocation().append(PREF_FILENAME).toFile();
-		if (preferences.propertyNames().length == 0) {
-			// there are no preference settings
-			// rather than write an empty file, just delete any existing file
-			if (prefFile.exists()) {
-				prefFile.delete(); // don't worry if delete unsuccessful
-			}
-			return;
-		}
-		
-		// write file, overwriting an existing one
-		OutputStream out = null;
-		try {
-			// do it as carefully as we know how so that we don't lose/mangle
-			// the setting in times of stress
-			out = new BufferedOutputStream(new FileOutputStream(prefFile));
-			preferences.store(out, null);
-		} catch (IOException e) { // problems saving preference store - quietly ignore
-		} finally {
-			if (out != null) {
-				try {
-					out.close();
-				} catch (IOException e) { // ignore problems with close
-				}
-			}
-		}
-	}
 
 	/**
 	 * Update the Java command in the build spec (replace existing one if present,
@@ -2525,10 +2613,16 @@
 	 */
 	public void setOption(String optionName, String optionValue) {
 		if (!JavaModelManager.getJavaModelManager().optionNames.contains(optionName)) return; // unrecognized option
-		Preferences preferences = getPreferences();
-		preferences.setDefault(optionName, CUSTOM_DEFAULT_OPTION_VALUE); // empty string isn't the default (26251)
-		preferences.setValue(optionName, optionValue);
-		savePreferences(preferences);
+		IEclipsePreferences projectPreferences = getEclipsePreferences();
+		String defaultValue = JavaCore.getOption(optionName);
+		if (defaultValue == null || !defaultValue.equals(optionValue)) {
+			projectPreferences.put(optionName, optionValue);
+			try {
+				projectPreferences.flush();
+			} catch (BackingStoreException e) {
+				// problem with pref store - quietly ignore
+			}
+		}
 	}
 
 	/**
@@ -2536,33 +2630,38 @@
 	 */
 	public void setOptions(Map newOptions) {
 
-		Preferences preferences = getPreferences();
-		if (newOptions != null){
-			Iterator keys = newOptions.keySet().iterator();
-			while (keys.hasNext()){
-				String key = (String)keys.next();
-				if (!JavaModelManager.getJavaModelManager().optionNames.contains(key)) continue; // unrecognized option
-				// no filtering for encoding (custom encoding for project is allowed)
-				String value = (String)newOptions.get(key);
-				preferences.setDefault(key, CUSTOM_DEFAULT_OPTION_VALUE); // empty string isn't the default (26251)
-				preferences.setValue(key, value);
+		IEclipsePreferences projectPreferences = getEclipsePreferences();
+		try {
+			if (newOptions == null){
+				projectPreferences.clear();
+			} else {
+				Iterator keys = newOptions.keySet().iterator();
+				while (keys.hasNext()){
+					String key = (String)keys.next();
+					if (!JavaModelManager.getJavaModelManager().optionNames.contains(key)) continue; // unrecognized option
+					// no filtering for encoding (custom encoding for project is allowed)
+					String value = (String)newOptions.get(key);
+					projectPreferences.put(key, value);
+				}
+				
+				// reset to default all options not in new map
+				// @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=26255
+				// @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=49691
+				String[] pNames = projectPreferences.keys();
+				int ln = pNames.length;
+				for (int i=0; i<ln; i++) {
+					String key = pNames[i];
+					if (!newOptions.containsKey(key)) {
+						projectPreferences.remove(key); // old preferences => remove from preferences table
+					}
+				}
 			}
-		}
-			
-		// reset to default all options not in new map
-		// @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=26255
-		// @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=49691
-		String[] pNames = preferences.propertyNames();
-		int ln = pNames.length;
-		for (int i=0; i<ln; i++) {
-			String key = pNames[i];
-			if (newOptions == null || !newOptions.containsKey(key)) {
-				preferences.setToDefault(key); // set default => remove from preferences table
-			}
-		}
 
-		// persist options
-		savePreferences(preferences);	
+			// persist options
+			projectPreferences.flush();
+		} catch (BackingStoreException e) {
+			// problem with pref store - quietly ignore
+		}
 	}
 
 	/**
@@ -2577,16 +2676,7 @@
 		if (path.equals(getOutputLocation())) {
 			return;
 		}
-		this.setRawClasspath(SetClasspathOperation.ReuseClasspath, path, monitor);
-	}
-
-	/*
-	 * Set cached preferences, no preference file is saved, only info is updated
-	 */
-	public void setPreferences(Preferences preferences) {
-		if (!JavaProject.hasJavaNature(this.project)) return; // ignore
-		JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(this.project, true);
-		perProjectInfo.preferences = preferences;
+		this.setRawClasspath(SetClasspathOperation.REUSE_ENTRIES, path, monitor);
 	}
 
 	/**
@@ -2600,7 +2690,6 @@
 
 		this.project = project;
 		this.parent = JavaModelManager.getJavaModelManager().getJavaModel();
-		this.name = project.getName();
 	}
 
 	/**
@@ -2614,7 +2703,7 @@
 
 		setRawClasspath(
 			entries, 
-			outputLocation, 
+			outputLocation,
 			monitor, 
 			true, // canChangeResource (as per API contract)
 			getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/),
@@ -2665,7 +2754,7 @@
 
 		setRawClasspath(
 			entries, 
-			SetClasspathOperation.ReuseOutputLocation, 
+			SetClasspathOperation.REUSE_PATH, 
 			monitor, 
 			true, // canChangeResource (as per API contract)
 			getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/),
@@ -2690,7 +2779,15 @@
 	public void setSharedProperty(String key, String value) throws CoreException {
 
 		IFile rscFile = this.project.getFile(key);
-		InputStream inputStream = new ByteArrayInputStream(value.getBytes());
+		byte[] bytes = null;
+		try {
+			bytes = value.getBytes("UTF-8"); //$NON-NLS-1$ // .classpath always encoded with UTF-8
+		} catch (UnsupportedEncodingException e) {
+			Util.log(e, "Could not write .classpath with UTF-8 encoding "); //$NON-NLS-1$
+			// fallback to default
+			bytes = value.getBytes();
+		}
+		InputStream inputStream = new ByteArrayInputStream(bytes);
 		// update the resource content
 		if (rscFile.exists()) {
 			if (rscFile.isReadOnly()) {
@@ -2702,64 +2799,44 @@
 			rscFile.create(inputStream, IResource.FORCE, null);
 		}
 	}
-
-	/**
-	 * Update cycle markers for all java projects
-	 * @param preferredClasspaths Map
-	 * @throws JavaModelException
+	
+	/*
+	 * Update .classpath format markers.
 	 */
-	public static void updateAllCycleMarkers(Map preferredClasspaths) throws JavaModelException {
-
-		//long start = System.currentTimeMillis();
-
-		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
-		IProject[] rscProjects = workspaceRoot.getProjects();
-		int length = rscProjects.length;
-		JavaProject[] projects = new JavaProject[length];
-				
-		HashSet cycleParticipants = new HashSet();
-		HashSet traversed = new HashSet();
+	public void updateClasspathMarkers(Map preferredClasspaths, Map preferredOutputs) {
 		
-		// compute cycle participants
-		ArrayList prereqChain = new ArrayList();
-		for (int i = 0; i < length; i++){
-			if (hasJavaNature(rscProjects[i])) {
-				JavaProject project = (projects[i] = (JavaProject)JavaCore.create(rscProjects[i]));
-				if (!traversed.contains(project.getPath())){
-					prereqChain.clear();
-					project.updateCycleParticipants(prereqChain, cycleParticipants, workspaceRoot, traversed, preferredClasspaths);
-				}
-			}
-		}
-		//System.out.println("updateAllCycleMarkers: " + (System.currentTimeMillis() - start) + " ms");
+		this.flushClasspathProblemMarkers(false/*cycle*/, true/*format*/);
+		this.flushClasspathProblemMarkers(false/*cycle*/, false/*format*/);
 
-		for (int i = 0; i < length; i++){
-			JavaProject project = projects[i];
-			if (project != null) {
-				if (cycleParticipants.contains(project.getPath())){
-					IMarker cycleMarker = project.getCycleMarker();
-					String circularCPOption = project.getOption(JavaCore.CORE_CIRCULAR_CLASSPATH, true);
-					int circularCPSeverity = JavaCore.ERROR.equals(circularCPOption) ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING;
-					if (cycleMarker != null) {
-						// update existing cycle marker if needed
-						try {
-							int existingSeverity = ((Integer)cycleMarker.getAttribute(IMarker.SEVERITY)).intValue();
-							if (existingSeverity != circularCPSeverity) {
-								cycleMarker.setAttribute(IMarker.SEVERITY, circularCPSeverity);
-							}
-						} catch (CoreException e) {
-							throw new JavaModelException(e);
-						}
-					} else {
-						// create new marker
-						project.createClasspathProblemMarker(
-							new JavaModelStatus(IJavaModelStatusConstants.CLASSPATH_CYCLE, project)); 
-					}
-				} else {
-					project.flushClasspathProblemMarkers(true, false);
-				}			
+		IClasspathEntry[] classpath = this.readClasspathFile(true/*marker*/, false/*log*/);
+		IPath output = null;
+		// discard the output location
+		if (classpath != null && classpath.length > 0) {
+			IClasspathEntry entry = classpath[classpath.length - 1];
+			if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
+				IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
+				System.arraycopy(classpath, 0, copy, 0, copy.length);
+				classpath = copy;
+				output = entry.getPath();
 			}
+		}					
+		// remember invalid path so as to avoid reupdating it again later on
+		if (preferredClasspaths != null) {
+			preferredClasspaths.put(this, classpath == null ? INVALID_CLASSPATH : classpath);
 		}
+		if (preferredOutputs != null) {
+			preferredOutputs.put(this, output == null ? defaultOutputLocation() : output);
+		}
+		
+		 // force classpath marker refresh
+		 if (classpath != null && output != null) {
+		 	for (int i = 0; i < classpath.length; i++) {
+				IJavaModelStatus status = ClasspathEntry.validateClasspathEntry(this, classpath[i], false/*src attach*/, true /*recurse in container*/);
+				if (!status.isOK()) this.createClasspathProblemMarker(status);					 
+			 }
+			IJavaModelStatus status = ClasspathEntry.validateClasspath(this, classpath, output);
+			if (!status.isOK()) this.createClasspathProblemMarker(status);
+		 }
 	}
 
 	/**
@@ -2812,45 +2889,6 @@
 		prereqChain.remove(path);
 	}
 	
-	/*
-	 * Update .classpath format markers.
-	 */
-	public void updateClasspathMarkers(Map preferredClasspaths, Map preferredOutputs) {
-		
-		this.flushClasspathProblemMarkers(false/*cycle*/, true/*format*/);
-		this.flushClasspathProblemMarkers(false/*cycle*/, false/*format*/);
-
-		IClasspathEntry[] classpath = this.readClasspathFile(true/*marker*/, false/*log*/);
-		IPath output = null;
-		// discard the output location
-		if (classpath != null && classpath.length > 0) {
-			IClasspathEntry entry = classpath[classpath.length - 1];
-			if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
-				IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
-				System.arraycopy(classpath, 0, copy, 0, copy.length);
-				classpath = copy;
-				output = entry.getPath();
-			}
-		}					
-		// remember invalid path so as to avoid reupdating it again later on
-		if (preferredClasspaths != null) {
-			preferredClasspaths.put(this, classpath == null ? INVALID_CLASSPATH : classpath);
-		}
-		if (preferredOutputs != null) {
-			preferredOutputs.put(this, output == null ? defaultOutputLocation() : output);
-		}
-		
-		 // force classpath marker refresh
-		 if (classpath != null && output != null) {
-		 	for (int i = 0; i < classpath.length; i++) {
-				IJavaModelStatus status = ClasspathEntry.validateClasspathEntry(this, classpath[i], false/*src attach*/, true /*recurse in container*/);
-				if (!status.isOK()) this.createClasspathProblemMarker(status);					 
-			 }
-			IJavaModelStatus status = ClasspathEntry.validateClasspath(this, classpath, output);
-			if (!status.isOK()) this.createClasspathProblemMarker(status);
-		 }
-	}
-	
 	/**
 	 * Reset the collection of package fragment roots (local ones) - only if opened.
 	 */
@@ -2869,4 +2907,28 @@
 				}
 			}
 	}
+
+	/*
+	 * Update eclipse preferences from old preferences.
+	 */
+	 private void updatePreferences(IEclipsePreferences preferences) {
+	 	
+	 	Preferences oldPreferences = loadPreferences();
+	 	if (oldPreferences != null) {
+	 		String[] propertyNames = oldPreferences.propertyNames();
+			for (int i = 0; i < propertyNames.length; i++){
+				String propertyName = propertyNames[i];
+			    String propertyValue = oldPreferences.getString(propertyName);
+			    if (!"".equals(propertyValue)) { //$NON-NLS-1$
+				    preferences.put(propertyName, propertyValue);
+			    }
+			}
+			try {
+				// save immediately old preferences
+				preferences.flush();
+			} catch (BackingStoreException e) {
+				// fails silently
+			}
+		}
+	 }
 }
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java
index 2710ef5..42a1c88 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java
@@ -10,8 +10,8 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
-import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Map;
 
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IResource;
@@ -22,6 +22,7 @@
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.internal.core.util.Util;
+import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
 
 /** 
  * Info for IJavaProject.
@@ -48,10 +49,12 @@
 	
 	/*
 	 * A cache of all package fragments in this project.
-	 * (a map from String (the package name) to IPackageFragment[] (the package fragments with this name)
+	 * (a map from String[] (the package name) to IPackageFragmentRoot[] (the package fragment roots that contain a package fragment with this name)
 	 */
-	private HashMap allPkgFragmentsCache;
+	private HashtableOfArrayToObject allPkgFragmentsCache;
 
+	public Map pathToResolvedEntries;
+	
 	/**
 	 * Create and initialize a new instance of the receiver
 	 */
@@ -165,7 +168,9 @@
 	IPackageFragmentRoot[] getAllPackageFragmentRoots(JavaProject project) {
 		if (this.allPkgFragmentRootsCache == null) {
 			try {
-				this.allPkgFragmentRootsCache = project.getAllPackageFragmentRoots();
+				Map reverseMap = new HashMap(3);
+				this.allPkgFragmentRootsCache = project.getAllPackageFragmentRoots(reverseMap);
+				this.pathToResolvedEntries = reverseMap;
 			} catch (JavaModelException e) {
 				// project does not exist: cannot happend since this is the info of the project
 			}
@@ -173,23 +178,32 @@
 		return this.allPkgFragmentRootsCache;
 	}
 	
-	HashMap getAllPackageFragments(JavaProject project) {
+	HashtableOfArrayToObject getAllPackageFragments(JavaProject project) {
 		if (this.allPkgFragmentsCache == null) {
-			HashMap cache = new HashMap();
+			HashtableOfArrayToObject cache = new HashtableOfArrayToObject();
 			IPackageFragmentRoot[] roots = getAllPackageFragmentRoots(project);
-			IPackageFragment[] frags = this.getPackageFragmentsInRoots(roots, project);
-			for (int i= 0; i < frags.length; i++) {
-				IPackageFragment fragment= frags[i];
-				IPackageFragment[] entry= (IPackageFragment[]) cache.get(fragment.getElementName());
-				if (entry == null) {
-					entry= new IPackageFragment[1];
-					entry[0]= fragment;
-					cache.put(fragment.getElementName(), entry);
-				} else {
-					IPackageFragment[] copy= new IPackageFragment[entry.length + 1];
-					System.arraycopy(entry, 0, copy, 0, entry.length);
-					copy[entry.length]= fragment;
-					cache.put(fragment.getElementName(), copy);
+			for (int i = 0, length = roots.length; i < length; i++) {
+				IPackageFragmentRoot root = roots[i];
+				IJavaElement[] frags = null;
+				try {
+					frags = root.getChildren();
+				} catch (JavaModelException e) {
+					// root doesn't exist: ignore
+					continue;
+				}
+				for (int j = 0, length2 = frags.length; j < length2; j++) {
+					PackageFragment fragment= (PackageFragment) frags[j];
+					String[] pkgName = fragment.names;
+					IPackageFragmentRoot[] entry= (IPackageFragmentRoot[]) cache.get(pkgName);
+					if (entry == null) {
+						entry= new IPackageFragmentRoot[] {root};
+						cache.put(pkgName, entry);
+					} else {
+						IPackageFragmentRoot[] copy= new IPackageFragmentRoot[entry.length + 1];
+						System.arraycopy(entry, 0, copy, 0, entry.length);
+						copy[entry.length]= root;
+						cache.put(pkgName, copy);
+					}
 				}
 			}
 			this.allPkgFragmentsCache = cache;
@@ -207,50 +221,6 @@
 		}
 		return this.nonJavaResources;
 	}
-	
-	/**
-	 * Returns all the package fragments found in the specified
-	 * package fragment roots. Make sure the returned fragments have the given
-	 * project as great parent. This ensures the name lookup will not refer to another
-	 * project (through jar package fragment roots)
-	 */
-	private IPackageFragment[] getPackageFragmentsInRoots(IPackageFragmentRoot[] roots, IJavaProject project) {
-
-		// The following code assumes that all the roots have the given project as their parent
-		ArrayList frags = new ArrayList();
-		for (int i = 0; i < roots.length; i++) {
-			IPackageFragmentRoot root = roots[i];
-			try {
-				IJavaElement[] pkgs = root.getChildren();
-
-				/* 2 jar package fragment roots can be equals but not belonging 
-				   to the same project. As a result, they share the same element info.
-				   So this jar package fragment root could get the children of
-				   another jar package fragment root.
-				   The following code ensures that the children of this jar package
-				   fragment root have the given project as a great parent.
-				 */
-				int length = pkgs.length;
-				if (length == 0) continue;
-				if (pkgs[0].getParent().getParent().equals(project)) {
-					// the children have the right parent, simply add them to the list
-					for (int j = 0; j < length; j++) {
-						frags.add(pkgs[j]);
-					}
-				} else {
-					// create a new handle with the root as the parent
-					for (int j = 0; j < length; j++) {
-						frags.add(root.getPackageFragment(pkgs[j].getElementName()));
-					}
-				}
-			} catch (JavaModelException e) {
-				// do nothing
-			}
-		}
-		IPackageFragment[] fragments = new IPackageFragment[frags.size()];
-		frags.toArray(fragments);
-		return fragments;
-	}
 
 	/*
 	 * Returns whether the given path is a classpath entry or an output location.
@@ -271,11 +241,25 @@
 	}
 	
 	/*
+	 * Creates a new name lookup for this project info. 
+	 * The given project is assumed to be the handle of this info.
+	 * This name lookup first looks in the given working copies.
+	 */
+	synchronized NameLookup newNameLookup(JavaProject project, ICompilationUnit[] workingCopies) {
+		// note that this method has to be synchronized so that the field pathToResolvedEntries is not reset while computing the roots and package fragments
+		// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=79766)
+		return new NameLookup(getAllPackageFragmentRoots(project), getAllPackageFragments(project), workingCopies, this.pathToResolvedEntries);
+	}
+	
+	/*
 	 * Reset the package fragment roots and package fragment caches
 	 */
-	void resetCaches() {
+	synchronized void resetCaches() {
+		// note that this method has to be synchronized so that the field pathToResolvedEntries is not reset while computing the roots and package fragments
+		// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=79766)
 		this.allPkgFragmentRootsCache = null;
 		this.allPkgFragmentsCache = null;
+		this.pathToResolvedEntries = null;
 	}
 	
 	/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LocalVariable.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LocalVariable.java
index 22d77c0..d1f7036 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LocalVariable.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LocalVariable.java
@@ -23,8 +23,9 @@
 import org.eclipse.jdt.internal.core.util.Util;
 
 
-public class LocalVariable extends JavaElement implements ILocalVariable {
+public class LocalVariable extends SourceRefElement implements ILocalVariable {
 
+	String name;
 	public int declarationSourceStart, declarationSourceEnd;
 	public int nameStart, nameEnd;
 	String typeSignature;
@@ -38,7 +39,8 @@
 			int nameEnd,
 			String typeSignature) {
 		
-		super(parent, name);
+		super(parent);
+		this.name = name;
 		this.declarationSourceStart = declarationSourceStart;
 		this.declarationSourceEnd = declarationSourceEnd;
 		this.nameStart = nameStart;
@@ -83,10 +85,10 @@
 	}
 
 	/*
-	 * @see JavaElement#getHandleMemento()
+	 * @see JavaElement#getHandleMemento(StringBuffer)
 	 */
-	public String getHandleMemento(){
-		StringBuffer buff= new StringBuffer(((JavaElement)getParent()).getHandleMemento());
+	protected void getHandleMemento(StringBuffer buff) {
+		((JavaElement)getParent()).getHandleMemento(buff);
 		buff.append(getHandleMementoDelimiter());
 		buff.append(this.name);
 		buff.append(JEM_COUNT);
@@ -103,7 +105,6 @@
 			buff.append(JEM_COUNT);
 			buff.append(this.occurrenceCount);
 		}
-		return buff.toString();
 	}
 
 	protected char getHandleMementoDelimiter() {
@@ -113,6 +114,10 @@
 	public IResource getCorrespondingResource() {
 		return null;
 	}
+	
+	public String getElementName() {
+		return this.name;
+	}
 
 	public int getElementType() {
 		return LOCAL_VARIABLE;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
index 388336f..bb04b9e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
@@ -32,10 +32,11 @@
  */
 
 public abstract class Member extends SourceRefElement implements IMember {
-protected Member(JavaElement parent, String name) {
-	super(parent, name);
+
+protected Member(JavaElement parent) {
+	super(parent);
 }
-protected boolean areSimilarMethods(
+protected static boolean areSimilarMethods(
 	String name1, String[] params1, 
 	String name2, String[] params2,
 	String[] simpleNames1) {
@@ -46,9 +47,9 @@
 			for (int i = 0; i < params1Length; i++) {
 				String simpleName1 = 
 					simpleNames1 == null ? 
-						Signature.getSimpleName(Signature.toString(params1[i])) :
+						Signature.getSimpleName(Signature.toString(Signature.getTypeErasure(params1[i]))) :
 						simpleNames1[i];
-				String simpleName2 = Signature.getSimpleName(Signature.toString(params2[i]));
+				String simpleName2 = Signature.getSimpleName(Signature.toString(Signature.getTypeErasure(params2[i])));
 				if (!simpleName1.equals(simpleName2)) {
 					return false;
 				}
@@ -85,7 +86,7 @@
 			return new Long(constant.longValue());
 		case TypeIds.T_short :
 			return new Short(constant.shortValue());
-		case TypeIds.T_String :
+		case TypeIds.T_JavaLangString :
 			return constant.stringValue();
 		default :
 			return null;
@@ -102,18 +103,19 @@
 /*
  * Helper method for SourceType.findMethods and BinaryType.findMethods
  */
-protected IMethod[] findMethods(IMethod method, IMethod[] methods) {
+public static IMethod[] findMethods(IMethod method, IMethod[] methods) {
 	String elementName = method.getElementName();
 	String[] parameters = method.getParameterTypes();
 	int paramLength = parameters.length;
 	String[] simpleNames = new String[paramLength];
 	for (int i = 0; i < paramLength; i++) {
-		simpleNames[i] = Signature.getSimpleName(Signature.toString(parameters[i]));
+		String erasure = Signature.getTypeErasure(parameters[i]);
+		simpleNames[i] = Signature.getSimpleName(Signature.toString(erasure));
 	}
 	ArrayList list = new ArrayList();
 	next: for (int i = 0, length = methods.length; i < length; i++) {
 		IMethod existingMethod = methods[i];
-		if (this.areSimilarMethods(
+		if (areSimilarMethods(
 				elementName,
 				parameters,
 				existingMethod.getElementName(),
@@ -183,18 +185,34 @@
 				return type.getHandleFromMemento(token, memento, workingCopyOwner);
 			}
 		case JEM_LOCALVARIABLE:
+			if (!memento.hasMoreTokens()) return this;
 			String varName = memento.nextToken();
+			if (!memento.hasMoreTokens()) return this;
 			memento.nextToken(); // JEM_COUNT
+			if (!memento.hasMoreTokens()) return this;
 			int declarationStart = Integer.parseInt(memento.nextToken());
+			if (!memento.hasMoreTokens()) return this;
 			memento.nextToken(); // JEM_COUNT
+			if (!memento.hasMoreTokens()) return this;
 			int declarationEnd = Integer.parseInt(memento.nextToken());
+			if (!memento.hasMoreTokens()) return this;
 			memento.nextToken(); // JEM_COUNT
+			if (!memento.hasMoreTokens()) return this;
 			int nameStart = Integer.parseInt(memento.nextToken());
+			if (!memento.hasMoreTokens()) return this;
 			memento.nextToken(); // JEM_COUNT
+			if (!memento.hasMoreTokens()) return this;
 			int nameEnd = Integer.parseInt(memento.nextToken());
+			if (!memento.hasMoreTokens()) return this;
 			memento.nextToken(); // JEM_COUNT
+			if (!memento.hasMoreTokens()) return this;
 			String typeSignature = memento.nextToken();
 			return new LocalVariable(this, varName, declarationStart, declarationEnd, nameStart, nameEnd, typeSignature);
+		case JEM_TYPE_PARAMETER:
+			if (!memento.hasMoreTokens()) return this;
+			String typeParameterName = memento.nextToken();
+			JavaElement typeParameter = new TypeParameter(this, typeParameterName);
+			return typeParameter.getHandleFromMemento(memento, workingCopyOwner);
 	}
 	return null;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MemberElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MemberElementInfo.java
index 379bfe5..ae91903 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MemberElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MemberElementInfo.java
@@ -34,10 +34,6 @@
 	protected int nameEnd= -1;
 
 	/**
-	 * This member's name
-	 */
-	protected char[] name;
-	/**
 	 * @see org.eclipse.jdt.internal.compiler.env.IGenericType#getModifiers()
 	 * @see org.eclipse.jdt.internal.compiler.env.IGenericMethod#getModifiers()
 	 * @see org.eclipse.jdt.internal.compiler.env.IGenericField#getModifiers()
@@ -46,12 +42,6 @@
 		return this.flags;
 	}
 	/**
-	 * @see org.eclipse.jdt.internal.compiler.env.ISourceType#getName()
-	 */
-	public char[] getName() {
-		return this.name;
-	}
-	/**
 	 * @see org.eclipse.jdt.internal.compiler.env.ISourceType#getNameSourceEnd()
 	 * @see org.eclipse.jdt.internal.compiler.env.ISourceMethod#getNameSourceEnd()
 	 * @see org.eclipse.jdt.internal.compiler.env.ISourceField#getNameSourceEnd()
@@ -71,12 +61,6 @@
 		this.flags = flags;
 	}
 	/**
-	 * Sets this member's name
-	 */
-	protected void setName(char[] name) {
-		this.name= name;
-	}
-	/**
 	 * Sets the last position of this member's name, relative
 	 * to its openable's source buffer.
 	 */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MultiOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MultiOperation.java
index 212db65..cef01a8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MultiOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MultiOperation.java
@@ -267,7 +267,7 @@
 	
 		switch (element.getElementType()) {
 			case IJavaElement.PACKAGE_FRAGMENT :
-				if (element.getElementName().equals(IPackageFragment.DEFAULT_PACKAGE_NAME)) {
+				if (((IPackageFragment) element).isDefaultPackage()) {
 					// don't allow renaming of default package (see PR #1G47GUM)
 					throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.NAME_COLLISION, element));
 				}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
index dc0234a..40a999e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
@@ -32,11 +32,16 @@
 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.core.search.IJavaSearchConstants;
 import org.eclipse.jdt.core.search.ITypeNameRequestor;
 import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
 import org.eclipse.jdt.internal.core.util.Util;
 
 /**
@@ -56,15 +61,33 @@
  *
  */
 public class NameLookup implements SuffixConstants {
+	// TODO (jerome) suppress the accept flags (qualified name is sufficient to find a type)
 	/**
 	 * Accept flag for specifying classes.
 	 */
-	public static final int ACCEPT_CLASSES = 0x00000002;
+	public static final int ACCEPT_CLASSES = ASTNode.Bit2;
 
 	/**
 	 * Accept flag for specifying interfaces.
 	 */
-	public static final int ACCEPT_INTERFACES = 0x00000004;
+	public static final int ACCEPT_INTERFACES = ASTNode.Bit3;
+	
+	/**
+	 * Accept flag for specifying enums.
+	 */
+	public static final int ACCEPT_ENUMS = ASTNode.Bit4;
+
+	/**
+	 * Accept flag for specifying annotations.
+	 */
+	public static final int ACCEPT_ANNOTATIONS = ASTNode.Bit5;
+	
+	/*
+	 * Accept flag for all kinds of types
+	 */
+	public static final int ACCEPT_ALL = ACCEPT_CLASSES | ACCEPT_INTERFACES | ACCEPT_ENUMS | ACCEPT_ANNOTATIONS;
+
+	public static boolean VERBOSE = false;
 
 	/**
 	 * The <code>IPackageFragmentRoot</code>'s associated
@@ -74,32 +97,91 @@
 	protected IPackageFragmentRoot[] packageFragmentRoots;
 
 	/**
-	 * Table that maps package names to lists of package fragments for
-	 * all package fragments in the package fragment roots known
+	 * Table that maps package names to lists of package fragment roots
+	 * that contain such a package known
 	 * by this name lookup facility. To allow > 1 package fragment
-	 * with the same name, values are arrays of package fragments
+	 * with the same name, values are arrays of package fragment roots
 	 * ordered as they appear on the classpath.
 	 */
-	protected Map packageFragments;
+	protected HashtableOfArrayToObject packageFragments;
 
 	/**
-	 * A map from compilation unit handles to units to look inside (compilation
-	 * units or working copies).
+	 * Reverse map from root path to corresponding resolved CP entry
+	 * (so as to be able to figure inclusion/exclusion rules)
+	 */
+	protected Map rootToResolvedEntries;
+	
+	/**
+	 * A map from package handles to a map from type name to an IType of an IType[].
 	 * Allows working copies to take precedence over compilation units.
 	 */
 	protected HashMap unitsToLookInside;
+	
+	public long timeSpentInSeekTypesInSourcePackage = 0;
 
-	public NameLookup(IPackageFragmentRoot[] packageFragmentRoots, HashMap packageFragments, ICompilationUnit[] workingCopies) {
+	public NameLookup(IPackageFragmentRoot[] packageFragmentRoots, HashtableOfArrayToObject packageFragments, ICompilationUnit[] workingCopies, Map rootToResolvedEntries) {
+		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$
+		}
 		this.packageFragmentRoots = packageFragmentRoots;
-		this.packageFragments = packageFragments;
+		try {
+			this.packageFragments = (HashtableOfArrayToObject) packageFragments.clone();
+		} catch (CloneNotSupportedException e1) {
+			// ignore (implementation of HashtableOfArrayToObject supports cloning)
+		}
 		if (workingCopies != null) {
 			this.unitsToLookInside = new HashMap();
+			HashSet visited = new HashSet();
 			for (int i = 0, length = workingCopies.length; i < length; i++) {
-				ICompilationUnit unitToLookInside = workingCopies[i];
-				ICompilationUnit original = unitToLookInside.getPrimary();
-				this.unitsToLookInside.put(original, unitToLookInside);
+				ICompilationUnit workingCopy = workingCopies[i];
+				PackageFragment pkg = (PackageFragment) workingCopy.getParent();
+				HashMap typeMap = (HashMap) this.unitsToLookInside.get(pkg);
+				if (typeMap == null) {
+					typeMap = new HashMap();
+					this.unitsToLookInside.put(pkg, typeMap);
+				}
+				try {
+					IType[] types = workingCopy.getTypes();
+					for (int j = 0, typeLength = types.length; j < typeLength; j++) {
+						IType type = types[j];
+						String typeName = type.getElementName();
+						Object existing = typeMap.get(typeName);
+						if (existing == null) {
+							typeMap.put(typeName, type);
+						} else if (existing instanceof IType) {
+							typeMap.put(typeName, new IType[] {(IType) existing, type});
+						} else {
+							IType[] existingTypes = (IType[]) existing;
+							int existingTypeLength = existingTypes.length;
+							System.arraycopy(existingTypes, 0, existingTypes = new IType[existingTypeLength+1], 0, existingTypeLength);
+							existingTypes[existingTypeLength] = type;
+							typeMap.put(typeName, existingTypes);
+						}
+					}
+				} catch (JavaModelException e) {
+					// working copy doesn't exist -> ignore
+				}
+				
+				// add root of package fragment to cache
+				IPackageFragmentRoot root = (IPackageFragmentRoot) pkg.getParent();
+				if (visited.contains(root)) continue;
+				String[] pkgName = pkg.names;
+				IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) packageFragments.get(pkgName);
+				if (roots == null) {
+					this.packageFragments.put(pkgName, new IPackageFragmentRoot[] {root});
+				} else {
+					int rootLength = roots.length;
+					System.arraycopy(roots, 0, roots = new IPackageFragmentRoot[rootLength+1], 0, rootLength);
+					roots[rootLength] = root;
+					this.packageFragments.put(pkgName, roots);
+				}
+				visited.add(root);
 			}
 		}
+		this.rootToResolvedEntries = rootToResolvedEntries;
 	}
 
 	/**
@@ -113,14 +195,23 @@
 	 *  </ul>
 	 * Otherwise, false is returned. 
 	 */
-	protected boolean acceptType(IType type, int acceptFlags) {
-		if (acceptFlags == 0)
-			return true; // no flags, always accepted
+	protected boolean acceptType(IType type, int acceptFlags, boolean isSourceType) {
+		if (acceptFlags == 0 || acceptFlags == ACCEPT_ALL)
+			return true; // no flags or all flags, always accepted
 		try {
-			if (type.isClass()) {
-				return (acceptFlags & ACCEPT_CLASSES) != 0;
-			} else {
-				return (acceptFlags & ACCEPT_INTERFACES) != 0;
+			int kind = isSourceType
+					? ((SourceTypeElementInfo) ((SourceType) type).getElementInfo()).getKind() 
+					: ((IBinaryType) ((BinaryType) type).getElementInfo()).getKind();
+			switch (kind) {
+				case IGenericType.CLASS_DECL :
+					return (acceptFlags & ACCEPT_CLASSES) != 0;
+				case IGenericType.INTERFACE_DECL :
+					return (acceptFlags & ACCEPT_INTERFACES) != 0;
+				case IGenericType.ENUM_DECL :
+					return (acceptFlags & ACCEPT_ENUMS) != 0;
+				default:
+					//case IGenericType.ANNOTATION_TYPE :
+					return (acceptFlags & ACCEPT_ANNOTATIONS) != 0;
 			}
 		} catch (JavaModelException npe) {
 			return false; // the class is not present, do not accept.
@@ -167,27 +258,34 @@
 	 * The name must be fully qualified (eg "java.lang.Object", "java.util.Hashtable$Entry")
 	 */
 	public ICompilationUnit findCompilationUnit(String qualifiedTypeName) {
-		String pkgName= IPackageFragment.DEFAULT_PACKAGE_NAME;
-		String cuName= qualifiedTypeName;
+		String[] pkgName = CharOperation.NO_STRINGS;
+		String cuName = qualifiedTypeName;
 
 		int index= qualifiedTypeName.lastIndexOf('.');
 		if (index != -1) {
-			pkgName= qualifiedTypeName.substring(0, index);
+			pkgName= Util.splitOn('.', qualifiedTypeName, 0, index);
 			cuName= qualifiedTypeName.substring(index + 1);
 		}
 		index= cuName.indexOf('$');
 		if (index != -1) {
 			cuName= cuName.substring(0, index);
 		}
-		cuName += SUFFIX_STRING_java;
-		IPackageFragment[] frags= (IPackageFragment[]) this.packageFragments.get(pkgName);
-		if (frags != null) {
-			for (int i= 0; i < frags.length; i++) {
-				IPackageFragment frag= frags[i];
-				if (!(frag instanceof JarPackageFragment)) {
-					ICompilationUnit cu= frag.getCompilationUnit(cuName);
-					if (cu != null && cu.exists()) {
-						return cu;
+		IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) this.packageFragments.get(pkgName);
+		if (roots != null) {
+			for (int i= 0; i < roots.length; i++) {
+				PackageFragmentRoot root= (PackageFragmentRoot) roots[i];
+				if (!root.isArchive()) {
+					IPackageFragment pkg = root.getPackageFragment(pkgName);
+					try {
+						ICompilationUnit[] cus = pkg.getCompilationUnits();
+						for (int j = 0, length = cus.length; j < length; j++) {
+							ICompilationUnit cu = cus[j];
+							if (Util.equalsIgnoreJavaLikeExtension(cu.getElementName(), cuName))
+								return cu;
+						}
+					} catch (JavaModelException e) {
+						// pkg does not exist
+						// -> try next package
 					}
 				}
 			}
@@ -209,7 +307,7 @@
 			throw new IllegalArgumentException(Util.bind("path.mustBeAbsolute")); //$NON-NLS-1$
 		}
 /*
- * this code should rather use the package fragment map to find the candidate package, then
+ * TODO (jerome) this code should rather use the package fragment map to find the candidate package, then
  * check if the respective enclosing root maps to the one on this given IPath.
  */		
 		IResource possibleFragment = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
@@ -258,13 +356,13 @@
 						if (entry != null) {
 							IPackageFragmentRoot root =
 								project.getPackageFragmentRoot(project.getResource());
-							IPackageFragment[] pkgs = (IPackageFragment[]) this.packageFragments.get(IPackageFragment.DEFAULT_PACKAGE_NAME);
-							if (pkgs == null) {
+							IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) this.packageFragments.get(CharOperation.NO_STRINGS);
+							if (roots == null) {
 								return null;
 							}
-							for (int i = 0; i < pkgs.length; i++) {
-								if (pkgs[i].getParent().equals(root)) {
-									return pkgs[i];
+							for (int i = 0; i < roots.length; i++) {
+								if (roots[i].equals(root)) {
+									return  ((PackageFragmentRoot) root).getPackageFragment(CharOperation.NO_STRINGS);
 								}
 							}
 						}
@@ -273,7 +371,7 @@
 					}
 					return null;
 				case IJavaElement.PACKAGE_FRAGMENT_ROOT:
-					return ((IPackageFragmentRoot)fromFactory).getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
+					return ((PackageFragmentRoot)fromFactory).getPackageFragment(CharOperation.NO_STRINGS);
 			}
 		}
 		return null;
@@ -290,48 +388,44 @@
 	 *	only exact name matches qualify when <code>false</code>
 	 */
 	public IPackageFragment[] findPackageFragments(String name, boolean partialMatch) {
-		int count= this.packageFragmentRoots.length;
 		if (partialMatch) {
-			name= name.toLowerCase();
-			for (int i= 0; i < count; i++) {
-				IPackageFragmentRoot root= this.packageFragmentRoots[i];
-				IJavaElement[] list= null;
-				try {
-					list= root.getChildren();
-				} catch (JavaModelException npe) {
-					continue; // the package fragment root is not present;
-				}
-				int elementCount= list.length;
-				IPackageFragment[] result = new IPackageFragment[elementCount];
-				int resultLength = 0; 
-				for (int j= 0; j < elementCount; j++) {
-					IPackageFragment packageFragment= (IPackageFragment) list[j];
-					if (nameMatches(name, packageFragment, true)) {
-						result[resultLength++] = packageFragment;
+			String[] splittedName = Util.splitOn('.', name, 0, name.length());
+			IPackageFragment[] oneFragment = null;
+			ArrayList pkgs = null;
+			Object[][] keys = this.packageFragments.keyTable;
+			for (int i = 0, length = keys.length; i < length; i++) {
+				String[] pkgName = (String[]) keys[i];
+				if (pkgName != null && Util.startsWithIgnoreCase(pkgName, splittedName)) {
+					IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) this.packageFragments.valueTable[i];
+					for (int j = 0, length2 = roots.length; j < length2; j++) {
+						PackageFragmentRoot root = (PackageFragmentRoot) roots[j];
+						IPackageFragment pkg = root.getPackageFragment(pkgName);
+						if (oneFragment == null) {
+							oneFragment = new IPackageFragment[] {pkg};
+						} else {
+							if (pkgs == null) {
+								pkgs = new ArrayList();
+								pkgs.add(oneFragment[0]);
+							}
+							pkgs.add(pkg);
+						}
 					}
 				}
-				if (resultLength > 0) {
-					System.arraycopy(result, 0, result = new IPackageFragment[resultLength], 0, resultLength);
-					return result;
-				} else {
-					return null;
-				}
 			}
+			if (pkgs == null) return oneFragment;
+			int resultLength = pkgs.size();
+			IPackageFragment[] result = new IPackageFragment[resultLength];
+			pkgs.toArray(result);
+			return result;
 		} else {
-			IPackageFragment[] fragments= (IPackageFragment[]) this.packageFragments.get(name);
-			if (fragments != null) {
-				IPackageFragment[] result = new IPackageFragment[fragments.length];
-				int resultLength = 0; 
-				for (int i= 0; i < fragments.length; i++) {
-					IPackageFragment packageFragment= fragments[i];
-					result[resultLength++] = packageFragment;
+			String[] splittedName = Util.splitOn('.', name, 0, name.length());
+			IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) this.packageFragments.get(splittedName);
+			if (roots != null) {
+				IPackageFragment[] result = new IPackageFragment[roots.length];
+				for (int i= 0; i < roots.length; i++) {
+					result[i] = ((PackageFragmentRoot) roots[i]).getPackageFragment(splittedName);
 				}
-				if (resultLength > 0) {
-					System.arraycopy(result, 0, result = new IPackageFragment[resultLength], 0, resultLength);
-					return result;
-				} else {
-					return null;
-				}
+				return result;
 			}
 		}
 		return null;
@@ -358,6 +452,16 @@
 		}
 		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);
+		}
+		return type;
+	}
 
 	/**
 	 * Returns the first type in the given package whose name
@@ -375,6 +479,8 @@
 	 *
 	 * @see #ACCEPT_CLASSES
 	 * @see #ACCEPT_INTERFACES
+	 * @see #ACCEPT_ENUMS
+	 * @see #ACCEPT_ANNOTATIONS
 	 */
 	public IType findType(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags) {
 		if (pkg == null) return null;
@@ -421,7 +527,7 @@
 				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.compiler.util.Util.isJavaFileName(pathname)) {
+					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);
@@ -449,6 +555,8 @@
 	 *
 	 * @see #ACCEPT_CLASSES
 	 * @see #ACCEPT_INTERFACES
+	 * @see #ACCEPT_ENUMS
+	 * @see #ACCEPT_ANNOTATIONS
 	 */
 	public IType findType(String name, boolean partialMatch, int acceptFlags) {
 		int index= name.lastIndexOf('.');
@@ -482,6 +590,24 @@
 	}
 
 	/**
+	 * Returns true if the given cu's name matches the
+	 * specified <code>searchName</code>, otherwise false.
+	 *
+	 * <p>The <code>partialMatch</code> argument indicates partial matches
+	 * should be considered.
+	 * NOTE: in partialMatch mode, the case will be ignored, and the searchName must already have
+	 *          been lowercased.
+	 */
+	protected boolean nameMatches(String searchName, ICompilationUnit cu, boolean partialMatch) {
+		if (partialMatch) {
+			// partial matches are used in completion mode, thus case insensitive mode
+			return cu.getElementName().toLowerCase().startsWith(searchName);
+		} else {
+			return Util.equalsIgnoreJavaLikeExtension(cu.getElementName(), searchName);
+		}
+	}
+
+	/**
 	 * Notifies the given requestor of all package fragments with the
 	 * given name. Checks the requestor at regular intervals to see if the
 	 * requestor has canceled. The domain of
@@ -492,25 +618,38 @@
 	 *	only exact name matches qualify when <code>false</code>
 	 */
 	public void seekPackageFragments(String name, boolean partialMatch, IJavaElementRequestor requestor) {
-		int count= this.packageFragmentRoots.length;
-		String matchName= partialMatch ? name.toLowerCase() : name;
-		for (int i= 0; i < count; i++) {
-			if (requestor.isCanceled())
-				return;
-			IPackageFragmentRoot root= this.packageFragmentRoots[i];
-			IJavaElement[] list= null;
-			try {
-				list= root.getChildren();
-			} catch (JavaModelException npe) {
-				continue; // this root package fragment is not present
-			}
-			int elementCount= list.length;
-			for (int j= 0; j < elementCount; j++) {
+/*		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$
+		}
+*/		if (partialMatch) {
+			String[] splittedName = Util.splitOn('.', name, 0, name.length());
+			Object[][] keys = this.packageFragments.keyTable;
+			for (int i = 0, length = keys.length; i < length; i++) {
 				if (requestor.isCanceled())
 					return;
-				IPackageFragment packageFragment= (IPackageFragment) list[j];
-				if (nameMatches(matchName, packageFragment, partialMatch))
-					requestor.acceptPackageFragment(packageFragment);
+				String[] pkgName = (String[]) keys[i];
+				if (pkgName != null && Util.startsWithIgnoreCase(pkgName, splittedName)) {
+					IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) this.packageFragments.valueTable[i];
+					for (int j = 0, length2 = roots.length; j < length2; j++) {
+						if (requestor.isCanceled())
+							return;
+						PackageFragmentRoot root = (PackageFragmentRoot) roots[j];
+						requestor.acceptPackageFragment(root.getPackageFragment(pkgName));					
+					}
+				}
+			}
+		} else {
+			String[] splittedName = Util.splitOn('.', name, 0, name.length());
+			IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) this.packageFragments.get(splittedName);
+			if (roots != null) {
+				for (int i = 0, length = roots.length; i < length; i++) {
+					if (requestor.isCanceled())
+						return;
+					PackageFragmentRoot root = (PackageFragmentRoot) roots[i];
+					requestor.acceptPackageFragment(root.getPackageFragment(splittedName));
+				}
 			}
 		}
 	}
@@ -532,13 +671,18 @@
 	 *
 	 * @see #ACCEPT_CLASSES
 	 * @see #ACCEPT_INTERFACES
+	 * @see #ACCEPT_ENUMS
+	 * @see #ACCEPT_ANNOTATIONS
 	 */
 	public void seekTypes(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
-
-		String matchName= partialMatch ? name.toLowerCase() : name;
-		if (matchName.indexOf('.') >= 0) { //looks for member type A.B
-			matchName= matchName.replace('.', '$');
+/*		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$
 		}
+*/
+		String matchName= partialMatch ? name.toLowerCase() : name;
 		if (pkg == null) {
 			findAllTypes(matchName, partialMatch, acceptFlags, requestor);
 			return;
@@ -548,6 +692,7 @@
 			int packageFlavor= root.getKind();
 			switch (packageFlavor) {
 				case IPackageFragmentRoot.K_BINARY :
+					matchName= matchName.replace('.', '$');
 					seekTypesInBinaryPackage(matchName, pkg, partialMatch, acceptFlags, requestor);
 					break;
 				case IPackageFragmentRoot.K_SOURCE :
@@ -577,12 +722,9 @@
 		int index= name.lastIndexOf('$');
 		if (index != -1) {
 			//the type name of the inner type
-			unqualifiedName= name.substring(index + 1, name.length());
+			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
-			if ((unqualifiedName.length() > 0 && Character.isDigit(unqualifiedName.charAt(0))) || unqualifiedName.length() == 0){
-				unqualifiedName = name;
-			}
 		}
 		String matchName= partialMatch ? name.toLowerCase() : name;
 		for (int i= 0; i < length; i++) {
@@ -604,7 +746,7 @@
 					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))
+					if (nameMatches(unqualifiedName, type, partialMatch) && acceptType(type, acceptFlags, false/*not a source type*/))
 						requestor.acceptType(type);
 				}
 			}
@@ -616,115 +758,106 @@
 	 */
 	protected void seekTypesInSourcePackage(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
 		
-		ICompilationUnit[] compilationUnits = null;
+		long start = -1;
+		if (VERBOSE)
+			start = System.currentTimeMillis();
 		try {
-			compilationUnits = pkg.getCompilationUnits();
-		} catch (JavaModelException npe) {
-			return; // the package is not present
-		}
-
-		// replace with working copies to look inside
-		int length= compilationUnits.length;
-		boolean[] isWorkingCopy = new boolean[length];
-		int workingCopiesSize;
-		if (this.unitsToLookInside != null && (workingCopiesSize = this.unitsToLookInside.size()) > 0) {
-			Map temp = new HashMap(workingCopiesSize);
-			temp.putAll(this.unitsToLookInside);
-			for (int i = 0; i < length; i++) {
-				ICompilationUnit unit = compilationUnits[i];
-				ICompilationUnit workingCopy = (ICompilationUnit)temp.remove(unit);
-				if (workingCopy != null) {
-					compilationUnits[i] = workingCopy;
-					isWorkingCopy[i] = true;
-				}
-			}
-			// add remaining working copies that belong to this package
-			int index = 0;
-			Collection values = temp.values();
-			Iterator iterator = values.iterator();
-			while (iterator.hasNext()) {
-				ICompilationUnit workingCopy = (ICompilationUnit)iterator.next();
-				if (pkg.equals(workingCopy.getParent())) {
-					if (index == 0) {
-						int valuesLength = values.size();
-						index = length;
-						length += valuesLength;
-						System.arraycopy(compilationUnits, 0, compilationUnits = new ICompilationUnit[length], 0, index);
-						System.arraycopy(isWorkingCopy, 0, isWorkingCopy = new boolean[length], 0, index);
+			if (!partialMatch) {
+				int firstDot = name.indexOf('.');
+				String topLevelTypeName = firstDot == -1 ? name : name.substring(0, firstDot);
+				
+				// look in unitsToLookInside first
+				HashMap typeMap = (HashMap) (this.unitsToLookInside == null ? null : this.unitsToLookInside.get(pkg));
+				if (typeMap != null) {
+					Object object = typeMap.get(topLevelTypeName);
+					if (object instanceof IType) {
+						IType type = getMemberType((IType) object, name, firstDot);
+						if (acceptType(type, acceptFlags, true/*a source type*/)) {
+							requestor.acceptType(type);
+							return; // don't continue with compilation unit
+						}
+					} else if (object instanceof IType[]) {
+						IType[] topLevelTypes = (IType[]) object;
+						for (int i = 0, length = topLevelTypes.length; i < length; i++) {
+							if (requestor.isCanceled())
+								return;
+							IType type = getMemberType(topLevelTypes[i], name, firstDot);
+							if (acceptType(type, acceptFlags, true/*a source type*/)) {
+								requestor.acceptType(type);
+								return; // return the first one
+							}
+						}
 					}
-					isWorkingCopy[index] = true; 
-					compilationUnits[index++] = workingCopy;
 				}
-			}
-			if (index > 0 && index < length) {
-				System.arraycopy(compilationUnits, 0, compilationUnits = new ICompilationUnit[index], 0, index);
-				System.arraycopy(isWorkingCopy, 0, isWorkingCopy = new boolean[index], 0, index);
-				length = index;
-			}
-		}
-			
-		String matchName = name;
-		int index= name.indexOf('$');
-		boolean potentialMemberType = false;
-		String potentialMatchName = null;
-		if (index != -1) {
-			//the compilation unit name of the inner type
-			potentialMatchName = name.substring(0, index);
-			potentialMemberType = true;
-		}
-
-		/**
-		 * In the following, matchName will never have the extension ".java" and 
-		 * the compilationUnits always will. So add it if we're looking for 
-		 * an exact match.
-		 */
-		String unitName = partialMatch ? matchName.toLowerCase() : matchName + SUFFIX_STRING_java;
-		String potentialUnitName = null;
-		if (potentialMemberType) {
-			potentialUnitName = partialMatch ? potentialMatchName.toLowerCase() : potentialMatchName + SUFFIX_STRING_java;
-		}
-
-		for (int i= 0; i < length; i++) {
-			if (requestor.isCanceled())
-				return;
-			ICompilationUnit compilationUnit= compilationUnits[i];
-			
-			if ((isWorkingCopy[i] && !potentialMemberType)
-					|| nameMatches(unitName, compilationUnit, partialMatch)) {
-						
-				IType[] types= null;
+				
+				// look in compilation units
 				try {
-					types= compilationUnit.getTypes();
-				} catch (JavaModelException npe) {
-					continue; // the compilation unit is not present
+					ICompilationUnit[] compilationUnits = pkg.getCompilationUnits();
+					for (int i = 0, length = compilationUnits.length; i < length; i++) {
+						if (requestor.isCanceled())
+							return;
+						ICompilationUnit cu = compilationUnits[i];
+						String cuName = cu.getElementName();
+						int lastDot = cuName.lastIndexOf('.');
+						if (!topLevelTypeName.equals(cuName.substring(0, lastDot))) 
+							continue;
+						IType type = cu.getType(topLevelTypeName);
+						type = getMemberType(type, name, firstDot);
+						if (acceptType(type, acceptFlags, true/*a source type*/)) { // accept type checks for existence
+							requestor.acceptType(type);
+							break;  // since an exact match was requested, no other matching type can exist
+						}
+					}
+				} catch (JavaModelException e) {
+					// package doesn't exist -> ignore
 				}
-				int typeLength= types.length;
-				for (int j= 0; j < typeLength; j++) {
-					if (requestor.isCanceled())
-						return;
-					IType type= types[j];
-					if (nameMatches(matchName, type, partialMatch)) {
-						if (acceptType(type, acceptFlags)) requestor.acceptType(type);
+			} else {
+				String prefix = name.toLowerCase();
+				int firstDot = prefix.indexOf('.');
+				
+				// look in unitsToLookInside first
+				HashMap typeMap = (HashMap) (this.unitsToLookInside == null ? null : this.unitsToLookInside.get(pkg));
+				if (typeMap != null) {
+					Iterator iterator = typeMap.values().iterator();
+					while (iterator.hasNext()) {
+						if (requestor.isCanceled())
+							return;
+						Object object = iterator.next();
+						if (object instanceof IType) {
+							seekTypesInTopLevelType(prefix, firstDot, (IType) object, requestor, acceptFlags);
+						} else if (object instanceof IType[]) {
+							IType[] topLevelTypes = (IType[]) object;
+							for (int i = 0, length = topLevelTypes.length; i < length; i++)
+								seekTypesInTopLevelType(prefix, firstDot, topLevelTypes[i], requestor, acceptFlags);
+						}
 					}
 				}
-			} else if (potentialMemberType && nameMatches(potentialUnitName, compilationUnit, partialMatch)) {
-				IType[] types= null;
+				
+				// look in compilation units
 				try {
-					types= compilationUnit.getTypes();
-				} catch (JavaModelException npe) {
-					continue; // the compilation unit is not present
-				}
-				int typeLength= types.length;
-				for (int j= 0; j < typeLength; j++) {
-					if (requestor.isCanceled())
-						return;
-					IType type= types[j]; 
-					if (nameMatches(potentialMatchName, type, partialMatch)) {
-						seekQualifiedMemberTypes(name.substring(index + 1, name.length()), type, partialMatch, requestor, acceptFlags);
+					String cuPrefix = firstDot == -1 ? prefix : prefix.substring(0, firstDot);
+					ICompilationUnit[] compilationUnits = pkg.getCompilationUnits();
+					for (int i = 0, length = compilationUnits.length; i < length; i++) {
+						if (requestor.isCanceled())
+							return;
+						ICompilationUnit cu = compilationUnits[i];
+						if (!cu.getElementName().toLowerCase().startsWith(cuPrefix))
+							continue;
+						try {
+							IType[] types = cu.getTypes();
+							for (int j = 0, typeLength = types.length; j < typeLength; j++)
+								seekTypesInTopLevelType(prefix, firstDot, types[j], requestor, acceptFlags);
+						} catch (JavaModelException e) {
+							// cu doesn't exist -> ignore
+						}
 					}
+				} catch (JavaModelException e) {
+					// package doesn't exist -> ignore
 				}
 			}
-
+		} finally {
+			if (VERBOSE)
+				this.timeSpentInSeekTypesInSourcePackage += System.currentTimeMillis()-start;
 		}
 	}
 
@@ -733,37 +866,46 @@
 	 * given type with the given (possibly qualified) name. Checks
 	 * the requestor at regular intervals to see if the requestor
 	 * has canceled.
-	 *
-	 * @param partialMatch partial name matches qualify when <code>true</code>,
-	 *  only exact name matches qualify when <code>false</code>
 	 */
-	protected void seekQualifiedMemberTypes(String qualifiedName, IType type, boolean partialMatch, IJavaElementRequestor requestor, int acceptFlags) {
-		if (type == null)
-			return;
+	protected void seekTypesInType(String prefix, int firstDot, IType type, IJavaElementRequestor requestor, int acceptFlags) {
 		IType[] types= null;
 		try {
 			types= type.getTypes();
 		} catch (JavaModelException npe) {
 			return; // the enclosing type is not present
 		}
-		String matchName= qualifiedName;
-		int index= qualifiedName.indexOf('$');
-		boolean nested= false;
-		if (index != -1) {
-			matchName= qualifiedName.substring(0, index);
-			nested= true;
-		}
 		int length= types.length;
+		if (length == 0) return; 
+		
+		String memberPrefix = prefix;
+		boolean isMemberTypePrefix = false;
+		if (firstDot != -1) {
+			memberPrefix= prefix.substring(0, firstDot);
+			isMemberTypePrefix = true;
+		}
 		for (int i= 0; i < length; i++) {
 			if (requestor.isCanceled())
 				return;
 			IType memberType= types[i];
-			if (nameMatches(matchName, memberType, partialMatch))
-				if (nested) {
-					seekQualifiedMemberTypes(qualifiedName.substring(index + 1, qualifiedName.length()), memberType, partialMatch, requestor, acceptFlags);
+			if (memberType.getElementName().toLowerCase().startsWith(memberPrefix))
+				if (isMemberTypePrefix) {
+					String subPrefix = prefix.substring(firstDot + 1, prefix.length());
+					seekTypesInType(subPrefix, subPrefix.indexOf('.'), memberType, requestor, acceptFlags);
 				} else {
-					if (acceptType(memberType, acceptFlags)) requestor.acceptMemberType(memberType);
+					if (acceptType(memberType, acceptFlags, true/*a source type*/)) 
+						requestor.acceptMemberType(memberType);
 				}
 		}
 	}
+	
+	protected void seekTypesInTopLevelType(String prefix, int firstDot, IType topLevelType, IJavaElementRequestor requestor, int acceptFlags) {
+		if (!topLevelType.getElementName().toLowerCase().startsWith(prefix))
+			return;
+		if (firstDot == -1) {
+			if (acceptType(topLevelType, acceptFlags, true/*a source type*/))
+				requestor.acceptType(topLevelType);
+		} else {
+			seekTypesInType(prefix, firstDot, topLevelType, requestor, acceptFlags);
+		}
+	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java
new file mode 100644
index 0000000..330c57f
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.ITypeParameter;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.compiler.CharOperation;
+
+public abstract class NamedMember extends Member {
+
+	/*
+	 * This element's name, or an empty <code>String</code> if this
+	 * element does not have a name.
+	 */
+	protected String name;
+	
+	public NamedMember(JavaElement parent, String name) {
+		super(parent);
+		this.name = name;
+	}
+	
+	private void appendTypeParameters(StringBuffer buffer) throws JavaModelException {
+		ITypeParameter[] typeParameters = getTypeParameters();
+		int length = typeParameters.length;
+		if (length == 0) return;
+		buffer.append('<');
+		for (int i = 0; i < length; i++) {
+			ITypeParameter typeParameter = typeParameters[i];
+			buffer.append(typeParameter.getElementName());
+			String[] bounds = typeParameter.getBounds();
+			int boundsLength = bounds.length;
+			if (boundsLength > 0) {
+				buffer.append(" extends "); //$NON-NLS-1$
+				for (int j = 0; j < boundsLength; j++) {
+					buffer.append(bounds[j]);
+					if (j < boundsLength-1)
+						buffer.append(" & "); //$NON-NLS-1$
+				}
+			}
+			if (i < length-1)
+				buffer.append(", "); //$NON-NLS-1$
+		}
+		buffer.append('>');
+	}
+
+	public String getElementName() {
+		return this.name;
+	}
+
+	protected String getFullyQualifiedParameterizedName(String fullyQualifiedName, String uniqueKey) throws JavaModelException {
+		char[][] typeArguments = Signature.getTypeArguments(uniqueKey.toCharArray());
+		int length = typeArguments.length;
+		if (length == 0) return fullyQualifiedName;
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(fullyQualifiedName);
+		buffer.append('<');
+		for (int i = 0; i < length; i++) {
+			char[] typeArgument = typeArguments[i];
+			CharOperation.replace(typeArgument, '/', '.');
+			buffer.append(Signature.toCharArray(typeArgument));
+			if (i < length-1)
+				buffer.append(',');
+		}
+		buffer.append('>');
+		return buffer.toString();
+	}
+	
+	protected IPackageFragment getPackageFragment() {
+		return null;
+	}
+	
+	public String getFullyQualifiedName(char enclosingTypeSeparator, boolean showParameters) throws JavaModelException {
+		String packageName = getPackageFragment().getElementName();
+		if (packageName.equals(IPackageFragment.DEFAULT_PACKAGE_NAME)) {
+			return getTypeQualifiedName(enclosingTypeSeparator, showParameters);
+		}
+		return packageName + '.' + getTypeQualifiedName(enclosingTypeSeparator, showParameters);
+	}
+
+	public String getTypeQualifiedName(char enclosingTypeSeparator, boolean showParameters) throws JavaModelException {
+		NamedMember declaringType;
+		switch (this.parent.getElementType()) {
+			case IJavaElement.COMPILATION_UNIT:
+				if (showParameters) {
+					StringBuffer buffer = new StringBuffer(this.name);
+					appendTypeParameters(buffer);
+					return buffer.toString();
+				}
+				return this.name;
+			case IJavaElement.CLASS_FILE:
+				String classFileName = this.parent.getElementName();
+				String typeName;
+				if (classFileName.indexOf('$') == -1) {
+					// top level class file: name of type is same as name of class file
+					typeName = this.name;
+				} else {
+					// anonymous or local class file
+					typeName = classFileName.substring(0, classFileName.lastIndexOf('.')); // remove .class
+				}
+				if (showParameters) {
+					StringBuffer buffer = new StringBuffer(typeName);
+					appendTypeParameters(buffer);
+					return buffer.toString();
+				}
+				return typeName;
+			case IJavaElement.TYPE:
+				declaringType = (NamedMember) this.parent;
+				break;
+			case IJavaElement.FIELD:
+			case IJavaElement.INITIALIZER:
+			case IJavaElement.METHOD:
+				declaringType = (NamedMember) ((IMember) this.parent).getDeclaringType();
+				break;
+			default:
+				return null;
+		}
+		StringBuffer buffer = new StringBuffer(declaringType.getTypeQualifiedName(enclosingTypeSeparator, showParameters));
+		buffer.append(enclosingTypeSeparator);
+		String simpleName = this.name.length() == 0 ? Integer.toString(this.occurrenceCount) : this.name;
+		buffer.append(simpleName);
+		if (showParameters) {
+			appendTypeParameters(buffer);
+		}
+		return buffer.toString();
+	}
+	
+	protected ITypeParameter[] getTypeParameters() throws JavaModelException {
+		return null;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java
index 92f7a4c..bc1be95 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java
@@ -10,7 +10,6 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
-import java.text.NumberFormat;
 import java.util.*;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -18,13 +17,11 @@
 
 import org.eclipse.core.resources.*;
 import org.eclipse.core.resources.IContainer;
-import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.codeassist.CompletionEngine;
 import org.eclipse.jdt.internal.codeassist.SelectionEngine;
 
@@ -37,8 +34,8 @@
  */
 public abstract class Openable extends JavaElement implements IOpenable, IBufferChangedListener {
 
-protected Openable(JavaElement parent, String name) {
-	super(parent, name);
+protected Openable(JavaElement parent) {
+	super(parent);
 }
 /**
  * The buffer associated with this element has changed. Registers
@@ -100,7 +97,7 @@
 protected void closing(Object info) {
 	closeBuffer();
 }
-protected void codeComplete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, org.eclipse.jdt.internal.compiler.env.ICompilationUnit unitToSkip, int position, ICompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
+protected void codeComplete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, org.eclipse.jdt.internal.compiler.env.ICompilationUnit unitToSkip, int position, CompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
 	if (requestor == null) {
 		throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$
 	}
@@ -112,21 +109,21 @@
 		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INDEX_OUT_OF_BOUNDS));
 	}
 	JavaProject project = (JavaProject) getJavaProject();
-	SearchableEnvironment environment = (SearchableEnvironment) project.newSearchableNameEnvironment(owner);
+	SearchableEnvironment environment = project.newSearchableNameEnvironment(owner);
 
 	// set unit to skip
 	environment.unitToSkip = unitToSkip;
 
 	// code complete
-	CompletionRequestorWrapper requestorWrapper = new CompletionRequestorWrapper(requestor, environment.nameLookup);
-	CompletionEngine engine = new CompletionEngine(environment, requestorWrapper, project.getOptions(true), project);
-	requestorWrapper.completionEngine = engine;
+	CompletionEngine engine = new CompletionEngine(environment, requestor, project.getOptions(true), project);
 	engine.complete(cu, position, 0);
+	if (NameLookup.VERBOSE)
+		System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
 }
 protected IJavaElement[] codeSelect(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, int offset, int length, WorkingCopyOwner owner) throws JavaModelException {
 
 	JavaProject project = (JavaProject)getJavaProject();
-	SearchableEnvironment environment = (SearchableEnvironment) project.newSearchableNameEnvironment(owner);
+	SearchableEnvironment environment = project.newSearchableNameEnvironment(owner);
 	
 	SelectionRequestor requestor= new SelectionRequestor(environment.nameLookup, this);
 	IBuffer buffer = getBuffer();
@@ -141,6 +138,8 @@
 	// fix for 1FVXGDK
 	SelectionEngine engine = new SelectionEngine(environment, requestor, project.getOptions(true));
 	engine.select(cu, offset, offset + length - 1);
+	if (NameLookup.VERBOSE)
+		System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
 	return requestor.getElements();
 }
 /*
@@ -166,12 +165,33 @@
 protected void generateInfos(Object info, HashMap newElements, IProgressMonitor monitor) throws JavaModelException {
 
 	if (JavaModelManager.VERBOSE){
-		System.out.println("OPENING Element ("+ Thread.currentThread()+"): " + this.toStringWithAncestors()); //$NON-NLS-1$//$NON-NLS-2$
+		String element;
+		switch (getElementType()) {
+			case JAVA_PROJECT:
+				element = "project"; //$NON-NLS-1$
+				break;
+			case PACKAGE_FRAGMENT_ROOT:
+				element = "root"; //$NON-NLS-1$
+				break;
+			case PACKAGE_FRAGMENT:
+				element = "package"; //$NON-NLS-1$
+				break;
+			case CLASS_FILE:
+				element = "class file"; //$NON-NLS-1$
+				break;
+			case COMPILATION_UNIT:
+				element = "compilation unit"; //$NON-NLS-1$
+				break;
+			default:
+				element = "element"; //$NON-NLS-1$
+		}
+		System.out.println(Thread.currentThread() +" OPENING " + element + " " + this.toStringWithAncestors()); //$NON-NLS-1$//$NON-NLS-2$
 	}
 	
 	// open the parent if necessary
 	openParent(info, newElements, monitor);
-	if (monitor != null && monitor.isCanceled()) return;
+	if (monitor != null && monitor.isCanceled()) 
+		throw new OperationCanceledException();
 
 	 // puts the info before building the structure so that questions to the handle behave as if the element existed
 	 // (case of compilation units becoming working copies)
@@ -191,8 +211,7 @@
 	JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
 
 	if (JavaModelManager.VERBOSE) {
-		System.out.println("-> Package cache size = " + JavaModelManager.getJavaModelManager().cache.pkgSize()); //$NON-NLS-1$
-		System.out.println("-> Openable cache filling ratio = " + NumberFormat.getInstance().format(JavaModelManager.getJavaModelManager().cache.openableFillingRatio()) + "%"); //$NON-NLS-1$//$NON-NLS-2$
+		System.out.println(JavaModelManager.getJavaModelManager().cache.toStringFillingRation("-> ")); //$NON-NLS-1$
 	}
 }
 /**
@@ -261,7 +280,7 @@
 	int type = parentResource.getType();
 	if (type == IResource.FOLDER || type == IResource.PROJECT) {
 		IContainer folder = (IContainer) parentResource;
-		IResource resource = folder.findMember(this.name);
+		IResource resource = folder.findMember(getElementName());
 		if (resource == null) {
 			throw newNotPresentException();
 		} else {
@@ -336,6 +355,12 @@
 	return false;
 }
 /**
+ * @see IJavaElement
+ */
+public boolean isStructureKnown() throws JavaModelException {
+	return ((OpenableElementInfo)getElementInfo()).isStructureKnown();
+}
+/**
  * @see IOpenable
  */
 public void makeConsistent(IProgressMonitor monitor) throws JavaModelException {
@@ -445,78 +470,5 @@
 	} while(current != null);
 	return null;
 }
-/**
- * @see ICodeAssist
- * @deprecated - use codeComplete(ICompilationUnit, ICompilationUnit, int, ICompletionRequestor) instead
- */
-protected void codeComplete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, org.eclipse.jdt.internal.compiler.env.ICompilationUnit unitToSkip, int position, final ICodeCompletionRequestor requestor) throws JavaModelException {
 
-	if (requestor == null){ 
-		codeComplete(cu, unitToSkip, position, null, DefaultWorkingCopyOwner.PRIMARY);
-		return;
-	}
-	codeComplete(
-		cu,
-		unitToSkip,
-		position,
-		new ICompletionRequestor(){
-			public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
-				// ignore
-			}
-			public void acceptClass(char[] packageName, char[] className, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-				requestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd);
-			}
-			public void acceptError(IProblem error) {
-				if (true) return; // was disabled in 1.0
-
-				try {
-					IMarker marker = ResourcesPlugin.getWorkspace().getRoot().createMarker(IJavaModelMarker.TRANSIENT_PROBLEM);
-					marker.setAttribute(IJavaModelMarker.ID, error.getID());
-					marker.setAttribute(IMarker.CHAR_START, error.getSourceStart());
-					marker.setAttribute(IMarker.CHAR_END, error.getSourceEnd() + 1);
-					marker.setAttribute(IMarker.LINE_NUMBER, error.getSourceLineNumber());
-					marker.setAttribute(IMarker.MESSAGE, error.getMessage());
-					marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
-					requestor.acceptError(marker);
-				} catch(CoreException e){
-					// could not create marker: ignore
-				}
-			}
-			public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] fieldName, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-				requestor.acceptField(declaringTypePackageName, declaringTypeName, fieldName, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd);
-			}
-			public void acceptInterface(char[] packageName,char[] interfaceName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
-				requestor.acceptInterface(packageName, interfaceName, completionName, modifiers, completionStart, completionEnd);
-			}
-			public void acceptKeyword(char[] keywordName,int completionStart,int completionEnd, int relevance){
-				requestor.acceptKeyword(keywordName, completionStart, completionEnd);
-			}
-			public void acceptLabel(char[] labelName,int completionStart,int completionEnd, int relevance){
-				requestor.acceptLabel(labelName, completionStart, completionEnd);
-			}
-			public void acceptLocalVariable(char[] localVarName,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd, int relevance){
-				// ignore
-			}
-			public void acceptMethod(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
-				// skip parameter names
-				requestor.acceptMethod(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart, completionEnd);
-			}
-			public void acceptMethodDeclaration(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
-				// ignore
-			}
-			public void acceptModifier(char[] modifierName,int completionStart,int completionEnd, int relevance){
-				requestor.acceptModifier(modifierName, completionStart, completionEnd);
-			}
-			public void acceptPackage(char[] packageName,char[] completionName,int completionStart,int completionEnd, int relevance){
-				requestor.acceptPackage(packageName, completionName, completionStart, completionEnd);
-			}
-			public void acceptType(char[] packageName,char[] typeName,char[] completionName,int completionStart,int completionEnd, int relevance){
-				requestor.acceptType(packageName, typeName, completionName, completionStart, completionEnd);
-			}
-			public void acceptVariableName(char[] typePackageName,char[] typeName,char[] varName,char[] completionName,int completionStart,int completionEnd, int relevance){
-				// ignore
-			}
-		},
-		DefaultWorkingCopyOwner.PRIMARY);
-}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java
index ddf8505..3407f25 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java
@@ -10,7 +10,29 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import org.eclipse.jdt.core.IJavaElement;
+
 /** Element info for IOpenable elements. */
 public class OpenableElementInfo extends JavaElementInfo {
-	// root of all openable element infos
+
+	/**
+	 * Is the structure of this element known
+	 * @see IJavaElement#isStructureKnown()
+	 */
+	protected boolean isStructureKnown = false;
+
+	/**
+	 * @see IJavaElement#isStructureKnown()
+	 */
+	public boolean isStructureKnown() {
+		return this.isStructureKnown;
+	}
+	
+	/**
+	 * Sets whether the structure of this element known
+	 * @see IJavaElement#isStructureKnown()
+	 */
+	public void setIsStructureKnown(boolean newIsStructureKnown) {
+		this.isStructureKnown = newIsStructureKnown;
+	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageDeclaration.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageDeclaration.java
index b3e9c22..18bd545 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageDeclaration.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageDeclaration.java
@@ -19,8 +19,12 @@
  */
 
 /* package */ class PackageDeclaration extends SourceRefElement implements IPackageDeclaration {
+	
+	String name;
+	
 protected PackageDeclaration(CompilationUnit parent, String name) {
-	super(parent, name);
+	super(parent);
+	this.name = name;
 }
 public boolean equals(Object o) {
 	if (!(o instanceof PackageDeclaration)) return false;
@@ -34,6 +38,9 @@
 protected boolean equalsDOMNode(IDOMNode node) {
 	return (node.getNodeType() == IDOMNode.PACKAGE) && getElementName().equals(node.getName());
 }
+public String getElementName() {
+	return this.name;
+}
 /**
  * @see IJavaElement
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java
index b3f9d1f..9c9c78a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java
@@ -28,7 +28,6 @@
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.util.MementoTokenizer;
 import org.eclipse.jdt.internal.core.util.Util;
@@ -45,13 +44,12 @@
 	 * Constant empty list of compilation units
 	 */
 	protected static final ICompilationUnit[] NO_COMPILATION_UNITS = new ICompilationUnit[] {};
-/**
- * Constructs a handle for a package fragment
- *
- * @see IPackageFragment
- */
-protected PackageFragment(PackageFragmentRoot root, String name) {
-	super(root, name);
+	
+	public String[] names;
+
+protected PackageFragment(PackageFragmentRoot root, String[] names) {
+	super(root);
+	this.names = names;
 }
 /**
  * @see Openable
@@ -62,12 +60,6 @@
 	if (!underlyingResource.isAccessible()) throw newNotPresentException();
 
 	int kind = getKind();
-	String extType;
-	if (kind == IPackageFragmentRoot.K_SOURCE) {
-		extType = EXTENSION_java;
-	} else {
-		extType = EXTENSION_class;
-	}
 
 	// add compilation units/class files from resources
 	HashSet vChildren = new HashSet();
@@ -80,18 +72,13 @@
 			IResource child = members[i];
 			if (child.getType() != IResource.FOLDER
 					&& !Util.isExcluded(child, inclusionPatterns, exclusionPatterns)) {
-				String extension = child.getProjectRelativePath().getFileExtension();
-				if (extension != null) {
-					if (extension.equalsIgnoreCase(extType)) {
-						IJavaElement childElement;
-						if (kind == IPackageFragmentRoot.K_SOURCE && Util.isValidCompilationUnitName(child.getName())) {
-							childElement = new CompilationUnit(this, child.getName(), DefaultWorkingCopyOwner.PRIMARY);
-							vChildren.add(childElement);
-						} else if (Util.isValidClassFileName(child.getName())) {
-							childElement = getClassFile(child.getName());
-							vChildren.add(childElement);
-						}
-					}
+				IJavaElement childElement;
+				if (kind == IPackageFragmentRoot.K_SOURCE && Util.isValidCompilationUnitName(child.getName())) {
+					childElement = new CompilationUnit(this, child.getName(), DefaultWorkingCopyOwner.PRIMARY);
+					vChildren.add(childElement);
+				} else if (kind == IPackageFragmentRoot.K_BINARY && Util.isValidClassFileName(child.getName())) {
+					childElement = getClassFile(child.getName());
+					vChildren.add(childElement);
 				}
 			}
 		}
@@ -161,8 +148,12 @@
 	getJavaModel().delete(elements, force, monitor);
 }
 public boolean equals(Object o) {
+	if (this == o) return true;
 	if (!(o instanceof PackageFragment)) return false;
-	return super.equals(o);
+	
+	PackageFragment other = (PackageFragment) o;		
+	return Util.equalArraysOrNull(this.names, other.names) &&
+			this.parent.equals(other.parent);
 }
 /**
  * @see IPackageFragment#getClassFile(String)
@@ -196,7 +187,7 @@
  * @exception IllegalArgumentException if the name does not end with ".java"
  */
 public ICompilationUnit getCompilationUnit(String cuName) {
-	if (!org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(cuName)) {
+	if (!org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(cuName)) {
 		throw new IllegalArgumentException(Util.bind("convention.unit.notJavaName")); //$NON-NLS-1$
 	}
 	return new CompilationUnit(this, cuName, DefaultWorkingCopyOwner.PRIMARY);
@@ -234,6 +225,11 @@
 	}
 	return result;
 }
+public String getElementName() {
+	if (this.names.length == 0)
+		return DEFAULT_PACKAGE_NAME;
+	return Util.concatWith(this.names, '.');
+}
 /**
  * @see IJavaElement
  */
@@ -245,13 +241,13 @@
  */
 public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner owner) {
 	switch (token.charAt(0)) {
-		case JEM_COUNT:
-			return getHandleUpdatingCountFromMemento(memento, owner);
 		case JEM_CLASSFILE:
+			if (!memento.hasMoreTokens()) return this;
 			String classFileName = memento.nextToken();
 			JavaElement classFile = (JavaElement)getClassFile(classFileName);
 			return classFile.getHandleFromMemento(memento, owner);
 		case JEM_COMPILATIONUNIT:
+			if (!memento.hasMoreTokens()) return this;
 			String cuName = memento.nextToken();
 			JavaElement cu = new CompilationUnit(this, cuName, owner);
 			return cu.getHandleFromMemento(memento, owner);
@@ -289,7 +285,12 @@
 	if (root.isArchive()) {
 		return root.getPath();
 	} else {
-		return root.getPath().append(this.getElementName().replace('.', '/'));
+		IPath path = root.getPath();
+		for (int i = 0, length = this.names.length; i < length; i++) {
+			String name = this.names[i];
+			path = path.append(name);
+		}
+		return path;
 	}
 }
 /**
@@ -300,11 +301,14 @@
 	if (root.isArchive()) {
 		return root.getResource();
 	} else {
-		String elementName = this.getElementName();
-		if (elementName.length() == 0) {
+		int length = this.names.length;
+		if (length == 0) {
 			return root.getResource();
 		} else {
-			return ((IContainer)root.getResource()).getFolder(new Path(this.getElementName().replace('.', '/')));
+			IPath path = new Path(this.names[0]);
+			for (int i = 1; i < length; i++)
+				path = path.append(this.names[i]);
+			return ((IContainer)root.getResource()).getFolder(path);
 		}
 	}
 }
@@ -321,7 +325,7 @@
 	// is atually the package fragment root)
 	if (rootResource.getType() == IResource.FOLDER || rootResource.getType() == IResource.PROJECT) {
 		IContainer folder = (IContainer) rootResource;
-		String[] segs = Signature.getSimpleNames(this.name);
+		String[] segs = this.names;
 		for (int i = 0; i < segs.length; ++i) {
 			IResource child = folder.findMember(segs[i]);
 			if (child == null || child.getType() != IResource.FOLDER) {
@@ -334,6 +338,12 @@
 		return rootResource;
 	}
 }
+public int hashCode() {
+	int hash = this.parent.hashCode();
+	for (int i = 0, length = this.names.length; i < length; i++)
+		hash = Util.combineHashCodes(this.names[i].hashCode(), hash);
+	return hash;
+}
 /**
  * @see IParent 
  */
@@ -345,14 +355,14 @@
  */
 public boolean hasSubpackages() throws JavaModelException {
 	IJavaElement[] packages= ((IPackageFragmentRoot)getParent()).getChildren();
-	String elementName = getElementName();
-	int nameLength = elementName.length();
-	String packageName = isDefaultPackage() ? elementName : elementName+"."; //$NON-NLS-1$
-	for (int i= 0; i < packages.length; i++) {
-		String otherName = packages[i].getElementName();
-		if (otherName.length() > nameLength && otherName.startsWith(packageName)) {
-			return true;
-		}
+	int namesLength = this.names.length;
+	nextPackage: for (int i= 0, length = packages.length; i < length; i++) {
+		String[] otherNames = ((PackageFragment) packages[i]).names;
+		if (otherNames.length <= namesLength) continue nextPackage;
+		for (int j = 0; j < namesLength; j++)
+			if (!this.names[j].equals(otherNames[j]))
+				continue nextPackage;
+		return true;
 	}
 	return false;
 }
@@ -360,7 +370,7 @@
  * @see IPackageFragment#isDefaultPackage()
  */
 public boolean isDefaultPackage() {
-	return this.getElementName().length() == 0;
+	return this.names.length == 0;
 }
 /**
  * @see ISourceManipulation#move(IJavaElement, IJavaElement, String, boolean, IProgressMonitor)
@@ -406,7 +416,7 @@
  */
 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
 	buffer.append(this.tabString(tab));
-	if (getElementName().length() == 0) {
+	if (this.names.length == 0) {
 		buffer.append("<default>"); //$NON-NLS-1$
 	} else {
 		toStringName(buffer);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
index f68bcd0..58ea7b6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
@@ -56,8 +56,8 @@
  * Constructs a package fragment root which is the root of the java package
  * directory hierarchy.
  */
-protected PackageFragmentRoot(IResource resource, JavaProject project, String name) {
-	super(project, name);
+protected PackageFragmentRoot(IResource resource, JavaProject project) {
+	super(project);
 	this.resource = resource;
 }
 
@@ -165,9 +165,9 @@
 protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
 	
 	// check whether this pkg fragment root can be opened
-	if (!resourceExists() || !isOnClasspath()) {
-		throw newNotPresentException();
-	}
+	IStatus status = validateOnClasspath();
+	if (!status.isOK()) throw newJavaModelException(status);
+	if (!resourceExists()) throw newNotPresentException();
 
 	((PackageFragmentRootInfo) info).setRootKind(determineKind(underlyingResource));
 	return computeChildren(info, newElements);
@@ -177,7 +177,7 @@
 	SourceMapper mapper = new SourceMapper(
 		sourcePath, 
 		rootPath == null ? null : rootPath.toOSString(), 
-		this.isExternal() ? JavaCore.getOptions() : this.getJavaProject().getOptions(true)); // only project options if associated with resource
+		getJavaProject().getOptions(true)); // cannot use workspace options if external jar is 1.5 jar and workspace options are 1.4 options
 	return mapper;
 }
 /*
@@ -210,7 +210,7 @@
 			IContainer rootFolder = (IContainer) underlyingResource;
 			char[][] inclusionPatterns = fullInclusionPatternChars();
 			char[][] exclusionPatterns = fullExclusionPatternChars();
-			computeFolderChildren(rootFolder, !Util.isExcluded(rootFolder, inclusionPatterns, exclusionPatterns), "", vChildren, inclusionPatterns, exclusionPatterns); //$NON-NLS-1$
+			computeFolderChildren(rootFolder, !Util.isExcluded(rootFolder, inclusionPatterns, exclusionPatterns), CharOperation.NO_STRINGS, vChildren, inclusionPatterns, exclusionPatterns); //$NON-NLS-1$
 			IJavaElement[] children = new IJavaElement[vChildren.size()];
 			vChildren.toArray(children);
 			info.setChildren(children);
@@ -229,14 +229,15 @@
  * 
  * @exception JavaModelException  The resource associated with this package fragment does not exist
  */
-protected void computeFolderChildren(IContainer folder, boolean isIncluded, String prefix, ArrayList vChildren, char[][] inclusionPatterns, char[][] exclusionPatterns) throws JavaModelException {
+protected void computeFolderChildren(IContainer folder, boolean isIncluded, String[] pkgName, ArrayList vChildren, char[][] inclusionPatterns, char[][] exclusionPatterns) throws JavaModelException {
 
 	if (isIncluded) {
-	    IPackageFragment pkg = getPackageFragment(prefix);
+	    IPackageFragment pkg = getPackageFragment(pkgName);
 		vChildren.add(pkg);
 	}
 	try {
 		JavaProject javaProject = (JavaProject)getJavaProject();
+		JavaModelManager manager = JavaModelManager.getJavaModelManager();
 		IResource[] members = folder.members();
 		boolean hasIncluded = isIncluded;
 		for (int i = 0, max = members.length; i < max; i++) {
@@ -252,13 +253,8 @@
 					    if (isMemberIncluded || inclusionPatterns != null) { 
 							// eliminate binary output only if nested inside direct subfolders
 							if (javaProject.contains(member)) {
-								String newPrefix;
-								if (prefix.length() == 0) {
-									newPrefix = memberName;
-								} else {
-									newPrefix = prefix + "." + memberName; //$NON-NLS-1$
-								}
-								computeFolderChildren((IFolder) member, isMemberIncluded, newPrefix, vChildren, inclusionPatterns, exclusionPatterns);
+								String[] newNames = Util.arrayConcat(pkgName, manager.intern(memberName));
+								computeFolderChildren((IFolder) member, isMemberIncluded, newNames, vChildren, inclusionPatterns, exclusionPatterns);
 							}
 						}
 					}
@@ -269,7 +265,7 @@
 								&& Util.isValidCompilationUnitName(memberName)
 								&& !Util.isExcluded(member, inclusionPatterns, exclusionPatterns)) {
 						hasIncluded = true;
-					    IPackageFragment pkg = getPackageFragment(prefix);
+					    IPackageFragment pkg = getPackageFragment(pkgName);
 					    vChildren.add(pkg); 
 					}
 			        break;
@@ -311,7 +307,7 @@
 public IPackageFragment createPackageFragment(String pkgName, boolean force, IProgressMonitor monitor) throws JavaModelException {
 	CreatePackageFragmentOperation op = new CreatePackageFragmentOperation(this, pkgName, force);
 	op.runOperation(monitor);
-	return getPackageFragment(pkgName);
+	return getPackageFragment(op.pkgName);
 }
 
 /**
@@ -344,8 +340,7 @@
 	if (!(o instanceof PackageFragmentRoot))
 		return false;
 	PackageFragmentRoot other = (PackageFragmentRoot) o;
-	return this.resource.equals(other.resource) &&
-			this.occurrenceCount == other.occurrenceCount && 
+	return this.resource.equals(other.resource) && 
 			this.parent.equals(other.parent);
 }
 
@@ -353,7 +348,7 @@
  * @see IJavaElement
  */
 public boolean exists() {
-	return super.exists() && isOnClasspath();
+	return super.exists() && validateOnClasspath().isOK();
 }
 
 public IClasspathEntry findSourceAttachmentRecommendation() {
@@ -468,7 +463,11 @@
 		return null;
 	}
 }		
-
+public String getElementName() {
+	if (this.resource instanceof IFolder)
+		return ((IFolder) this.resource).getName();
+	return ""; //$NON-NLS-1$
+}
 /**
  * @see IJavaElement
  */
@@ -486,8 +485,6 @@
  */
 public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner owner) {
 	switch (token.charAt(0)) {
-		case JEM_COUNT:
-			return getHandleUpdatingCountFromMemento(memento, owner);
 		case JEM_PACKAGEFRAGMENT:
 			String pkgName;
 			if (memento.hasMoreTokens()) {
@@ -513,9 +510,9 @@
 	return null;
 }
 /**
- * @see JavaElement#getHandleMemento()
+ * @see JavaElement#getHandleMemento(StringBuffer)
  */
-public String getHandleMemento(){
+protected void getHandleMemento(StringBuffer buff) {
 	IPath path;
 	IResource underlyingResource = getResource();
 	if (underlyingResource != null) {
@@ -529,14 +526,9 @@
 		// external jar
 		path = getPath();
 	}
-	StringBuffer buff= new StringBuffer(((JavaElement)getParent()).getHandleMemento());
+	((JavaElement)getParent()).getHandleMemento(buff);
 	buff.append(getHandleMementoDelimiter());
 	escapeMementoName(buff, path.toString()); 
-	if (this.occurrenceCount > 1) {
-		buff.append(JEM_COUNT);
-		buff.append(this.occurrenceCount);
-	}
-	return buff.toString();
 }
 /**
  * @see IPackageFragmentRoot
@@ -556,20 +548,13 @@
  * @see IPackageFragmentRoot
  */
 public IPackageFragment getPackageFragment(String packageName) {
-	if (packageName.indexOf(' ') != -1) { // tolerate package names with spaces (e.g. 'x . y') (http://bugs.eclipse.org/bugs/show_bug.cgi?id=21957)
-		char[][] compoundName = Util.toCompoundChars(packageName);
-		StringBuffer buffer = new StringBuffer(packageName.length());
-		for (int i = 0, length = compoundName.length; i < length; i++) {
-			buffer.append(CharOperation.trim(compoundName[i]));
-			if (i != length-1) {
-				buffer.append('.');
-			}
-		}
-		packageName = buffer.toString();
-	}
-	return new PackageFragment(this, packageName);
+	// tolerate package names with spaces (e.g. 'x . y') (http://bugs.eclipse.org/bugs/show_bug.cgi?id=21957)
+	String[] pkgName = Util.getTrimmedSimpleNames(packageName); 
+	return getPackageFragment(pkgName);
 }
-
+public PackageFragment getPackageFragment(String[] pkgName) {
+	return new PackageFragment(this, pkgName);
+}
 /**
  * Returns the package name for the given folder
  * (which is a decendent of this root).
@@ -794,9 +779,9 @@
 }
 
 /*
- * Returns whether this package fragment root is on the classpath of its project.
+ * Validate whether this package fragment root is on the classpath of its project.
  */
-protected boolean isOnClasspath() {
+protected IStatus validateOnClasspath() {
 	
 	IPath path = this.getPath();
 	try {
@@ -806,13 +791,14 @@
 		for (int i = 0, length = classpath.length; i < length; i++) {
 			IClasspathEntry entry = classpath[i];
 			if (entry.getPath().equals(path)) {
-				return true;
+				return Status.OK_STATUS;
 			}
 		}
 	} catch(JavaModelException e){
 		// could not read classpath, then assume it is outside
+		return e.getJavaModelStatus();
 	}
-	return false;
+	return new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_NOT_ON_CLASSPATH, this);
 }
 /*
  * @see org.eclipse.jdt.core.IPackageFragmentRoot#move
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedBinaryField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedBinaryField.java
new file mode 100644
index 0000000..b7fd630
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedBinaryField.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+/**
+ * Handle representing a binary field that is parameterized.
+ * The uniqueKey contains the genericSignature of the parameterized field.
+ */
+public class ParameterizedBinaryField extends BinaryField {
+	
+	public String uniqueKey;
+	
+	/*
+	 * See class comments.
+	 */
+	public ParameterizedBinaryField(JavaElement parent, String name, String uniqueKey) {
+		super(parent, name);
+		this.uniqueKey = uniqueKey;
+	}
+
+	/**
+	 * @private Debugging purposes
+	 */
+	protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
+		super.toStringInfo(tab, buffer, info);
+		buffer.append(" key="); //$NON-NLS-1$
+		buffer.append(uniqueKey);
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedBinaryMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedBinaryMethod.java
new file mode 100644
index 0000000..835116a
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedBinaryMethod.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+/**
+ * Handle representing a binary method that is parameterized.
+ * The uniqueKey contains the genericSignature of the parameterized method.
+ */
+public class ParameterizedBinaryMethod extends BinaryMethod {
+	
+	public String uniqueKey;
+	
+	/*
+	 * See class comments.
+	 */
+	public ParameterizedBinaryMethod(JavaElement parent, String name, String[] parameterTypes, String uniqueKey) {
+		super(parent, name, parameterTypes);
+		this.uniqueKey = uniqueKey;
+	}
+
+	/**
+	 * @private Debugging purposes
+	 */
+	protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
+		super.toStringInfo(tab, buffer, info);
+		buffer.append(" key="); //$NON-NLS-1$
+		buffer.append(uniqueKey);
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedBinaryType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedBinaryType.java
new file mode 100644
index 0000000..c4352ef
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedBinaryType.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.JavaModelException;
+
+/**
+ * Handle representing a binary type that is parameterized.
+ * The uniqueKey contains the genericTypeSignature of the parameterized type.
+ */
+public class ParameterizedBinaryType extends BinaryType {
+	
+	public String uniqueKey;
+	
+	/*
+	 * See class comments.
+	 */
+	public ParameterizedBinaryType(JavaElement parent, String name, String uniqueKey) {
+		super(parent, name);
+		this.uniqueKey = uniqueKey;
+	}
+
+	public String getFullyQualifiedParameterizedName() throws JavaModelException {
+		return getFullyQualifiedParameterizedName(getFullyQualifiedName(), this.uniqueKey);
+	}
+	
+	/**
+	 * @private Debugging purposes
+	 */
+	protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
+		super.toStringInfo(tab, buffer, info);
+		buffer.append(" key="); //$NON-NLS-1$
+		buffer.append(uniqueKey);
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedSourceField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedSourceField.java
new file mode 100644
index 0000000..593ac98
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedSourceField.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+/**
+ * Handle representing a source field that is parameterized.
+ * The uniqueKey contains the genericSignature of the parameterized field.
+ */
+public class ParameterizedSourceField extends SourceField {
+	
+	public String uniqueKey;
+	
+	/*
+	 * See class comments.
+	 */
+	public ParameterizedSourceField(JavaElement parent, String name, String uniqueKey) {
+		super(parent, name);
+		this.uniqueKey = uniqueKey;
+	}
+	
+	/**
+	 * @private Debugging purposes
+	 */
+	protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
+		super.toStringInfo(tab, buffer, info);
+		buffer.append(" key="); //$NON-NLS-1$
+		buffer.append(uniqueKey);
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedSourceMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedSourceMethod.java
new file mode 100644
index 0000000..6ee2145
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedSourceMethod.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+/**
+ * Handle representing a source method that is parameterized.
+ * The uniqueKey contains the genericSignature of the parameterized method.
+ */
+public class ParameterizedSourceMethod extends SourceMethod {
+	
+	public String uniqueKey;
+	
+	/*
+	 * See class comments.
+	 */
+	public ParameterizedSourceMethod(JavaElement parent, String name, String[] parameterTypes, String uniqueKey) {
+		super(parent, name, parameterTypes);
+		this.uniqueKey = uniqueKey;
+	}
+
+	/**
+	 * @private Debugging purposes
+	 */
+	protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
+		super.toStringInfo(tab, buffer, info);
+		buffer.append(" key="); //$NON-NLS-1$
+		buffer.append(uniqueKey);
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedSourceType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedSourceType.java
new file mode 100644
index 0000000..304f0cf
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ParameterizedSourceType.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.JavaModelException;
+
+/**
+ * Handle representing a source type that is parameterized.
+ * The uniqueKey contains the genericTypeSignature of the parameterized type.
+ */
+public class ParameterizedSourceType extends SourceType {
+	
+	public String uniqueKey;
+	
+	/*
+	 * See class comments.
+	 */
+	public ParameterizedSourceType(JavaElement parent, String name, String uniqueKey) {
+		super(parent, name);
+		this.uniqueKey = uniqueKey;
+	}
+	
+	public String getFullyQualifiedParameterizedName() throws JavaModelException {
+		return getFullyQualifiedParameterizedName(getFullyQualifiedName(), this.uniqueKey);
+	}
+	
+	/**
+	 * @private Debugging purposes
+	 */
+	protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
+		super.toStringInfo(tab, buffer, info);
+		buffer.append(" key="); //$NON-NLS-1$
+		buffer.append(uniqueKey);
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
index 0def8a5..fb0ee70 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
@@ -12,6 +12,7 @@
 
 import java.util.Map;
 
+import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.JavaModelException;
@@ -43,7 +44,8 @@
 	 */
 	protected void executeOperation() throws JavaModelException {
 		if (this.progressMonitor != null){
-			if (this.progressMonitor.isCanceled()) return;
+			if (this.progressMonitor.isCanceled()) 
+				throw new OperationCanceledException();
 			this.progressMonitor.beginTask(Util.bind("element.reconciling"), 2); //$NON-NLS-1$
 		}
 	
@@ -78,7 +80,7 @@
 							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*/, this.progressMonitor);
+								this.ast = AST.convertCompilationUnit(this.astLevel, unit, contents, options, true/*isResolved*/, workingCopy.owner, this.progressMonitor);
 								if (progressMonitor != null) progressMonitor.worked(1);
 							}
 					    } finally {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java
index fb09e05..5b80f77 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java
@@ -14,7 +14,6 @@
 import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaModelException;
@@ -22,38 +21,46 @@
 import org.eclipse.jdt.core.search.*;
 import org.eclipse.jdt.core.search.IJavaSearchConstants;
 import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.core.search.ITypeNameRequestor;
-import org.eclipse.jdt.core.search.SearchEngine;
 import org.eclipse.jdt.internal.codeassist.ISearchRequestor;
-import org.eclipse.jdt.internal.codeassist.ISearchableNameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.compiler.env.IConstants;
+import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.env.ISourceType;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.core.search.IRestrictedAccessTypeRequestor;
+import org.eclipse.jdt.internal.core.search.SearchBasicEngine;
 
 /**
  *	This class provides a <code>SearchableBuilderEnvironment</code> for code assist which
  *	uses the Java model as a search tool.  
  */
 public class SearchableEnvironment
-	implements ISearchableNameEnvironment, IJavaSearchConstants {
+	implements INameEnvironment, IJavaSearchConstants {
 	
 	public NameLookup nameLookup;
 	protected ICompilationUnit unitToSkip;
 
-	protected IJavaProject project;
+	protected JavaProject project;
 	protected IJavaSearchScope searchScope;
+	
+	protected boolean checkAccessRestrictions;
 
 	/**
 	 * Creates a SearchableEnvironment on the given project
 	 */
 	public SearchableEnvironment(JavaProject project, org.eclipse.jdt.core.ICompilationUnit[] workingCopies) throws JavaModelException {
 		this.project = project;
+		this.checkAccessRestrictions = !JavaCore.IGNORE.equals(project.getOption(JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE, true));
 		this.nameLookup = project.newNameLookup(workingCopies);
 
 		// Create search scope with visible entry on the project's classpath
-		this.searchScope = SearchEngine.createJavaSearchScope(this.project.getAllPackageFragmentRoots());
+		if(this.checkAccessRestrictions) {
+			this.searchScope = SearchBasicEngine.createJavaSearchScope(new IJavaElement[] {project});
+		} else {
+			this.searchScope = SearchBasicEngine.createJavaSearchScope(this.nameLookup.packageFragmentRoots);
+		}
 	}
 
 	/**
@@ -61,10 +68,15 @@
 	 */
 	public SearchableEnvironment(JavaProject project, WorkingCopyOwner owner) throws JavaModelException {
 		this.project = project;
+		this.checkAccessRestrictions = !JavaCore.IGNORE.equals(project.getOption(JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE, true));
 		this.nameLookup = project.newNameLookup(owner);
 
 		// Create search scope with visible entry on the project's classpath
-		this.searchScope = SearchEngine.createJavaSearchScope(this.project.getAllPackageFragmentRoots());
+		if(this.checkAccessRestrictions) {
+			this.searchScope = SearchBasicEngine.createJavaSearchScope(new IJavaElement[] {project});
+		} else {
+			this.searchScope = SearchBasicEngine.createJavaSearchScope(this.nameLookup.packageFragmentRoots);
+		}
 	}
 
 	/**
@@ -79,12 +91,31 @@
 				typeName,
 				packageName,
 				false,
-				NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
+				NameLookup.ACCEPT_ALL);
 		if (type != null) {
-			if (type instanceof BinaryType) {
+			boolean isBinary = type instanceof BinaryType;
+			
+			// determine associated access restriction
+			AccessRestriction accessRestriction = null;
+			
+			if (this.checkAccessRestrictions && (isBinary || !type.getJavaProject().equals(this.project))) {
+				PackageFragmentRoot root = (PackageFragmentRoot)type.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+				ClasspathEntry entry = (ClasspathEntry) this.nameLookup.rootToResolvedEntries.get(root);
+				if (entry != null) { // reverse map always contains resolved CP entry
+					accessRestriction = entry.getImportRestriction();
+					if (accessRestriction != null) {
+						// TODO (philippe) improve char[] <-> String conversions to avoid performing them on the fly
+						char[][] packageChars = CharOperation.splitOn('.', packageName.toCharArray());
+						char[] typeChars = typeName.toCharArray();
+						accessRestriction = accessRestriction.getViolatedRestriction(CharOperation.concatWith(packageChars, typeChars, '/'), null);
+					}
+				}
+			}
+			
+			// construct name env answer
+			if (isBinary) { // BinaryType
 				try {
-					return new NameEnvironmentAnswer(
-						(IBinaryType) ((BinaryType) type).getElementInfo());
+					return new NameEnvironmentAnswer((IBinaryType) ((BinaryType) type).getElementInfo(), accessRestriction);
 				} catch (JavaModelException npe) {
 					return null;
 				}
@@ -109,7 +140,7 @@
 						if (!otherType.equals(topLevelType) && index < length) // check that the index is in bounds (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=62861)
 							sourceTypes[index++] = otherType;
 					}
-					return new NameEnvironmentAnswer(sourceTypes);
+					return new NameEnvironmentAnswer(sourceTypes, accessRestriction);
 				} catch (JavaModelException npe) {
 					return null;
 				}
@@ -119,7 +150,11 @@
 	}
 
 	/**
-	 * @see ISearchableNameEnvironment#findPackages(char[], ISearchRequestor)
+	 * Find the packages that start with the given prefix.
+	 * A valid prefix is a qualified name separated by periods
+	 * (ex. java.util).
+	 * The packages found are passed to:
+	 *    ISearchRequestor.acceptPackage(char[][] packageName)
 	 */
 	public void findPackages(char[] prefix, ISearchRequestor requestor) {
 		this.nameLookup.seekPackageFragments(
@@ -161,7 +196,19 @@
 	}
 
 	/**
-	 * @see ISearchableNameEnvironment#findTypes(char[], ISearchRequestor)
+	 * Find the top-level types (classes and interfaces) that are defined
+	 * in the current environment and whose name starts with the
+	 * given prefix. The prefix is a qualified name separated by periods
+	 * or a simple name (ex. java.util.V or V).
+	 *
+	 * The types found are passed to one of the following methods (if additional
+	 * information is known about the types):
+	 *    ISearchRequestor.acceptType(char[][] packageName, char[] typeName)
+	 *    ISearchRequestor.acceptClass(char[][] packageName, char[] typeName, int modifiers)
+	 *    ISearchRequestor.acceptInterface(char[][] packageName, char[] typeName, int modifiers)
+	 *
+	 * This method can not be used to find member types... member
+	 * types are found relative to their enclosing type.
 	 */
 	public void findTypes(char[] prefix, final ISearchRequestor storage) {
 
@@ -179,7 +226,7 @@
 					findTypes(
 						new String(prefix),
 						storage,
-						NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
+						NameLookup.ACCEPT_ALL);
 					return;
 				}
 				excludePath = ((IJavaElement) this.unitToSkip).getPath().toString();
@@ -225,51 +272,77 @@
 					// implements interface method
 				}
 			};
-			ITypeNameRequestor nameRequestor = new ITypeNameRequestor() {
-				public void acceptClass(
+			IRestrictedAccessTypeRequestor typeRequestor = new IRestrictedAccessTypeRequestor() {
+				public void acceptAnnotation(
 					char[] packageName,
 					char[] simpleTypeName,
 					char[][] enclosingTypeNames,
-					String path) {
+					String path,
+					AccessRestriction access) {
 					if (excludePath != null && excludePath.equals(path))
 						return;
 					if (enclosingTypeNames != null && enclosingTypeNames.length > 0)
 						return; // accept only top level types
-					storage.acceptClass(packageName, simpleTypeName, IConstants.AccPublic);
+					storage.acceptAnnotation(packageName, simpleTypeName, IConstants.AccPublic, access);
+				}
+				public void acceptClass(
+					char[] packageName,
+					char[] simpleTypeName,
+					char[][] enclosingTypeNames,
+					String path,
+					AccessRestriction access) {
+					if (excludePath != null && excludePath.equals(path))
+						return;
+					if (enclosingTypeNames != null && enclosingTypeNames.length > 0)
+						return; // accept only top level types
+					storage.acceptClass(packageName, simpleTypeName, IConstants.AccPublic, access);
+				}
+				public void acceptEnum(
+					char[] packageName,
+					char[] simpleTypeName,
+					char[][] enclosingTypeNames,
+					String path,
+					AccessRestriction access) {
+					if (excludePath != null && excludePath.equals(path))
+						return;
+					if (enclosingTypeNames != null && enclosingTypeNames.length > 0)
+						return; // accept only top level types
+					storage.acceptEnum(packageName, simpleTypeName, IConstants.AccPublic, access);
 				}
 				public void acceptInterface(
 					char[] packageName,
 					char[] simpleTypeName,
 					char[][] enclosingTypeNames,
-					String path) {
+					String path,
+					AccessRestriction access) {
 					if (excludePath != null && excludePath.equals(path))
 						return;
 					if (enclosingTypeNames != null && enclosingTypeNames.length > 0)
 						return; // accept only top level types
-					storage.acceptInterface(packageName, simpleTypeName, IConstants.AccPublic);
+					storage.acceptInterface(packageName, simpleTypeName, IConstants.AccPublic, access);
 				}
 			};
 			try {
-				new SearchEngine().searchAllTypeNames(
+				new SearchBasicEngine().searchAllTypeNames(
 					qualification,
 					simpleName,
 					SearchPattern.R_PREFIX_MATCH, // not case sensitive
 					IJavaSearchConstants.TYPE,
 					this.searchScope,
-					nameRequestor,
+					typeRequestor,
 					CANCEL_IF_NOT_READY_TO_SEARCH,
 					progressMonitor);
 			} catch (OperationCanceledException e) {
 				findTypes(
 					new String(prefix),
 					storage,
-					NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
+					NameLookup.ACCEPT_ALL);
 			}
 		} catch (JavaModelException e) {
 			findTypes(
 				new String(prefix),
 				storage,
-				NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
+				NameLookup.ACCEPT_ALL);
 		}
 	}
 
@@ -281,7 +354,7 @@
 	 */
 	private void findTypes(String prefix, ISearchRequestor storage, int type) {
 		SearchableEnvironmentRequestor requestor =
-			new SearchableEnvironmentRequestor(storage, this.unitToSkip);
+			new SearchableEnvironmentRequestor(storage, this.unitToSkip, this.project, this.nameLookup);
 		int index = prefix.lastIndexOf('.');
 		if (index == -1) {
 			this.nameLookup.seekTypes(prefix, null, true, type, requestor);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java
index d06e21d..f921993 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java
@@ -11,43 +11,61 @@
 package org.eclipse.jdt.internal.core;
 
 import org.eclipse.jdt.core.IInitializer;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IPackageFragment;
 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.internal.codeassist.ISearchRequestor;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 
 /**
  * Implements <code>IJavaElementRequestor</code>, wrappering and forwarding
  * results onto a <code>org.eclipse.jdt.internal.codeassist.api.ISearchRequestor</code>.
  */
-class SearchableEnvironmentRequestor extends JavaElementRequestor implements IJavaElementRequestor {
+class SearchableEnvironmentRequestor extends JavaElementRequestor {
 	/**
 	 * The <code>ISearchRequestor</code> this JavaElementRequestor wraps
 	 * and forwards results to.
 	 */
-	protected ISearchRequestor fRequestor;
+	protected ISearchRequestor requestor;
 	/**
 	 * The <code>ICompilationUNit</code> this JavaElementRequestor will not
 	 * accept types within.
 	 */
-	protected ICompilationUnit fUnitToSkip;
+	protected ICompilationUnit unitToSkip;
+	
+	protected IJavaProject project;
+	
+	protected NameLookup nameLookup;
+	
+	protected boolean checkAccessRestrictions;
 /**
  * Constructs a SearchableEnvironmentRequestor that wraps the
  * given SearchRequestor.
  */
 public SearchableEnvironmentRequestor(ISearchRequestor requestor) {
-	fRequestor = requestor;
-	fUnitToSkip= null;
+	this.requestor = requestor;
+	this.unitToSkip= null;
+	this.project= null;
+	this.nameLookup= null;
+	this.checkAccessRestrictions = false;
+	
 }
 /**
  * Constructs a SearchableEnvironmentRequestor that wraps the
  * given SearchRequestor.  The requestor will not accept types in
  * the <code>unitToSkip</code>.
  */
-public SearchableEnvironmentRequestor(ISearchRequestor requestor, ICompilationUnit unitToSkip) {
-	fRequestor = requestor;
-	fUnitToSkip= unitToSkip;
+public SearchableEnvironmentRequestor(ISearchRequestor requestor, ICompilationUnit unitToSkip, IJavaProject project, NameLookup nameLookup) {
+	this.requestor = requestor;
+	this.unitToSkip= unitToSkip;
+	this.project= project;
+	this.nameLookup = nameLookup;
+	this.checkAccessRestrictions = !JavaCore.IGNORE.equals(project.getOption(JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE, true));
 }
 /**
  * Do nothing, a SearchRequestor does not accept initializers
@@ -62,20 +80,40 @@
  * @see IJavaElementRequestor
  */
 public void acceptPackageFragment(IPackageFragment packageFragment) {
-	fRequestor.acceptPackage(packageFragment.getElementName().toCharArray());
+	this.requestor.acceptPackage(packageFragment.getElementName().toCharArray());
 }
 /**
  * @see IJavaElementRequestor
  */
 public void acceptType(IType type) {
 	try {
-		if (fUnitToSkip != null && fUnitToSkip.equals(type.getCompilationUnit())){
+		if (this.unitToSkip != null && this.unitToSkip.equals(type.getCompilationUnit())){
 			return;
 		}
+		String packageName = type.getPackageFragment().getElementName();
+		String typeName = type.getElementName();
+		boolean isBinary = type instanceof BinaryType;
+		
+		// determine associated access restriction
+		AccessRestriction accessRestriction = null;
+		
+		if (this.checkAccessRestrictions && (isBinary || !type.getJavaProject().equals(this.project))) {
+			PackageFragmentRoot root = (PackageFragmentRoot)type.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+			ClasspathEntry entry = (ClasspathEntry) this.nameLookup.rootToResolvedEntries.get(root);
+			if (entry != null) { // reverse map always contains resolved CP entry
+				accessRestriction = entry.getImportRestriction();
+				if (accessRestriction != null) {
+					// TODO (philippe) improve char[] <-> String conversions to avoid performing them on the fly
+					char[][] packageChars = CharOperation.splitOn('.', packageName.toCharArray());
+					char[] typeChars = typeName.toCharArray();
+					accessRestriction = accessRestriction.getViolatedRestriction(CharOperation.concatWith(packageChars, typeChars, '/'), null);
+				}
+			}
+		}
 		if (type.isClass()) {
-			fRequestor.acceptClass(type.getPackageFragment().getElementName().toCharArray(), type.getElementName().toCharArray(), type.getFlags());
+			this.requestor.acceptClass(type.getPackageFragment().getElementName().toCharArray(), type.getElementName().toCharArray(), type.getFlags(), accessRestriction);
 		} else {
-			fRequestor.acceptInterface(type.getPackageFragment().getElementName().toCharArray(), type.getElementName().toCharArray(), type.getFlags());
+			this.requestor.acceptInterface(type.getPackageFragment().getElementName().toCharArray(), type.getElementName().toCharArray(), type.getFlags(), accessRestriction);
 		}
 	} catch (JavaModelException jme) {
 		// ignore
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
index 93a3d5f..a932791 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
@@ -13,22 +13,32 @@
 import java.util.ArrayList;
 
 import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IField;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IMethod;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.ISourceRange;
 import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.ITypeParameter;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.codeassist.ISelectionRequestor;
 import org.eclipse.jdt.internal.codeassist.SelectionEngine;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedFieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedMethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 import org.eclipse.jdt.internal.core.util.HandleFactory;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * Implementation of <code>ISelectionRequestor</code> to assist with
@@ -69,25 +79,16 @@
  *
  * fix for 1FWFT6Q
  */
-protected void acceptBinaryMethod(IType type, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames) {
-	String[] parameterTypes= null;
-	if (parameterTypeNames != null) {
-		parameterTypes= new String[parameterTypeNames.length];
-		for (int i= 0, max = parameterTypeNames.length; i < max; i++) {
-			String pkg = IPackageFragment.DEFAULT_PACKAGE_NAME;
-			if (parameterPackageNames[i] != null && parameterPackageNames[i].length > 0) {
-				pkg = new String(parameterPackageNames[i]) + "."; //$NON-NLS-1$
-			}
-			
-			String typeName = new String(parameterTypeNames[i]);
-			if (typeName.indexOf('.') > 0) 
-				typeName = typeName.replace('.', '$');
-			parameterTypes[i]= Signature.createTypeSignature(
-				pkg + typeName, true);
-		}
-	}
-	IMethod method= type.getMethod(new String(selector), parameterTypes);
+protected void acceptBinaryMethod(IType type, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, String[] paramterSignatures, char[] uniqueKey) {
+	IMethod method= type.getMethod(new String(selector), paramterSignatures);
 	if (method.exists()) {
+		if(uniqueKey != null) {
+			method = new ParameterizedBinaryMethod(
+					(JavaElement)method.getParent(),
+					method.getElementName(),
+					method.getParameterTypes(),
+					new String(uniqueKey));
+		}
 		addElement(method);
 		if(SelectionEngine.DEBUG){
 			System.out.print("SELECTION - accept method("); //$NON-NLS-1$
@@ -97,10 +98,22 @@
 	}
 }
 /**
+ * Resolve the annotation.
+ */
+public void acceptAnnotation(char[] packageName, char[] annotationName, boolean isDeclaration, char[] genericTypeSignature, int start, int end) {
+	acceptType(packageName, annotationName, NameLookup.ACCEPT_ANNOTATIONS, isDeclaration, genericTypeSignature, start, end);
+}
+/**
  * Resolve the class.
  */
-public void acceptClass(char[] packageName, char[] className, boolean needQualification, boolean isDeclaration, int start, int end) {
-	acceptType(packageName, className, NameLookup.ACCEPT_CLASSES, needQualification, isDeclaration, start, end);
+public void acceptClass(char[] packageName, char[] className, boolean isDeclaration, char[] genericTypeSignature, int start, int end) {
+	acceptType(packageName, className, NameLookup.ACCEPT_CLASSES, isDeclaration, genericTypeSignature, start, end);
+}
+/**
+ * Resolve the enum.
+ */
+public void acceptEnum(char[] packageName, char[] enumName, boolean isDeclaration, char[] genericTypeSignature, int start, int end) {
+	acceptType(packageName, enumName, NameLookup.ACCEPT_ENUMS, isDeclaration, genericTypeSignature, start, end);
 }
 /**
  * @see ISelectionRequestor#acceptError
@@ -111,10 +124,10 @@
 /**
  * Resolve the field.
  */
-public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, boolean isDeclaration, int start, int end) {
+public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, boolean isDeclaration, char[] uniqueKey, int start, int end) {
 	if(isDeclaration) {
 		IType type= resolveTypeByLocation(declaringTypePackageName, declaringTypeName,
-				NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES,
+				NameLookup.ACCEPT_ALL,
 				start, end);
 		if(type != null) {
 			try {
@@ -139,11 +152,23 @@
 			}
 		}
 	} else {
-		IType type= resolveType(declaringTypePackageName, declaringTypeName,
-				NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
+		IType type= resolveType(declaringTypePackageName, declaringTypeName, NameLookup.ACCEPT_ALL);
 		if (type != null) {
 			IField field= type.getField(new String(name));
 			if (field.exists()) {
+				if(uniqueKey != null) {
+					if(field.isBinary()) {
+						field = new ParameterizedBinaryField(
+								(JavaElement)field.getParent(),
+								field.getElementName(),
+								new String(uniqueKey));
+					} else {
+						field = new ParameterizedSourceField(
+								(JavaElement)field.getParent(),
+								field.getElementName(),
+								new String(uniqueKey));
+					}
+				}
 				addElement(field);
 				if(SelectionEngine.DEBUG){
 					System.out.print("SELECTION - accept field("); //$NON-NLS-1$
@@ -157,14 +182,35 @@
 /**
  * Resolve the interface
  */
-public void acceptInterface(char[] packageName, char[] interfaceName, boolean needQualification, boolean isDeclaration, int start, int end) {
-	acceptType(packageName, interfaceName, NameLookup.ACCEPT_INTERFACES, needQualification, isDeclaration, start, end);
+public void acceptInterface(char[] packageName, char[] interfaceName, boolean isDeclaration, char[] genericTypeSignature, int start, int end) {
+	acceptType(packageName, interfaceName, NameLookup.ACCEPT_INTERFACES, isDeclaration, genericTypeSignature, start, end);
 }
-public void acceptLocalField(SourceTypeBinding typeBinding, char[] name, CompilationUnitDeclaration parsedUnit) {
-	IType type = (IType)this.handleFactory.createElement(typeBinding.scope.referenceContext, parsedUnit, this.openable);
-	if (type != null) {
-		IField field= type.getField(new String(name));
+public void acceptLocalField(FieldBinding fieldBinding) {
+	IJavaElement res;
+	if(fieldBinding.declaringClass instanceof ParameterizedTypeBinding) {
+		LocalTypeBinding localTypeBinding = (LocalTypeBinding)((ParameterizedTypeBinding)fieldBinding.declaringClass).type;
+		res = findLocalElement(localTypeBinding.sourceStart());
+	} else {
+		SourceTypeBinding typeBinding = (SourceTypeBinding)fieldBinding.declaringClass;
+		res = findLocalElement(typeBinding.sourceStart());
+	}
+	if (res != null && res.getElementType() == IJavaElement.TYPE) {
+		IType type = (IType) res;
+		IField field= type.getField(new String(fieldBinding.name));
 		if (field.exists()) {
+			if (fieldBinding instanceof ParameterizedFieldBinding) {
+				if(field.isBinary()) {
+					field = new ParameterizedBinaryField(
+							(JavaElement)field.getParent(),
+							field.getElementName(),
+							new String(fieldBinding.computeUniqueKey()));
+				} else {
+					field = new ParameterizedSourceField(
+							(JavaElement)field.getParent(),
+							field.getElementName(),
+							new String(fieldBinding.computeUniqueKey()));
+				}
+			}
 			addElement(field);
 			if(SelectionEngine.DEBUG){
 				System.out.print("SELECTION - accept field("); //$NON-NLS-1$
@@ -174,50 +220,64 @@
 		}
 	}
 }
-public void acceptLocalMethod(SourceTypeBinding typeBinding, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, boolean isConstructor, CompilationUnitDeclaration parsedUnit, boolean isDeclaration, int start, int end) {
-	IType type = (IType)this.handleFactory.createElement(typeBinding.scope.referenceContext, parsedUnit, this.openable);
-	// fix for 1FWFT6Q
-	if (type != null) {
-		if (type.isBinary()) {
-			
-			// need to add a paramater for constructor in binary type
-			IType declaringDeclaringType = type.getDeclaringType();
-			
-			boolean isStatic = false;
-			try {
-				isStatic = Flags.isStatic(type.getFlags());
-			} catch (JavaModelException e) {
-				// isStatic == false
+public void acceptLocalMethod(MethodBinding methodBinding) {
+	IJavaElement res = findLocalElement(methodBinding.sourceStart());
+	if(res != null && res.getElementType() == IJavaElement.METHOD) {
+		if (methodBinding instanceof ParameterizedMethodBinding) {
+			if(((IMethod)res).isBinary()) {
+				res = new ParameterizedBinaryField(
+						(JavaElement)res.getParent(),
+						res.getElementName(),
+						new String(methodBinding.computeUniqueKey()));
+			} else {
+				res = new ParameterizedSourceField(
+						(JavaElement)res.getParent(),
+						res.getElementName(),
+						new String(methodBinding.computeUniqueKey()));
 			}
-			
-			if(declaringDeclaringType != null && isConstructor	&& !isStatic) {
-				int length = parameterPackageNames.length;
-				System.arraycopy(parameterPackageNames, 0, parameterPackageNames = new char[length+1][], 1, length);
-				System.arraycopy(parameterTypeNames, 0, parameterTypeNames = new char[length+1][], 1, length);
-				
-				parameterPackageNames[0] = declaringDeclaringType.getPackageFragment().getElementName().toCharArray();
-				parameterTypeNames[0] = declaringDeclaringType.getTypeQualifiedName().toCharArray();
-			}
-			
-			acceptBinaryMethod(type, selector, parameterPackageNames, parameterTypeNames);
-		} else {
-			acceptSourceMethod(type, selector, parameterPackageNames, parameterTypeNames);
 		}
-	}
-}
-public void acceptLocalType(SourceTypeBinding typeBinding, CompilationUnitDeclaration parsedUnit) {
-	IJavaElement type = this.handleFactory.createElement(typeBinding.scope.referenceContext, parsedUnit, this.openable);
-	if (type != null) {
-		addElement(type);
+		addElement(res);
 		if(SelectionEngine.DEBUG){
-			System.out.print("SELECTION - accept local type("); //$NON-NLS-1$
-			System.out.print(type.toString());
+			System.out.print("SELECTION - accept method("); //$NON-NLS-1$
+			System.out.print(res.toString());
 			System.out.println(")"); //$NON-NLS-1$
 		}
 	}
 }
-public void acceptLocalVariable(LocalVariableBinding binding, CompilationUnitDeclaration parsedUnit) {
-	IJavaElement localVar = this.handleFactory.createElement(binding.declaration, parsedUnit, this.openable);
+public void acceptLocalType(TypeBinding typeBinding) {
+	IJavaElement res =  null;
+	if(typeBinding instanceof ParameterizedTypeBinding) {
+		LocalTypeBinding localTypeBinding = (LocalTypeBinding)((ParameterizedTypeBinding)typeBinding).type;
+		res = findLocalElement(localTypeBinding.sourceStart());
+		if(typeBinding.isParameterizedType()) {
+			res = new ParameterizedSourceType((JavaElement)res.getParent(), res.getElementName(), new String(typeBinding.computeUniqueKey()));
+		}
+	} else if(typeBinding instanceof SourceTypeBinding) {
+		res = findLocalElement(((SourceTypeBinding)typeBinding).sourceStart());
+	}
+	if(res != null && res.getElementType() == IJavaElement.TYPE) {
+		addElement(res);
+		if(SelectionEngine.DEBUG){
+			System.out.print("SELECTION - accept type("); //$NON-NLS-1$
+			System.out.print(res.toString());
+			System.out.println(")"); //$NON-NLS-1$
+		}
+	}
+}
+public void acceptLocalVariable(LocalVariableBinding binding) {
+	LocalDeclaration local = binding.declaration;
+	IJavaElement parent = findLocalElement(local.sourceStart); // findLocalElement() cannot find local variable
+	IJavaElement localVar = null;
+	if(parent != null) {
+		localVar = new LocalVariable(
+				(JavaElement)parent, 
+				new String(local.name), 
+				local.declarationSourceStart,
+				local.declarationSourceEnd,
+				local.sourceStart,
+				local.sourceEnd,
+				Util.typeSignature(local.type));
+	}
 	if (localVar != null) {
 		addElement(localVar);
 		if(SelectionEngine.DEBUG){
@@ -230,10 +290,10 @@
 /**
  * Resolve the method
  */
-public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, boolean isConstructor, boolean isDeclaration, int start, int end) {
+public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, String enclosingDeclaringTypeSignature, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, String[] parameterSignatures, boolean isConstructor, boolean isDeclaration, char[] uniqueKey, int start, int end) {
 	if(isDeclaration) {
 		IType type = resolveTypeByLocation(declaringTypePackageName, declaringTypeName,
-				NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES,
+				NameLookup.ACCEPT_ALL,
 				start, end);
 		
 		if(type != null) {
@@ -241,7 +301,7 @@
 		}
 	} else {
 		IType type = resolveType(declaringTypePackageName, declaringTypeName,
-			NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
+			NameLookup.ACCEPT_ALL);
 		// fix for 1FWFT6Q
 		if (type != null) {
 			if (type.isBinary()) {
@@ -260,14 +320,16 @@
 					int length = parameterPackageNames.length;
 					System.arraycopy(parameterPackageNames, 0, parameterPackageNames = new char[length+1][], 1, length);
 					System.arraycopy(parameterTypeNames, 0, parameterTypeNames = new char[length+1][], 1, length);
+					System.arraycopy(parameterSignatures, 0, parameterSignatures = new String[length+1], 1, length);
 					
 					parameterPackageNames[0] = declaringDeclaringType.getPackageFragment().getElementName().toCharArray();
 					parameterTypeNames[0] = declaringDeclaringType.getTypeQualifiedName().toCharArray();
+					parameterSignatures[0] = enclosingDeclaringTypeSignature;
 				}
 				
-				acceptBinaryMethod(type, selector, parameterPackageNames, parameterTypeNames);
+				acceptBinaryMethod(type, selector, parameterPackageNames, parameterTypeNames, parameterSignatures, uniqueKey);
 			} else {
-				acceptSourceMethod(type, selector, parameterPackageNames, parameterTypeNames);
+				acceptSourceMethod(type, selector, parameterPackageNames, parameterTypeNames, uniqueKey);
 			}
 		}
 	}
@@ -293,7 +355,7 @@
  *
  * fix for 1FWFT6Q
  */
-protected void acceptSourceMethod(IType type, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames) {
+protected void acceptSourceMethod(IType type, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, char[] uniqueKey) {
 	String name = new String(selector);
 	IMethod[] methods = null;
 	try {
@@ -301,7 +363,17 @@
 		for (int i = 0; i < methods.length; i++) {
 			if (methods[i].getElementName().equals(name)
 					&& methods[i].getParameterTypes().length == parameterTypeNames.length) {
-				addElement(methods[i]);
+				if(uniqueKey != null) {
+					IMethod method = methods[i];
+					ParameterizedSourceMethod parameterizedSourceMethod = new ParameterizedSourceMethod(
+							(JavaElement)method.getParent(),
+							method.getElementName(),
+							method.getParameterTypes(),
+							new String(uniqueKey));
+					addElement(parameterizedSourceMethod);
+				} else {
+					addElement(methods[i]);
+				}
 			}
 		}
 	} catch (JavaModelException e) {
@@ -393,12 +465,19 @@
 /**
  * Resolve the type, adding to the resolved elements.
  */
-protected void acceptType(char[] packageName, char[] typeName, int acceptFlags, boolean needQualification, boolean isDeclaration, int start, int end) {
+protected void acceptType(char[] packageName, char[] typeName, int acceptFlags, boolean isDeclaration, char[] genericTypeSignature, int start, int end) {
 	IType type = null;
 	if(isDeclaration) {
 		type = resolveTypeByLocation(packageName, typeName, acceptFlags, start, end);
 	} else {
 		type = resolveType(packageName, typeName, acceptFlags);
+		if(type != null && genericTypeSignature != null) {
+			if(type.isBinary()) {
+				type = new ParameterizedBinaryType((JavaElement)type.getParent(), type.getElementName(), new String(genericTypeSignature));
+			} else {
+				type = new ParameterizedSourceType((JavaElement)type.getParent(), type.getElementName(), new String(genericTypeSignature));
+			}
+		}
 	}
 	
 	if (type != null) {
@@ -410,6 +489,89 @@
 		}
 	} 
 }
+public void acceptTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] typeParameterName, boolean isDeclaration, int start, int end) {
+	IType type;
+	if(isDeclaration) {
+		type = resolveTypeByLocation(declaringTypePackageName, declaringTypeName,
+				NameLookup.ACCEPT_ALL,
+				start, end);
+	} else {
+		type = resolveType(declaringTypePackageName, declaringTypeName,
+				NameLookup.ACCEPT_ALL);
+	}
+			
+	if(type != null) {
+		ITypeParameter typeParameter = type.getTypeParameter(new String(typeParameterName));
+		if(typeParameter == null) {
+			addElement(type);
+			if(SelectionEngine.DEBUG){
+				System.out.print("SELECTION - accept type("); //$NON-NLS-1$
+				System.out.print(type.toString());
+				System.out.println(")"); //$NON-NLS-1$
+			}
+		} else {
+			addElement(typeParameter);
+			if(SelectionEngine.DEBUG){
+				System.out.print("SELECTION - accept type parameter("); //$NON-NLS-1$
+				System.out.print(typeParameter.toString());
+				System.out.println(")"); //$NON-NLS-1$
+			}
+		}
+	}
+}
+public void acceptMethodTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector,int selectorStart, int selectorEnd, char[] typeParameterName, boolean isDeclaration, int start, int end) {
+	IType type = resolveTypeByLocation(declaringTypePackageName, declaringTypeName,
+			NameLookup.ACCEPT_ALL,
+			selectorStart, selectorEnd);
+	
+	if(type != null) {
+		IMethod method = null;
+		
+		String name = new String(selector);
+		IMethod[] methods = null;
+		
+		try {
+			methods = type.getMethods();
+			done : for (int i = 0; i < methods.length; i++) {
+				ISourceRange range = methods[i].getNameRange();
+				if(range.getOffset() >= selectorStart
+						&& range.getOffset() + range.getLength() <= selectorEnd
+						&& methods[i].getElementName().equals(name)) {
+					method = methods[i];
+					break done;
+				}
+			}
+		} catch (JavaModelException e) {
+			//nothing to do
+		}
+
+		if(method == null) {
+			addElement(type);
+			if(SelectionEngine.DEBUG){
+				System.out.print("SELECTION - accept type("); //$NON-NLS-1$
+				System.out.print(type.toString());
+				System.out.println(")"); //$NON-NLS-1$
+			}
+		} else {
+			ITypeParameter typeParameter = method.getTypeParameter(new String(typeParameterName));
+			if(typeParameter == null) {
+				addElement(method);
+				if(SelectionEngine.DEBUG){
+					System.out.print("SELECTION - accept method("); //$NON-NLS-1$
+					System.out.print(method.toString());
+					System.out.println(")"); //$NON-NLS-1$
+				}
+			} else {
+				addElement(typeParameter);
+				if(SelectionEngine.DEBUG){
+					System.out.print("SELECTION - accept method type parameter("); //$NON-NLS-1$
+					System.out.print(typeParameter.toString());
+					System.out.println(")"); //$NON-NLS-1$
+				}
+			}
+		}
+	}
+}
 /*
  * Adds the given element to the list of resolved elements.
  */
@@ -420,6 +582,29 @@
 	}
 	this.elements[++this.elementIndex] = element;
 }
+
+/*
+ * findLocalElement() cannot find local variable
+ */
+protected IJavaElement findLocalElement(int pos) {
+	IJavaElement res = null;
+	if(this.openable instanceof ICompilationUnit) {
+		ICompilationUnit cu = (ICompilationUnit) this.openable;
+		try {
+			res = cu.getElementAt(pos);
+		} catch (JavaModelException e) {
+			// do nothing
+		}
+	} else if (this.openable instanceof ClassFile) {
+		ClassFile cf = (ClassFile) this.openable;
+		try {
+			 res = cf.getElementAtConsideringSibling(pos);
+		} catch (JavaModelException e) {
+			// do nothing
+		}
+	}
+	return res;
+}
 /**
  * Returns the resolved elements.
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java
index 1bb8d83..837d73f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java
@@ -10,7 +10,6 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
-import java.io.File;
 import java.util.*;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -33,6 +32,7 @@
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaModelException;
 
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
 import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
 import org.eclipse.jdt.internal.core.util.Util;
@@ -54,11 +54,12 @@
 	IPath newOutputLocation;
 	JavaProject project;
 	boolean identicalRoots;
-
-	public static final IClasspathEntry[] ReuseClasspath = new IClasspathEntry[0];
-	public static final IClasspathEntry[] UpdateClasspath = new IClasspathEntry[0];
+	
+	public static final IClasspathEntry[] REUSE_ENTRIES = new IClasspathEntry[0];
+	public static final IClasspathEntry[] UPDATE_ENTRIES = new IClasspathEntry[0];
 	// if reusing output location, then also reuse clean flag
-	public static final IPath ReuseOutputLocation = new Path("Reuse Existing Output Location");  //$NON-NLS-1$
+	public static final IPath REUSE_PATH = new Path("Reuse Existing Output Location");  //$NON-NLS-1$
+	public static final IPath[] REUSE_PATHS = new IPath[0];
 	
 	/**
 	 * When executed, this operation sets the classpath of the given project.
@@ -214,7 +215,7 @@
 				IPath path = classpath[i].getPath();
 				if (entry.getEntryKind() != IClasspathEntry.CPE_PROJECT && path.isPrefixOf(location) && !path.equals(location)) {
 					IPackageFragmentRoot[] roots = project.computePackageFragmentRoots(classpath[i]);
-					IPackageFragmentRoot root = roots[0];
+					PackageFragmentRoot root = (PackageFragmentRoot) roots[0];
 					// now the output location becomes a package fragment - along with any subfolders
 					ArrayList folders = new ArrayList();
 					folders.add(folder);
@@ -224,12 +225,8 @@
 					while (elements.hasNext()) {
 						IFolder f = (IFolder) elements.next();
 						IPath relativePath = f.getFullPath().removeFirstSegments(segments);
-						String name = relativePath.toOSString();
-						name = name.replace(File.pathSeparatorChar, '.');
-						if (name.endsWith(".")) { //$NON-NLS-1$
-							name = name.substring(0, name.length() - 1);
-						}
-						IPackageFragment pkg = root.getPackageFragment(name);
+						String[] pkgName = relativePath.segments();
+						IPackageFragment pkg = root.getPackageFragment(pkgName);
 						fragments.add(pkg);
 					}
 				}
@@ -254,8 +251,8 @@
 		JavaModelException originalException = null;
 
 		try {
-			if (this.newRawPath == UpdateClasspath) this.newRawPath = project.getRawClasspath();
-			if (this.newRawPath != ReuseClasspath){
+			if (this.newRawPath == UPDATE_ENTRIES) this.newRawPath = project.getRawClasspath();
+			if (this.newRawPath != REUSE_ENTRIES){
 				updateClasspath();
 				project.updatePackageFragmentRoots();
 				JavaModelManager.getJavaModelManager().getDeltaProcessor().addForRefresh(project);
@@ -268,7 +265,7 @@
 		} finally { // if traversed by an exception we still need to update the output location when necessary
 
 			try {
-				if (this.newOutputLocation != ReuseOutputLocation) updateOutputLocation();
+				if (this.newOutputLocation != REUSE_PATH) updateOutputLocation();
 
 			} catch(JavaModelException e){
 				if (originalException != null) throw originalException; 
@@ -357,9 +354,10 @@
 							oldResolvedPath[i], 
 							accumulatedRoots, 
 							rootIDs,
-							true, // inside original project
+							null, // inside original project
 							false, // don't check existency
-							false); // don't retrieve exported roots
+							false, // don't retrieve exported roots
+							null); /*no reverse map*/
 						pkgFragmentRoots = new IPackageFragmentRoot[accumulatedRoots.size()];
 						accumulatedRoots.copyInto(pkgFragmentRoots);
 					} catch (JavaModelException e) {
@@ -413,7 +411,21 @@
 			} else {
 				// do not notify remote project changes
 				if (oldResolvedPath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
-					this.needCycleCheck |= (oldResolvedPath[i].isExported() != newResolvedPath[index].isExported());
+					// Need to updated dependents in case old and/or new entries are exported and have an access restriction
+					ClasspathEntry oldEntry = (ClasspathEntry) oldResolvedPath[i];
+					ClasspathEntry newEntry = (ClasspathEntry) newResolvedPath[index];
+					if (oldEntry.isExported || newEntry.isExported) { // then we need to verify if there's access restriction
+						AccessRestriction oldRestriction = oldEntry.getImportRestriction();
+						AccessRestriction newRestriction = newEntry.getImportRestriction();
+						if (index != i) { // entry has been moved
+							needToUpdateDependents |= (oldRestriction != null || newRestriction != null); // there's an access restriction, this may change combination
+						} else if (oldRestriction == null) {
+							needToUpdateDependents |= newRestriction != null; // access restriction was added
+						} else {
+							needToUpdateDependents |= !oldRestriction.equals(newRestriction); // access restriction has changed or has been removed
+						}
+					}
+					this.needCycleCheck |= (oldEntry.isExported() != newEntry.isExported());
 					continue; 
 				}				
 				needToUpdateDependents |= (oldResolvedPath[i].isExported() != newResolvedPath[index].isExported());
@@ -569,13 +581,13 @@
 		if (!this.canChangeResources || !this.needSave) return;
 				
 		IClasspathEntry[] classpathForSave;
-		if (this.newRawPath == ReuseClasspath || this.newRawPath == UpdateClasspath){
+		if (this.newRawPath == REUSE_ENTRIES || this.newRawPath == UPDATE_ENTRIES){
 			classpathForSave = project.getRawClasspath();
 		} else {
 			classpathForSave = this.newRawPath;
 		}
 		IPath outputLocationForSave;
-		if (this.newOutputLocation == ReuseOutputLocation){
+		if (this.newOutputLocation == REUSE_PATH){
 			outputLocationForSave = project.getOutputLocation();
 		} else {
 			outputLocationForSave = this.newOutputLocation;
@@ -591,7 +603,7 @@
 		StringBuffer buffer = new StringBuffer(20);
 		buffer.append("SetClasspathOperation\n"); //$NON-NLS-1$
 		buffer.append(" - classpath : "); //$NON-NLS-1$
-		if (this.newRawPath == ReuseClasspath){
+		if (this.newRawPath == REUSE_ENTRIES){
 			buffer.append("<Reuse Existing Classpath>"); //$NON-NLS-1$
 		} else {
 			buffer.append("{"); //$NON-NLS-1$
@@ -602,7 +614,7 @@
 			}
 		}
 		buffer.append("\n - output location : ");  //$NON-NLS-1$
-		if (this.newOutputLocation == ReuseOutputLocation){
+		if (this.newOutputLocation == REUSE_PATH){
 			buffer.append("<Reuse Existing Output Location>"); //$NON-NLS-1$
 		} else {
 			buffer.append(this.newOutputLocation.toString()); //$NON-NLS-1$
@@ -639,7 +651,8 @@
 	protected void updateAffectedProjects(IPath prerequisiteProjectPath) {
 
 		// remove all update classpath post actions for this project
-		removeAllPostAction(prerequisiteProjectPath.toString());
+		final String updateClasspath = "UpdateClassPath:"; //$NON-NLS-1$
+		removeAllPostAction(updateClasspath + prerequisiteProjectPath.toString());
 		
 		try {
 			IJavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
@@ -661,12 +674,12 @@
 								
 							postAction(new IPostAction() {
 									public String getID() {
-										return affectedProject.getPath().toString();
+										return updateClasspath + affectedProject.getPath().toString();
 									}
 									public void run() throws JavaModelException {
 										affectedProject.setRawClasspath(
-											UpdateClasspath, 
-											SetClasspathOperation.ReuseOutputLocation, 
+											UPDATE_ENTRIES, 
+											SetClasspathOperation.REUSE_PATH, 
 											SetClasspathOperation.this.progressMonitor, 
 											SetClasspathOperation.this.canChangeResources,  
 											affectedProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/), 
@@ -766,7 +779,7 @@
 	 */
 	protected void updateProjectReferencesIfNecessary() throws JavaModelException {
 		
-		if (this.newRawPath == ReuseClasspath || this.newRawPath == UpdateClasspath) return;
+		if (this.newRawPath == REUSE_ENTRIES || this.newRawPath == UPDATE_ENTRIES) return;
 		// will run now, or be deferred until next pre-auto-build notification if resource tree is locked
 		JavaModelManager.getJavaModelManager().deltaState.performClasspathResourceChange(
 		        project, 
@@ -786,7 +799,7 @@
 		if (needValidation) {
 			// retrieve classpath 
 			IClasspathEntry[] entries = this.newRawPath;
-			if (entries == ReuseClasspath){
+			if (entries == REUSE_ENTRIES){
 				try {
 					entries = project.getRawClasspath();			
 				} catch (JavaModelException e) {
@@ -795,7 +808,7 @@
 			}		
 			// retrieve output location
 			IPath outputLocation = this.newOutputLocation;
-			if (outputLocation == ReuseOutputLocation){
+			if (outputLocation == REUSE_PATH){
 				try {
 					outputLocation = project.getOutputLocation();
 				} catch (JavaModelException e) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementBuilder.java
index ae7c5cc..31233cc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementBuilder.java
@@ -27,8 +27,9 @@
 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
 import org.eclipse.jdt.core.util.CompilationUnitSorter;
 import org.eclipse.jdt.internal.compiler.SourceElementRequestorAdapter;
-import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.env.IConstants;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
@@ -927,12 +928,12 @@
 	int[] positionsToMap;
 	int positionsToMapIndex;
 	
-	public SortElementBuilder(char[] source, int[] positionsToMap, Comparator comparator) {
+	public SortElementBuilder(char[] source, int[] positionsToMap, Comparator comparator, CompilerOptions options) {
 		this.source = source;
 		this.comparator = comparator;
 		this.positionsToMap = positionsToMap;
-		this.scanner = new Scanner(false, false, false, ClassFileConstants.JDK1_3/*sourceLevel*/, null, null, true/*taskCaseSensitive*/);
 		this.ast = AST.newAST(AST.JLS2);
+		this.scanner = new Scanner(false, false, false, options.sourceLevel/*sourceLevel*/, null, null, true/*taskCaseSensitive*/);
 	}
 	
 	/*
@@ -999,22 +1000,6 @@
 		this.positionsToMapIndex = i;
 	}
 	/**
-	 * @see org.eclipse.jdt.internal.compiler.ISourceElementRequestor#enterClass(int, int, char[], int, int, char[], char[][])
-	 */
-	public void enterClass(
-		int declarationStart,
-		int modifiers,
-		char[] name,
-		int nameSourceStart,
-		int nameSourceEnd,
-		char[] superclass,
-		char[][] superinterfaces) {
-			SortType type = new SortClassDeclaration(declarationStart, modifiers, name, superclass, superinterfaces);
-			this.currentElement.addChild(type);
-			push(type);
-	}
-
-	/**
 	 * @see org.eclipse.jdt.internal.compiler.ISourceElementRequestor#enterCompilationUnit()
 	 */
 	public void enterCompilationUnit() {
@@ -1023,44 +1008,30 @@
 	}
 
 	/**
-	 * @see org.eclipse.jdt.internal.compiler.ISourceElementRequestor#enterConstructor(int, int, char[], int, int, char[][], char[][], char[][])
+	 * @see org.eclipse.jdt.internal.compiler.ISourceElementRequestor#enterConstructor(MethodInfo)
 	 */
-	public void enterConstructor(
-		int declarationStart,
-		int modifiers,
-		char[] name,
-		int nameSourceStart,
-		int nameSourceEnd,
-		char[][] parameterTypes,
-		char[][] parameterNames,
-		char[][] exceptionTypes) {
+	public void enterConstructor(MethodInfo methodInfo) {
 		if ((this.currentElement.id & SortJavaElement.TYPE) != 0) {
-			SortConstructorDeclaration constructorDeclaration = new SortConstructorDeclaration(declarationStart, modifiers, name, parameterNames, parameterTypes, exceptionTypes);
+			SortConstructorDeclaration constructorDeclaration = new SortConstructorDeclaration(methodInfo.declarationStart, methodInfo.modifiers, methodInfo.name, methodInfo.parameterNames, methodInfo.parameterTypes, methodInfo.exceptionTypes);
 			this.currentElement.addChild(constructorDeclaration);
 			push(constructorDeclaration);
 		}
 	}
 
 	/**
-	 * @see org.eclipse.jdt.internal.compiler.ISourceElementRequestor#enterField(int, int, char[], char[], int, int)
+	 * @see org.eclipse.jdt.internal.compiler.ISourceElementRequestor#enterField(FieldInfo)
 	 */
-	public void enterField(
-		int declarationStart,
-		int modifiers,
-		char[] type,
-		char[] name,
-		int nameSourceStart,
-		int nameSourceEnd) {
+	public void enterField(FieldInfo fieldInfo) {
 			if ((this.currentElement.id & SortJavaElement.TYPE) != 0) {
-				SortFieldDeclaration fieldDeclaration = new SortFieldDeclaration(declarationStart, modifiers, type, name, nameSourceStart);
+				SortFieldDeclaration fieldDeclaration = new SortFieldDeclaration(fieldInfo.declarationStart, fieldInfo.modifiers, fieldInfo.type, fieldInfo.name, fieldInfo.nameSourceStart);
 				SortElement[] currentElementChildren = this.currentElement.children;
 				if (currentElementChildren != null) {
 					SortElement previousElement = this.currentElement.children[this.currentElement.children_count - 1];
-					if (previousElement.id == SortJavaElement.FIELD && ((SortFieldDeclaration) previousElement).declarationStart == declarationStart) {
+					if (previousElement.id == SortJavaElement.FIELD && ((SortFieldDeclaration) previousElement).declarationStart == fieldInfo.declarationStart) {
 						SortMultipleFieldDeclaration multipleFielDeclaration = new SortMultipleFieldDeclaration((SortFieldDeclaration) previousElement);
 						multipleFielDeclaration.addField(fieldDeclaration);
 						this.currentElement.children[this.currentElement.children_count - 1] = multipleFielDeclaration;
-					} else if (previousElement.id == SortJavaElement.MULTIPLE_FIELD && ((SortMultipleFieldDeclaration) previousElement).declarationStart == declarationStart) {
+					} else if (previousElement.id == SortJavaElement.MULTIPLE_FIELD && ((SortMultipleFieldDeclaration) previousElement).declarationStart == fieldInfo.declarationStart) {
 						((SortMultipleFieldDeclaration) previousElement).addField(fieldDeclaration);
 					} else {
 						this.currentElement.addChild(fieldDeclaration);
@@ -1084,45 +1055,33 @@
 	}
 
 	/**
-	 * @see org.eclipse.jdt.internal.compiler.ISourceElementRequestor#enterInterface(int, int, char[], int, int, char[][])
+	 * @see org.eclipse.jdt.internal.compiler.ISourceElementRequestor#enterMethod(MethodInfo)
 	 */
-	public void enterInterface(
-		int declarationStart,
-		int modifiers,
-		char[] name,
-		int nameSourceStart,
-		int nameSourceEnd,
-		char[][] superinterfaces) {
-			SortType type = new SortInterfaceDeclaration(declarationStart, modifiers, name, superinterfaces);
-			this.currentElement.addChild(type);
-			push(type);
+	public void enterMethod(MethodInfo methodInfo) {
+		if ((this.currentElement.id & SortJavaElement.TYPE) != 0) {
+			SortMethodDeclaration methodDeclaration = new SortMethodDeclaration(methodInfo.declarationStart, methodInfo.modifiers, methodInfo.name, methodInfo.parameterNames, methodInfo.parameterTypes, methodInfo.exceptionTypes, methodInfo.returnType);
+			this.currentElement.addChild(methodDeclaration);
+			push(methodDeclaration);
+		}
 	}
 
 	/**
-	 * @see org.eclipse.jdt.internal.compiler.ISourceElementRequestor#enterMethod(int, int, char[], char[], int, int, char[][], char[][], char[][])
+	 * @see org.eclipse.jdt.internal.compiler.ISourceElementRequestor#enterType(TypeInfo)
 	 */
-	public void enterMethod(
-		int declarationStart,
-		int modifiers,
-		char[] returnType,
-		char[] name,
-		int nameSourceStart,
-		int nameSourceEnd,
-		char[][] parameterTypes,
-		char[][] parameterNames,
-		char[][] exceptionTypes) {
-			if ((this.currentElement.id & SortJavaElement.TYPE) != 0) {
-				SortMethodDeclaration methodDeclaration = new SortMethodDeclaration(declarationStart, modifiers, name, parameterNames, parameterTypes, exceptionTypes, returnType);
-				this.currentElement.addChild(methodDeclaration);
-				push(methodDeclaration);
-			}
-	}
-
-	/**
-	 * @see org.eclipse.jdt.internal.compiler.ISourceElementRequestor#exitClass(int)
-	 */
-	public void exitClass(int declarationEnd) {
-		pop(declarationEnd);
+	public void enterType(TypeInfo typeInfo) {
+		SortType type = null;
+		switch (typeInfo.kind) {
+			case IGenericType.CLASS_DECL:
+			case IGenericType.ANNOTATION_TYPE_DECL: // TODO (olivier) might need a SortAnnotationTypeDeclaration
+				type = new SortClassDeclaration(typeInfo.declarationStart, typeInfo.modifiers, typeInfo.name, typeInfo.superclass, typeInfo.superinterfaces);
+				break;
+			case IGenericType.INTERFACE_DECL:
+			case IGenericType.ENUM_DECL: // TODO (olivier) might need a SortEnumDeclaration
+				type = new SortInterfaceDeclaration(typeInfo.declarationStart, typeInfo.modifiers, typeInfo.name, typeInfo.superinterfaces);
+				break;
+		}
+		this.currentElement.addChild(type);
+		push(type);
 	}
 
 	/**
@@ -1178,16 +1137,16 @@
 	}
 
 	/**
-	 * @see org.eclipse.jdt.internal.compiler.ISourceElementRequestor#exitInterface(int)
+	 * @see org.eclipse.jdt.internal.compiler.ISourceElementRequestor#exitMethod(int, int, int)
 	 */
-	public void exitInterface(int declarationEnd) {
+	public void exitMethod(int declarationEnd, int defaultValueStart, int defaultValueEnd) {
 		pop(declarationEnd);
 	}
 
 	/**
-	 * @see org.eclipse.jdt.internal.compiler.ISourceElementRequestor#exitMethod(int)
+	 * @see org.eclipse.jdt.internal.compiler.ISourceElementRequestor#exitType(int)
 	 */
-	public void exitMethod(int declarationEnd) {
+	public void exitType(int declarationEnd) {
 		pop(declarationEnd);
 	}
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementsOperation.java
index 9e11710..29fbf3d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementsOperation.java
@@ -18,8 +18,6 @@
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaModelStatus;
 import org.eclipse.jdt.core.IJavaModelStatusConstants;
-import org.eclipse.jdt.core.IPackageFragment;
-import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.SourceElementParser;
@@ -88,15 +86,16 @@
 	 * @param source
 	 */
 	private String processElement(ICompilationUnit unit, int[] positionsToMap, char[] source) {
-		SortElementBuilder builder = new SortElementBuilder(source, positionsToMap, this.comparator);
+		CompilerOptions options = new CompilerOptions(unit.getJavaProject().getOptions(true));
+		SortElementBuilder builder = new SortElementBuilder(source, positionsToMap, this.comparator, options);
 		SourceElementParser parser = new SourceElementParser(builder,
-			ProblemFactory.getProblemFactory(Locale.getDefault()), new CompilerOptions(JavaCore.getOptions()), true);
+			ProblemFactory.getProblemFactory(Locale.getDefault()), options, true);
 		
 		if (unit.exists()) {
-			IPackageFragment packageFragment = (IPackageFragment)unit.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
+			PackageFragment packageFragment = (PackageFragment)unit.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
 			char[][] expectedPackageName = null;
 			if (packageFragment != null){
-				expectedPackageName = CharOperation.splitOn('.', packageFragment.getElementName().toCharArray());
+				expectedPackageName = Util.toCharArrays(packageFragment.names);
 			}
 			parser.parseCompilationUnit(
 				new BasicCompilationUnit(
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceAnnotationMethodInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceAnnotationMethodInfo.java
new file mode 100644
index 0000000..34cc073
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceAnnotationMethodInfo.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+
+/*
+ * Element info for annotation method from source.
+ */
+public class SourceAnnotationMethodInfo extends SourceMethodInfo {
+
+	/*
+	 * The positions of a default member value of an annotation method.
+	 * These are {-1, -1} if the method is an annotation method with no default value.
+	 * Otherwise these are the start and end (inclusive) of the expression representing the default value.
+	 */
+	protected int defaultValueStart;
+	protected int defaultValueEnd;
+
+	public boolean isAnnotationMethod() {
+		return true;
+	}
+	
+	public char[] getDefaultValueSource(char[] cuSource) {
+		if (this.defaultValueStart == -1 && this.defaultValueEnd == -1) 
+			return null;
+		return CharOperation.subarray(cuSource, this.defaultValueStart, this.defaultValueEnd+1);
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceConstructorInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceConstructorInfo.java
new file mode 100644
index 0000000..07468d4
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceConstructorInfo.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+/*
+ * Element info for constructor from source.
+ */
+public class SourceConstructorInfo extends SourceMethodElementInfo {
+	
+	private static final char[] RETURN_TYPE_NAME = new char[]{'v', 'o','i', 'd'};
+	
+	public boolean isAnnotationMethod() {
+		// a constructor cannot be an annotation method
+		return false;
+	}
+	
+	public boolean isConstructor() {
+		return true;
+	}
+	
+	public char[] getReturnTypeName() {
+		return RETURN_TYPE_NAME;
+	}
+	
+	protected void setReturnType(char[] type) {
+		// ignore (always void)
+	}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java
index 5974b74..746d179 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java
@@ -21,7 +21,7 @@
  * @see IField
  */
 
-/* package */ class SourceField extends Member implements IField {
+public class SourceField extends NamedMember implements IField {
 
 /**
  * Constructs a handle to the field with the given name in the specified type. 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java
index df249da..de0c5bb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java
@@ -18,6 +18,8 @@
  */
 
 public class SourceFieldElementInfo extends MemberElementInfo implements ISourceField {
+	
+	protected char[] fieldName;
 
 	/**
 	 * The type name of this field.
@@ -36,6 +38,9 @@
 public char[] getInitializationSource() {
 	return this.initializationSource;
 }
+public char[] getName() {
+	return this.fieldName;
+}
 /**
  * Returns the type name of the field.
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java
index d969ade..a4013a0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java
@@ -33,7 +33,6 @@
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IMember;
 import org.eclipse.jdt.core.IMethod;
-import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.ISourceRange;
 import org.eclipse.jdt.core.IType;
@@ -71,7 +70,7 @@
 	 */
 	private static final FilenameFilter FILENAME_FILTER = new FilenameFilter() {
 		public boolean accept(File dir, String name) {
-			return name.endsWith(SUFFIX_STRING_JAVA) || name.endsWith(SUFFIX_STRING_java); //$NON-NLS-1$
+			return org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(name);
 		}
 	};
 	/**
@@ -84,7 +83,7 @@
 	/**
 	 * The binary type source is being mapped for
 	 */
-	protected BinaryType fType;
+	protected BinaryType binaryType;
 
 	/**
 	 * The location of the zip file containing source.
@@ -219,13 +218,13 @@
 			char[] name,
 			boolean onDemand,
 			int modifiers) {
-		char[][] imports = (char[][]) this.importsTable.get(fType);
+		char[][] imports = (char[][]) this.importsTable.get(this.binaryType);
 		int importsCounter;
 		if (imports == null) {
 			imports = new char[5][];
 			importsCounter = 0;
 		} else {
-			importsCounter = ((Integer) this.importsCounterTable.get(fType)).intValue();
+			importsCounter = ((Integer) this.importsCounterTable.get(this.binaryType)).intValue();
 		}
 		if (imports.length == importsCounter) {
 			System.arraycopy(
@@ -242,8 +241,8 @@
 			name[nameLength + 1] = '*';
 		}
 		imports[importsCounter++] = name;
-		this.importsTable.put(fType, imports);
-		this.importsCounterTable.put(fType, new Integer(importsCounter));
+		this.importsTable.put(this.binaryType, imports);
+		this.importsCounterTable.put(this.binaryType, new Integer(importsCounter));
 	}
 	
 	/**
@@ -387,14 +386,15 @@
 				zip = manager.getZipFile(this.sourcePath);
 				for (Enumeration entries = zip.entries(); entries.hasMoreElements(); ) {
 					ZipEntry entry = (ZipEntry) entries.nextElement();
-					if (!entry.isDirectory()) {
-						IPath path = new Path(entry.getName());
+					String entryName;
+					if (!entry.isDirectory() && org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(entryName = entry.getName())) {
+						IPath path = new Path(entryName);
 						int segmentCount = path.segmentCount();
 						if (segmentCount > 1) {
 							loop: for (int i = 0, max = path.segmentCount() - 1; i < max; i++) {
 								if (firstLevelPackageNames.contains(path.segment(i))) {
 									this.rootPaths.add(path.uptoSegment(i).toString());
-									break loop;
+									// don't break here as this path could contain other first level package names (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=74014)
 								}
 								if (i == max - 1 && containsADefaultPackage) {
 									this.rootPaths.add(path.uptoSegment(max).toString());
@@ -477,7 +477,7 @@
 					// check if one member is a .java file
 					boolean hasJavaSourceFile = false;
 					for (int j = 0; j < max; j++) {
-						if (Util.isJavaFileName(resources[i].getName())) {
+						if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(resources[i].getName())) {
 							hasJavaSourceFile = true;
 							break;
 						}
@@ -497,14 +497,7 @@
 	/**
 	 * @see ISourceElementRequestor
 	 */
-	public void enterClass(
-		int declarationStart,
-		int modifiers,
-		char[] name,
-		int nameSourceStart,
-		int nameSourceEnd,
-		char[] superclass,
-		char[][] superinterfaces) {
+	public void enterType(TypeInfo typeInfo) {
 
 		this.typeDepth++;
 		if (this.typeDepth == this.types.length) { // need to grow
@@ -557,19 +550,19 @@
 				0,
 				this.typeDepth);					
 		}
-		if (name.length == 0) {
+		if (typeInfo.name.length == 0) {
 			this.anonymousCounter++;
 			if (this.anonymousCounter == this.anonymousClassName) {
-				this.types[typeDepth] = this.getType(fType.getElementName());
+				this.types[typeDepth] = this.getType(this.binaryType.getElementName());
 			} else {
-				this.types[typeDepth] = this.getType(new String(name));				
+				this.types[typeDepth] = this.getType(new String(typeInfo.name));				
 			}
 		} else {
-			this.types[typeDepth] = this.getType(new String(name));
+			this.types[typeDepth] = this.getType(new String(typeInfo.name));
 		}
 		this.typeNameRanges[typeDepth] =
-			new SourceRange(nameSourceStart, nameSourceEnd - nameSourceStart + 1);
-		this.typeDeclarationStarts[typeDepth] = declarationStart;
+			new SourceRange(typeInfo.nameSourceStart, typeInfo.nameSourceEnd - typeInfo.nameSourceStart + 1);
+		this.typeDeclarationStarts[typeDepth] = typeInfo.declarationStart;
 	}
 	
 	/**
@@ -582,42 +575,19 @@
 	/**
 	 * @see ISourceElementRequestor
 	 */
-	public void enterConstructor(
-		int declarationStart,
-		int modifiers,
-		char[] name,
-		int nameSourceStart,
-		int nameSourceEnd,
-		char[][] parameterTypes,
-		char[][] parameterNames,
-		char[][] exceptionTypes) {
-		enterMethod(
-			declarationStart,
-			modifiers,
-			null,
-			name,
-			nameSourceStart,
-			nameSourceEnd,
-			parameterTypes,
-			parameterNames,
-			exceptionTypes);
+	public void enterConstructor(MethodInfo methodInfo) {
+		enterAbstractMethod(methodInfo);
 	}
 	
 	/**
 	 * @see ISourceElementRequestor
 	 */
-	public void enterField(
-		int declarationStart,
-		int modifiers,
-		char[] type,
-		char[] name,
-		int nameSourceStart,
-		int nameSourceEnd) {
+	public void enterField(FieldInfo fieldInfo) {
 		if (typeDepth >= 0) {
-			fMemberDeclarationStart[typeDepth] = declarationStart;
+			fMemberDeclarationStart[typeDepth] = fieldInfo.declarationStart;
 			fMemberNameRange[typeDepth] =
-				new SourceRange(nameSourceStart, nameSourceEnd - nameSourceStart + 1);
-			fMemberName[typeDepth] = new String(name);
+				new SourceRange(fieldInfo.nameSourceStart, fieldInfo.nameSourceEnd - fieldInfo.nameSourceStart + 1);
+			fMemberName[typeDepth] = new String(fieldInfo.name);
 		}
 	}
 	
@@ -633,50 +603,24 @@
 	/**
 	 * @see ISourceElementRequestor
 	 */
-	public void enterInterface(
-		int declarationStart,
-		int modifiers,
-		char[] name,
-		int nameSourceStart,
-		int nameSourceEnd,
-		char[][] superinterfaces) {
-		enterClass(
-			declarationStart,
-			modifiers,
-			name,
-			nameSourceStart,
-			nameSourceEnd,
-			null,
-			superinterfaces);
+	public void enterMethod(MethodInfo methodInfo) {
+		enterAbstractMethod(methodInfo);
 	}
-	
-	/**
-	 * @see ISourceElementRequestor
-	 */
-	public void enterMethod(
-		int declarationStart,
-		int modifiers,
-		char[] returnType,
-		char[] name,
-		int nameSourceStart,
-		int nameSourceEnd,
-		char[][] parameterTypes,
-		char[][] parameterNames,
-		char[][] exceptionTypes) {
+	private void enterAbstractMethod(MethodInfo methodInfo) {
 		if (typeDepth >= 0) {
-			fMemberName[typeDepth] = new String(name);
+			fMemberName[typeDepth] = new String(methodInfo.name);
 			fMemberNameRange[typeDepth] =
-				new SourceRange(nameSourceStart, nameSourceEnd - nameSourceStart + 1);
-			fMemberDeclarationStart[typeDepth] = declarationStart;
-			fMethodParameterTypes[typeDepth] = parameterTypes;
-			fMethodParameterNames[typeDepth] = parameterNames;
+				new SourceRange(methodInfo.nameSourceStart, methodInfo.nameSourceEnd - methodInfo.nameSourceStart + 1);
+			fMemberDeclarationStart[typeDepth] = methodInfo.declarationStart;
+			fMethodParameterTypes[typeDepth] = methodInfo.parameterTypes;
+			fMethodParameterNames[typeDepth] =methodInfo. parameterNames;
 		}
 	}
 	
 	/**
 	 * @see ISourceElementRequestor
 	 */
-	public void exitClass(int declarationEnd) {
+	public void exitType(int declarationEnd) {
 		if (typeDepth >= 0) {
 			IType currentType = this.types[typeDepth];
 			setSourceRange(
@@ -700,7 +644,7 @@
 	 * @see ISourceElementRequestor
 	 */
 	public void exitConstructor(int declarationEnd) {
-		exitMethod(declarationEnd);
+		exitAbstractMethod(declarationEnd);
 	}
 	
 	/**
@@ -728,14 +672,10 @@
 	/**
 	 * @see ISourceElementRequestor
 	 */
-	public void exitInterface(int declarationEnd) {
-		exitClass(declarationEnd);
+	public void exitMethod(int declarationEnd, int defaultValueStart, int defaultValueEnd) {
+		exitAbstractMethod(declarationEnd);
 	}
-	
-	/**
-	 * @see ISourceElementRequestor
-	 */
-	public void exitMethod(int declarationEnd) {
+	private void exitAbstractMethod(int declarationEnd) {
 		if (typeDepth >= 0) {
 			IType currentType = this.types[typeDepth];
 			SourceRange sourceRange =
@@ -776,11 +716,11 @@
 		} catch (JavaModelException e) {
 			return null;
 		}
-		String simpleSourceFileName = findSourceFileName(type, info);
+		String simpleSourceFileName = declType.sourceFileName(info);
 		if (simpleSourceFileName == null) {
 			return null;
 		}
-		return this.findSource(type, simpleSourceFileName);
+		return findSource(type, simpleSourceFileName);
 	}
 	
 	/**
@@ -795,12 +735,8 @@
 		if (VERBOSE) {
 			time = System.currentTimeMillis();
 		}
-		String name = simpleSourceFileName;
-		IPackageFragment pkgFrag = type.getPackageFragment();
-		if (!pkgFrag.isDefaultPackage()) {
-			String pkg = pkgFrag.getElementName().replace('.', '/');
-			name = pkg + '/' + name;
-		}
+		PackageFragment pkgFrag = (PackageFragment) type.getPackageFragment();
+		String name = org.eclipse.jdt.internal.core.util.Util.concatWith(pkgFrag.names, simpleSourceFileName, '/');
 	
 		char[] source = null;
 		
@@ -837,41 +773,6 @@
 		return source;
 	}
 
-	/*
-	 * Finds the source file name (using the simple .java file name) for the given IBinaryType.
-	 * Returns null if not found.
-	 */
-	public String findSourceFileName(IType type, IBinaryType info) {
-		char[] sourceFileName = info.sourceFileName();
-		if (sourceFileName == null) {
-			/*
-			 * We assume that this type has been compiled from a file with its name
-			 * For example, A.class comes from A.java and p.A.class comes from a file A.java
-			 * in the folder p.
-			 */
-			if (info.isMember()) {
-				IType enclosingType = type.getDeclaringType();
-				if (enclosingType == null) return null; // play it safe
-				while (enclosingType.getDeclaringType() != null) {
-					enclosingType = enclosingType.getDeclaringType();
-				}
-				return enclosingType.getElementName() + SUFFIX_STRING_java;
-			} else if (info.isLocal() || info.isAnonymous()){
-				String typeQualifiedName = type.getTypeQualifiedName();
-				int dollar = typeQualifiedName.indexOf('$');
-				if (dollar == -1) {
-					// malformed inner type: name doesn't contain a dollar
-					return type.getElementName() + SUFFIX_STRING_java;
-				}
-				return typeQualifiedName.substring(0, dollar) + SUFFIX_STRING_java;
-			} else {
-				return type.getElementName() + SUFFIX_STRING_java;
-			}
-		} else {
-			return  new String(sourceFileName);
-		}
-	}
-
 	private char[] getSourceForRootPath(String currentRootPath, String name) {
 		String newFullName;
 		if (!currentRootPath.equals(IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH)) {
@@ -1007,10 +908,21 @@
 	 * as well.
 	 */
 	protected IType getType(String typeName) {
-		if (fType.getElementName().equals(typeName))
-			return fType;
+		if (typeName.length() == 0) {
+			IJavaElement classFile = this.binaryType.getParent();
+			String classFileName = classFile.getElementName();
+			StringBuffer newClassFileName = new StringBuffer();
+			int lastDollar = classFileName.lastIndexOf('$');
+			for (int i = 0; i <= lastDollar; i++)
+				newClassFileName.append(classFileName.charAt(i));
+			newClassFileName.append(Integer.toString(this.anonymousCounter));
+			newClassFileName.append(SuffixConstants.SUFFIX_class);
+			PackageFragment pkg = (PackageFragment) classFile.getParent();
+			return new BinaryType(new ClassFile(pkg, newClassFileName.toString()), typeName);
+		} else if (this.binaryType.getElementName().equals(typeName))
+			return this.binaryType;
 		else
-			return fType.getType(typeName);
+			return this.binaryType.getType(typeName);
 	}
 	
 	/**
@@ -1029,16 +941,36 @@
 				unqualifiedName.append(Signature.C_ARRAY);
 				++count;
 			}
-			if (qualifiedName.charAt(count) == Signature.C_RESOLVED) {
+			char currentChar = qualifiedName.charAt(count);
+			if (currentChar == Signature.C_RESOLVED || currentChar == Signature.C_TYPE_VARIABLE) {
 				unqualifiedName.append(Signature.C_UNRESOLVED);
 				String simpleName = Signature.getSimpleName(qualifiedName.substring(count+1));
-				if(!noDollar) {
-					if(!hasDollar && simpleName.indexOf('$') != -1) {
-						hasDollar = true;
+				int lastDollar = simpleName.lastIndexOf('$');
+				hasDollar |= lastDollar != -1;
+				int start = noDollar ? lastDollar + 1 : 0;
+				boolean sigStart = false;
+				for (int j = start, length = simpleName.length(); j < length; j++) {
+					char current = simpleName.charAt(j);
+					switch (current) {
+						case Signature.C_SUPER:
+						case Signature.C_EXTENDS:
+						case Signature.C_GENERIC_START:
+						case Signature.C_NAME_END:
+							unqualifiedName.append(current);
+							sigStart = true;
+							break;
+						default:
+							if (sigStart) {
+								if (current == Signature.C_TYPE_VARIABLE) {
+									unqualifiedName.append(Signature.C_UNRESOLVED);
+								} else {
+									unqualifiedName.append(current);
+								}
+								sigStart = false;
+							} else {
+								unqualifiedName.append(current);
+							}
 					}
-					unqualifiedName.append(simpleName);
-				} else {
-					unqualifiedName.append(CharOperation.lastSegment(simpleName.toCharArray(), '$'));
 				}
 			} else {
 				unqualifiedName.append(qualifiedName.substring(count, qualifiedName.length()));
@@ -1073,13 +1005,13 @@
 		char[] contents,
 		IJavaElement elementToFind) {
 			
-		fType = (BinaryType) type;
+		this.binaryType = (BinaryType) type;
 		
 		// check whether it is already mapped
 		if (this.fSourceRanges.get(type) != null) return (elementToFind != null) ? this.getNameRange(elementToFind) : null;
 		
-		this.importsTable.remove(fType);
-		this.importsCounterTable.remove(fType);
+		this.importsTable.remove(this.binaryType);
+		this.importsCounterTable.remove(this.binaryType);
 		this.searchedElement = elementToFind;
 		this.types = new IType[1];
 		this.typeDeclarationStarts = new int[1];
@@ -1099,15 +1031,16 @@
 			boolean isAnonymousClass = false;
 			char[] fullName = null;
 			this.anonymousClassName = 0;
+			IBinaryType info = null;
 			try {
-				IBinaryType binType = (IBinaryType) fType.getElementInfo();
-				isAnonymousClass = binType.isAnonymous();
-				fullName = binType.getName();
+				info = (IBinaryType) this.binaryType.getElementInfo();
+				isAnonymousClass = info.isAnonymous();
+				fullName = info.getName();
 			} catch(JavaModelException e) {
 				// ignore
 			}
 			if (isAnonymousClass) {
-				String eltName = fType.getElementName();
+				String eltName = this.binaryType.getParent().getElementName();
 				eltName = eltName.substring(eltName.lastIndexOf('$') + 1, eltName.length());
 				try {
 					this.anonymousClassName = Integer.parseInt(eltName);
@@ -1117,10 +1050,10 @@
 			}
 			boolean doFullParse = hasToRetrieveSourceRangesForLocalClass(fullName);
 			parser = new SourceElementParser(this, factory, new CompilerOptions(this.options), doFullParse);
-			IJavaElement javaElement = this.fType.getCompilationUnit();
-			if (javaElement == null) javaElement = this.fType.getParent();
+			IJavaElement javaElement = this.binaryType.getCompilationUnit();
+			if (javaElement == null) javaElement = this.binaryType.getParent();
 			parser.parseCompilationUnit(
-				new BasicCompilationUnit(contents, null, type.getElementName() + SUFFIX_STRING_java, javaElement),
+				new BasicCompilationUnit(contents, null, this.binaryType.sourceFileName(info), javaElement),
 				doFullParse);
 			if (elementToFind != null) {
 				ISourceRange range = this.getNameRange(elementToFind);
@@ -1132,7 +1065,7 @@
 			if (elementToFind != null) {
 				fSourceRanges = oldSourceRanges;
 			}
-			fType = null;
+			this.binaryType = null;
 			this.searchedElement = null;
 			this.types = null;
 			this.typeDeclarationStarts = null;
@@ -1180,7 +1113,7 @@
 	}
 
 	/**
-	 * Return a char[][] array containing the imports of the attached source for the fType binary
+	 * Return a char[][] array containing the imports of the attached source for the binary type
 	 */
 	public char[][] getImports(BinaryType type) {
 		char[][] imports = (char[][]) this.importsTable.get(type);
@@ -1205,34 +1138,21 @@
 		 * A$B$B$2 : true
 		 * A$C$B$D : false
 		 * A$F$B$D$1$F : true
+		 * A$F$B$D$1F : true
 		 * A$1 : true
 		 * A$B : false
 		 */
 		if (eltName == null) return false;
-		int index = 0;
-		int dollarIndex = CharOperation.indexOf('$', eltName, index);
-		if (dollarIndex != -1) {
-			index = dollarIndex + 1;
-			dollarIndex = CharOperation.indexOf('$', eltName, index);
-			if (dollarIndex == -1) { 
-				dollarIndex = eltName.length;
-			}
-			while (dollarIndex != -1) {
-				for (int i = index; i < dollarIndex; i++) {
-					if (!Character.isDigit(eltName[i])) {
-						index = dollarIndex + 1;
-						i = dollarIndex;
-						if (index > eltName.length) return false;
-						dollarIndex = CharOperation.indexOf('$', eltName, index);
-						if (dollarIndex == -1) { 
-							dollarIndex = eltName.length;
-						}
-						continue;
-					}
-				}
+		int length = eltName.length;
+		int dollarIndex = CharOperation.indexOf('$', eltName, 0);
+		while (dollarIndex != -1) {
+			int nameStart = dollarIndex+1;
+			if (nameStart == length) return false;
+			if (Character.isDigit(eltName[nameStart]))
 				return true;
-			}
+			dollarIndex = CharOperation.indexOf('$', eltName, nameStart);
 		}
 		return false;
 	}	
+	
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethod.java
index 811d3c4..db83ef6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethod.java
@@ -16,6 +16,7 @@
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.jdom.*;
 import org.eclipse.jdt.internal.core.util.Util;
 
@@ -23,7 +24,7 @@
  * @see IMethod
  */
 
-/* package */ class SourceMethod extends Member implements IMethod {
+public class SourceMethod extends NamedMember implements IMethod {
 
 	/**
 	 * The parameter type signatures of the method - stored locally
@@ -32,19 +33,23 @@
 	 */
 	protected String[] fParameterTypes;
 
-	/**
-	 * An empty list of Strings
-	 */
-	protected static final String[] fgEmptyList= new String[] {};
 protected SourceMethod(JavaElement parent, String name, String[] parameterTypes) {
 	super(parent, name);
 	Assert.isTrue(name.indexOf('.') == -1);
 	if (parameterTypes == null) {
-		fParameterTypes= fgEmptyList;
+		fParameterTypes= CharOperation.NO_STRINGS;
 	} else {
 		fParameterTypes= parameterTypes;
 	}
 }
+protected void closing(Object info) throws JavaModelException {
+	super.closing(info);
+	SourceMethodElementInfo elementInfo = (SourceMethodElementInfo) info;
+	ITypeParameter[] typeParameters = elementInfo.typeParameters;
+	for (int i = 0, length = typeParameters.length; i < length; i++) {
+		((TypeParameter) typeParameters[i]).close();
+	}
+}
 public boolean equals(Object o) {
 	if (!(o instanceof SourceMethod)) return false;
 	return super.equals(o) && Util.equalArraysOrNull(fParameterTypes, ((SourceMethod)o).fParameterTypes);
@@ -88,22 +93,21 @@
 	return CompilationUnitStructureRequestor.convertTypeNamesToSigs(exs);
 }
 /**
- * @see JavaElement#getHandleMemento()
+ * @see JavaElement#getHandleMemento(StringBuffer)
  */
-public String getHandleMemento() {
-	StringBuffer buff = new StringBuffer(((JavaElement) getParent()).getHandleMemento());
+protected void getHandleMemento(StringBuffer buff) {
+	((JavaElement) getParent()).getHandleMemento(buff);
 	char delimiter = getHandleMementoDelimiter();
 	buff.append(delimiter);
 	escapeMementoName(buff, getElementName());
 	for (int i = 0; i < fParameterTypes.length; i++) {
 		buff.append(delimiter);
-		buff.append(fParameterTypes[i]);
+		escapeMementoName(buff, fParameterTypes[i]);
 	}
 	if (this.occurrenceCount > 1) {
 		buff.append(JEM_COUNT);
 		buff.append(this.occurrenceCount);
 	}
-	return buff.toString();
 }
 /**
  * @see JavaElement#getHandleMemento()
@@ -123,14 +127,7 @@
 public String[] getParameterNames() throws JavaModelException {
 	SourceMethodElementInfo info = (SourceMethodElementInfo) getElementInfo();
 	char[][] names= info.getArgumentNames();
-	if (names == null || names.length == 0) {
-		return fgEmptyList;
-	}
-	String[] strings= new String[names.length];
-	for (int i= 0; i < names.length; i++) {
-		strings[i]= new String(names[i]);
-	}
-	return strings;
+	return CharOperation.toStrings(names);
 }
 /**
  * @see IMethod
@@ -139,13 +136,40 @@
 	return fParameterTypes;
 }
 
+public ITypeParameter getTypeParameter(String typeParameterName) {
+	return new TypeParameter(this, typeParameterName);
+}
+
+public ITypeParameter[] getTypeParameters() throws JavaModelException {
+	SourceMethodElementInfo info = (SourceMethodElementInfo) getElementInfo();
+	return info.typeParameters;
+}
+
 /**
  * @see IMethod#getTypeParameterSignatures()
  * @since 3.0
+ * @deprecated
  */
 public String[] getTypeParameterSignatures() throws JavaModelException {
-	// TODO (jerome) - missing implementation
-	return new String[0];
+	ITypeParameter[] typeParameters = getTypeParameters();
+	int length = typeParameters.length;
+	String[] typeParameterSignatures = new String[length];
+	for (int i = 0; i < length; i++) {
+		TypeParameter typeParameter = (TypeParameter) typeParameters[i];
+		TypeParameterElementInfo info = (TypeParameterElementInfo) typeParameter.getElementInfo();
+		char[][] bounds = info.bounds;
+		if (bounds == null) {
+			typeParameterSignatures[i] = Signature.createTypeParameterSignature(typeParameter.getElementName(), CharOperation.NO_STRINGS);
+		} else {
+			int boundsLength = bounds.length;
+			char[][] boundSignatures = new char[boundsLength][];
+			for (int j = 0; j < boundsLength; j++) {
+				boundSignatures[j] = Signature.createCharArrayTypeSignature(bounds[j], false);
+			}
+			typeParameterSignatures[i] = new String(Signature.createTypeParameterSignature(typeParameter.getElementName().toCharArray(), boundSignatures));
+		}
+	}
+	return typeParameterSignatures;
 }
 
 /*
@@ -202,7 +226,7 @@
  */
 public boolean isSimilar(IMethod method) {
 	return 
-		this.areSimilarMethods(
+		areSimilarMethods(
 			this.getElementName(), this.getParameterTypes(),
 			method.getElementName(), method.getParameterTypes(),
 			null);
@@ -267,37 +291,52 @@
  * @private Debugging purposes
  */
 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
-	buffer.append(this.tabString(tab));
+	buffer.append(tabString(tab));
 	if (info == null) {
 		toStringName(buffer);
 		buffer.append(" (not open)"); //$NON-NLS-1$
 	} else if (info == NO_INFO) {
 		toStringName(buffer);
 	} else {
-		try {
-			if (Flags.isStatic(this.getFlags())) {
-				buffer.append("static "); //$NON-NLS-1$
-			}
-			if (!this.isConstructor()) {
-				buffer.append(Signature.toString(this.getReturnType()));
-				buffer.append(' ');
-			}
-			toStringName(buffer);
-		} catch (JavaModelException e) {
-			buffer.append("<JavaModelException in toString of " + getElementName()); //$NON-NLS-1$
+		SourceMethodElementInfo methodInfo = (SourceMethodElementInfo) info;
+		int flags = methodInfo.getModifiers();
+		if (Flags.isStatic(flags)) {
+			buffer.append("static "); //$NON-NLS-1$
 		}
+		if (!methodInfo.isConstructor()) {
+			buffer.append(methodInfo.getReturnTypeName());
+			buffer.append(' ');
+		}
+		toStringName(buffer, flags);
 	}
 }
 protected void toStringName(StringBuffer buffer) {
+	toStringName(buffer, 0);
+}
+protected void toStringName(StringBuffer buffer, int flags) {
 	buffer.append(getElementName());
 	buffer.append('(');
-	String[] parameters = this.getParameterTypes();
+	String[] parameters = getParameterTypes();
 	int length;
 	if (parameters != null && (length = parameters.length) > 0) {
+		boolean isVarargs = Flags.isVarargs(flags);
 		for (int i = 0; i < length; i++) {
-			buffer.append(Signature.toString(parameters[i]));
-			if (i < length - 1) {
-				buffer.append(", "); //$NON-NLS-1$
+			try {
+				if (i < length - 1) {
+					buffer.append(Signature.toString(parameters[i]));
+					buffer.append(", "); //$NON-NLS-1$
+				} else if (isVarargs) {
+					// remove array from signature
+					String parameter = parameters[i].substring(1);
+					buffer.append(Signature.toString(parameter));
+					buffer.append(" ..."); //$NON-NLS-1$
+				} else {
+					buffer.append(Signature.toString(parameters[i]));
+				}
+			} catch (IllegalArgumentException e) {
+				// parameter signature is malformed
+				buffer.append("*** invalid signature: "); //$NON-NLS-1$
+				buffer.append(parameters[i]);
 			}
 		}
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodElementInfo.java
index f2fdf3f..e35c41f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodElementInfo.java
@@ -10,13 +10,18 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import org.eclipse.jdt.core.*;
+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.env.ISourceMethod;
 
 /** 
  * Element info for IMethod elements. 
  */
-public class SourceMethodElementInfo extends MemberElementInfo implements ISourceMethod {
+public abstract class SourceMethodElementInfo extends MemberElementInfo implements ISourceMethod {
+	
+	protected char[] selector;
 
 	/**
 	 * For a source method (that is, a method contained in a compilation unit)
@@ -38,12 +43,6 @@
 	protected char[][] argumentTypeNames;
 
 	/**
-	 * Return type name for this method. The return type of
-	 * constructors is equivalent to void.
-	 */
-	protected char[] returnType;
-
-	/**
 	 * A collection of type names of the exceptions this
 	 * method throws, or an empty collection if this method
 	 * does not declare to throw any exceptions. A name is a simple
@@ -52,10 +51,11 @@
 	 */
 	protected char[][] exceptionTypes;
 
-	/**
-	 * Constructor flag.
+	/*
+	 * The type parameters of this source type. Empty if none.
 	 */
-	protected boolean isConstructor= false;
+	protected ITypeParameter[] typeParameters = TypeParameter.NO_TYPE_PARAMETERS;
+	
 public char[][] getArgumentNames() {
 	return this.argumentNames;
 }
@@ -65,11 +65,10 @@
 public char[][] getExceptionTypeNames() {
 	return this.exceptionTypes;
 }
-public char[] getReturnTypeName() {
-	return this.returnType;
-}
+public abstract char[] getReturnTypeName();
+
 public char[] getSelector() {
-	return this.name;
+	return this.selector;
 }
 protected String getSignature() {
 
@@ -77,24 +76,40 @@
 	for (int i = 0; i < this.argumentTypeNames.length; ++i) {
 		paramSignatures[i] = Signature.createTypeSignature(this.argumentTypeNames[i], false);
 	}
-	return Signature.createMethodSignature(paramSignatures, Signature.createTypeSignature(this.returnType, false));
+	return Signature.createMethodSignature(paramSignatures, Signature.createTypeSignature(getReturnTypeName(), false));
 }
-public boolean isConstructor() {
-	return this.isConstructor;
+public char[][][] getTypeParameterBounds() {
+	int length = this.typeParameters.length;
+	char[][][] typeParameterBounds = new char[length][][];
+	for (int i = 0; i < length; i++) {
+		try {
+			TypeParameterElementInfo info = (TypeParameterElementInfo) ((JavaElement)this.typeParameters[i]).getElementInfo();
+			typeParameterBounds[i] = info.bounds;
+		} catch (JavaModelException e) {
+			// type parameter does not exist: ignore
+		}
+	}
+	return typeParameterBounds;
 }
+public char[][] getTypeParameterNames() {
+	int length = this.typeParameters.length;
+	if (length == 0) return CharOperation.NO_CHAR_CHAR;
+	char[][] typeParameterNames = new char[length][];
+	for (int i = 0; i < length; i++) {
+		typeParameterNames[i] = this.typeParameters[i].getElementName().toCharArray();
+	}
+	return typeParameterNames;
+}
+public abstract boolean isConstructor();
+public abstract boolean isAnnotationMethod();
 protected void setArgumentNames(char[][] names) {
 	this.argumentNames = names;
 }
 protected void setArgumentTypeNames(char[][] types) {
 	this.argumentTypeNames = types;
 }
-protected void setConstructor(boolean isConstructor) {
-	this.isConstructor = isConstructor;
-}
 protected void setExceptionTypeNames(char[][] types) {
 	this.exceptionTypes = types;
 }
-protected void setReturnType(char[] type) {
-	this.returnType = type;
-}
+protected abstract void setReturnType(char[] type);
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodInfo.java
new file mode 100644
index 0000000..484484a
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodInfo.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+/*
+ * Element info for method from source.
+ */
+public class SourceMethodInfo extends SourceMethodElementInfo {
+
+	/*
+	 * Return type name for this method. The return type of
+	 * constructors is equivalent to void.
+	 */
+	protected char[] returnType;
+	
+	public boolean isAnnotationMethod() {
+		return false;
+	}
+	
+	public boolean isConstructor() {
+		return false;
+	}
+
+	public char[] getReturnTypeName() {
+		return this.returnType;
+	}
+
+	protected void setReturnType(char[] type) {
+		this.returnType = type;
+	}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElement.java
index 64e6a7b..eec3db3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElement.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElement.java
@@ -29,9 +29,19 @@
 /**
  * Abstract class for Java elements which implement ISourceReference.
  */
-/* package */ abstract class SourceRefElement extends JavaElement implements ISourceReference {
-protected SourceRefElement(JavaElement parent, String name) {
-	super(parent, name);
+public abstract class SourceRefElement extends JavaElement implements ISourceReference {
+	/*
+	 * A count to uniquely identify this element in the case
+	 * that a duplicate named element exists. For example, if
+	 * there are two fields in a compilation unit with the
+	 * same name, the occurrence count is used to distinguish
+	 * them.  The occurrence count starts at 1 (thus the first 
+	 * occurrence is occurrence 1, not occurrence 0).
+	 */
+	public int occurrenceCount = 1;
+
+protected SourceRefElement(JavaElement parent) {
+	super(parent);
 }
 /**
  * This element is being closed.  Do any necessary cleanup.
@@ -71,6 +81,11 @@
 	IJavaElement[] elements = new IJavaElement[] {this};
 	getJavaModel().delete(elements, force, monitor);
 }
+public boolean equals(Object o) {
+	if (!(o instanceof SourceRefElement)) return false;
+	return this.occurrenceCount == ((SourceRefElement)o).occurrenceCount &&
+			super.equals(o);
+}
 /*
  * @see JavaElement#generateInfos
  */
@@ -109,6 +124,24 @@
 	}
 	return this;
 }
+protected void getHandleMemento(StringBuffer buff) {
+	super.getHandleMemento(buff);
+	if (this.occurrenceCount > 1) {
+		buff.append(JEM_COUNT);
+		buff.append(this.occurrenceCount);
+	}
+}
+/*
+ * Update the occurence count of the receiver and creates a Java element handle from the given memento.
+ * The given working copy owner is used only for compilation unit handles.
+ */
+public IJavaElement getHandleUpdatingCountFromMemento(MementoTokenizer memento, WorkingCopyOwner owner) {
+	if (!memento.hasMoreTokens()) return this;
+	this.occurrenceCount = Integer.parseInt(memento.nextToken());
+	if (!memento.hasMoreTokens()) return this;
+	String token = memento.nextToken();
+	return getHandleFromMemento(token, memento, owner);
+}
 /**
  * Return the first instance of IOpenable in the hierarchy of this
  * type (going up the hierarchy from this type);
@@ -177,6 +210,13 @@
 	return getChildren().length > 0;
 }
 /**
+ * @see IJavaElement
+ */
+public boolean isStructureKnown() throws JavaModelException {
+	// structure is always known inside an openable
+	return true;
+}
+/**
  * @see ISourceManipulation
  */
 public void move(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor) throws JavaModelException {
@@ -207,4 +247,11 @@
 	String[] renamings= new String[] {newName};
 	getJavaModel().rename(elements, dests, renamings, force, monitor);
 }
+protected void toStringName(StringBuffer buffer) {
+	super.toStringName(buffer);
+	if (this.occurrenceCount > 1) {
+		buffer.append("#"); //$NON-NLS-1$
+		buffer.append(this.occurrenceCount);
+	}
+}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElementInfo.java
index 29c2b6d..b4f7bc1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElementInfo.java
@@ -17,9 +17,6 @@
  */
 /* package */ class SourceRefElementInfo extends JavaElementInfo {
 	protected int fSourceRangeStart, fSourceRangeEnd;
-protected SourceRefElementInfo() {
-	setIsStructureKnown(true);
-}
 /**
  * @see org.eclipse.jdt.internal.compiler.env.ISourceType#getDeclarationSourceEnd()
  * @see org.eclipse.jdt.internal.compiler.env.ISourceMethod#getDeclarationSourceEnd()
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
index b5d443f..13e757a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
@@ -20,9 +20,9 @@
 import org.eclipse.jdt.core.jdom.*;
 import org.eclipse.jdt.core.search.SearchEngine;
 import org.eclipse.jdt.internal.codeassist.CompletionEngine;
-import org.eclipse.jdt.internal.codeassist.ISearchableNameEnvironment;
 import org.eclipse.jdt.internal.codeassist.ISelectionRequestor;
 import org.eclipse.jdt.internal.codeassist.SelectionEngine;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.env.ISourceType;
 import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
 import org.eclipse.jdt.internal.core.util.MementoTokenizer;
@@ -36,35 +36,56 @@
  * @see IType
  */
 
-public class SourceType extends Member implements IType {
-	/**
-	 * An empty list of Strings
-	 */
-	protected static final String[] fgEmptyList= new String[] {};
+public class SourceType extends NamedMember implements IType {
+	
 protected SourceType(JavaElement parent, String name) {
 	super(parent, name);
 	Assert.isTrue(name.indexOf('.') == -1, Util.bind("sourcetype.invalidName", name)); //$NON-NLS-1$
 }
+protected void closing(Object info) throws JavaModelException {
+	super.closing(info);
+	SourceTypeElementInfo elementInfo = (SourceTypeElementInfo) info;
+	ITypeParameter[] typeParameters = elementInfo.typeParameters;
+	for (int i = 0, length = typeParameters.length; i < length; i++) {
+		((TypeParameter) typeParameters[i]).close();
+	}
+}
 /**
  * @see IType
+ * @deprecated
  */
 public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,ICompletionRequestor requestor) throws JavaModelException {
 	codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, requestor, DefaultWorkingCopyOwner.PRIMARY);
 }
 /**
  * @see IType
+ * @deprecated
  */
 public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,ICompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
 	if (requestor == null) {
 		throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$
 	}
+	codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, new org.eclipse.jdt.internal.codeassist.CompletionRequestorWrapper(requestor), owner);
+
+}
+/**
+ * @see IType
+ */
+public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,CompletionRequestor requestor) throws JavaModelException {
+	codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, requestor, DefaultWorkingCopyOwner.PRIMARY);
+}
+/**
+ * @see IType
+ */
+public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,CompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
+	if (requestor == null) {
+		throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$
+	}
 	
 	JavaProject project = (JavaProject) getJavaProject();
-	SearchableEnvironment environment = (SearchableEnvironment) project.newSearchableNameEnvironment(owner);
-	CompletionRequestorWrapper requestorWrapper = new CompletionRequestorWrapper(requestor, environment.nameLookup);
-	CompletionEngine engine = new CompletionEngine(environment, requestorWrapper, project.getOptions(true), project);
-	requestorWrapper.completionEngine = engine;
-	
+	SearchableEnvironment environment = project.newSearchableNameEnvironment(owner);
+	CompletionEngine engine = new CompletionEngine(environment, requestor, project.getOptions(true), project);
+
 	String source = getCompilationUnit().getSource();
 	if (source != null && insertion > -1 && insertion < source.length()) {
 		
@@ -83,6 +104,8 @@
 	} else {
 		engine.complete(this, snippet, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic);
 	}
+	if (NameLookup.VERBOSE)
+		System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
 }
 /**
  * @see IType
@@ -145,7 +168,7 @@
  */
 public IMethod[] findMethods(IMethod method) {
 	try {
-		return this.findMethods(method, this.getMethods());
+		return findMethods(method, getMethods());
 	} catch (JavaModelException e) {
 		// if type doesn't exist, no matching method can exist
 		return null;
@@ -199,11 +222,18 @@
  * @see IType#getFullyQualifiedName(char)
  */
 public String getFullyQualifiedName(char enclosingTypeSeparator) {
-	String packageName = getPackageFragment().getElementName();
-	if (packageName.equals(IPackageFragment.DEFAULT_PACKAGE_NAME)) {
-		return getTypeQualifiedName(enclosingTypeSeparator);
+	try {
+		return getFullyQualifiedName(enclosingTypeSeparator, false/*don't show parameters*/);
+	} catch (JavaModelException e) {
+		// exception thrown only when showing parameters
+		return null;
 	}
-	return packageName + '.' + getTypeQualifiedName(enclosingTypeSeparator);
+}
+/*
+ * @see IType#getFullyQualifiedParameterizedName()
+ */
+public String getFullyQualifiedParameterizedName() throws JavaModelException {
+	return getFullyQualifiedName('.', true/*show parameters*/);
 }
 /*
  * @see JavaElement
@@ -213,26 +243,32 @@
 		case JEM_COUNT:
 			return getHandleUpdatingCountFromMemento(memento, workingCopyOwner);
 		case JEM_FIELD:
+			if (!memento.hasMoreTokens()) return this;
 			String fieldName = memento.nextToken();
 			JavaElement field = (JavaElement)getField(fieldName);
 			return field.getHandleFromMemento(memento, workingCopyOwner);
 		case JEM_INITIALIZER:
+			if (!memento.hasMoreTokens()) return this;
 			String count = memento.nextToken();
 			JavaElement initializer = (JavaElement)getInitializer(Integer.parseInt(count));
 			return initializer.getHandleFromMemento(memento, workingCopyOwner);
 		case JEM_METHOD:
+			if (!memento.hasMoreTokens()) return this;
 			String selector = memento.nextToken();
 			ArrayList params = new ArrayList();
 			nextParam: while (memento.hasMoreTokens()) {
 				token = memento.nextToken();
 				switch (token.charAt(0)) {
 					case JEM_TYPE:
+					case JEM_TYPE_PARAMETER:
 						break nextParam;
 					case JEM_METHOD:
+						if (!memento.hasMoreTokens()) return this;
 						String param = memento.nextToken();
 						StringBuffer buffer = new StringBuffer();
-						while (Signature.C_ARRAY == param.charAt(0)) {
+						while (param.length() == 1 && Signature.C_ARRAY == param.charAt(0)) { // backward compatible with 3.0 mementos
 							buffer.append(Signature.C_ARRAY);
+							if (!memento.hasMoreTokens()) return this;
 							param = memento.nextToken();
 						}
 						params.add(buffer.toString() + param);
@@ -247,6 +283,7 @@
 			if (token != null) {
 				switch (token.charAt(0)) {
 					case JEM_TYPE:
+					case JEM_TYPE_PARAMETER:
 					case JEM_LOCALVARIABLE:
 						return method.getHandleFromMemento(token, memento, workingCopyOwner);
 					default:
@@ -276,6 +313,12 @@
 			} else {
 				return type.getHandleFromMemento(token, memento, workingCopyOwner);
 			}
+		case JEM_TYPE_PARAMETER:
+			if (!memento.hasMoreTokens()) return this;
+			String typeParameterName = memento.nextToken();
+			JavaElement typeParameter = new TypeParameter(this, typeParameterName);
+			return typeParameter.getHandleFromMemento(memento, workingCopyOwner);
+			
 	}
 	return null;
 }
@@ -377,14 +420,7 @@
 public String[] getSuperInterfaceNames() throws JavaModelException {
 	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
 	char[][] names= info.getInterfaceNames();
-	if (names == null) {
-		return fgEmptyList;
-	}
-	String[] strings= new String[names.length];
-	for (int i= 0; i < names.length; i++) {
-		strings[i]= new String(names[i]);
-	}
-	return strings;
+	return CharOperation.toStrings(names);
 }
 
 /**
@@ -394,23 +430,46 @@
 public String[] getSuperInterfaceTypeSignatures() throws JavaModelException {
 	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
 	char[][] names= info.getInterfaceNames();
-	if (names == null) {
-		return fgEmptyList;
-	}
-	String[] strings= new String[names.length];
-	for (int i= 0; i < names.length; i++) {
-		strings[i]= new String(Signature.createTypeSignature(names[i], false));
-	}
-	return strings;
+	return CharOperation.toStrings(names);
+}
+
+public ITypeParameter[] getTypeParameters() throws JavaModelException {
+	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
+	return info.typeParameters;
+}
+
+// Get type parameter names
+// TODO (frederic) see if this method needs to be added to API
+public char[][] getTypeParameterNames() throws JavaModelException {
+	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
+	return info.getTypeParameterNames();
 }
 
 /**
  * @see IType#getTypeParameterSignatures()
  * @since 3.0
+ * @deprecated
  */
 public String[] getTypeParameterSignatures() throws JavaModelException {
-	// TODO (jerome) - missing implementation
-	return new String[0];
+	ITypeParameter[] typeParameters = getTypeParameters();
+	int length = typeParameters.length;
+	String[] typeParameterSignatures = new String[length];
+	for (int i = 0; i < length; i++) {
+		TypeParameter typeParameter = (TypeParameter) typeParameters[i];
+		TypeParameterElementInfo info = (TypeParameterElementInfo) typeParameter.getElementInfo();
+		char[][] bounds = info.bounds;
+		if (bounds == null) {
+			typeParameterSignatures[i] = Signature.createTypeParameterSignature(typeParameter.getElementName(), CharOperation.NO_STRINGS);
+		} else {
+			int boundsLength = bounds.length;
+			char[][] boundSignatures = new char[boundsLength][];
+			for (int j = 0; j < boundsLength; j++) {
+				boundSignatures[j] = Signature.createCharArrayTypeSignature(bounds[j], false);
+			}
+			typeParameterSignatures[i] = new String(Signature.createTypeParameterSignature(typeParameter.getElementName().toCharArray(), boundSignatures));
+		}
+	}
+	return typeParameterSignatures;
 }
 
 /**
@@ -419,6 +478,9 @@
 public IType getType(String typeName) {
 	return new SourceType(this, typeName);
 }
+public ITypeParameter getTypeParameter(String typeParameterName) {
+	return new TypeParameter(this, typeParameterName);
+}
 /**
  * @see IType#getTypeQualifiedName()
  */
@@ -429,21 +491,12 @@
  * @see IType#getTypeQualifiedName(char)
  */
 public String getTypeQualifiedName(char enclosingTypeSeparator) {
-	switch (this.parent.getElementType()) {
-		case IJavaElement.COMPILATION_UNIT:
-			return this.name;
-		case IJavaElement.TYPE:
-			String simpleName = this.name.length() == 0 ? Integer.toString(this.occurrenceCount) : this.name;
-			return ((IType) this.parent).getTypeQualifiedName(enclosingTypeSeparator) + enclosingTypeSeparator + simpleName;
-		case IJavaElement.FIELD:
-		case IJavaElement.INITIALIZER:
-		case IJavaElement.METHOD:
-			simpleName = this.name.length() == 0 ? Integer.toString(this.occurrenceCount) : this.name;
-			return 
-				((IMember) this.parent).getDeclaringType().getTypeQualifiedName(enclosingTypeSeparator) 
-				+ enclosingTypeSeparator + simpleName;
+	try {
+		return getTypeQualifiedName(enclosingTypeSeparator, false/*don't show parameters*/);
+	} catch (JavaModelException e) {
+		// exception thrown only when showing parameters
+		return null;
 	}
-	return null;
 }
 
 /**
@@ -475,8 +528,8 @@
  * @since 3.0
  */
 public boolean isEnum() throws JavaModelException {
-	// TODO (jerome) - missing implementation - should only return true for enum classes
-	return false;
+	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
+	return info.getKind() == IGenericType.ENUM_DECL;
 }
 
 /**
@@ -484,8 +537,7 @@
  */
 public boolean isInterface() throws JavaModelException {
 	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
-	// TODO (jerome) - isInterface should not return true for annotation types
-	return info.isInterface();
+	return info.getKind() == IGenericType.INTERFACE_DECL;
 }
 
 /**
@@ -493,8 +545,8 @@
  * @since 3.0
  */
 public boolean isAnnotation() throws JavaModelException {
-	// TODO (jerome) - missing implementation - should only return true for annotation types
-	return false;
+	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
+	return info.getKind() == IGenericType.ANNOTATION_TYPE_DECL;
 }
 
 /**
@@ -704,7 +756,7 @@
 public String[][] resolveType(String typeName, WorkingCopyOwner owner) throws JavaModelException {
 	ISourceType info = (ISourceType) getElementInfo();
 	JavaProject project = (JavaProject) getJavaProject();
-	ISearchableNameEnvironment environment = project.newSearchableNameEnvironment(owner);
+	SearchableEnvironment environment = project.newSearchableNameEnvironment(owner);
 
 	class TypeResolveRequestor implements ISelectionRequestor {
 		String[][] answers = null;
@@ -718,26 +770,37 @@
 				this.answers[length] = answer;
 			}
 		}
-		public void acceptClass(char[] packageName, char[] className, boolean needQualification, boolean isDeclaration, int start, int end) {
+		public void acceptAnnotation(char[] packageName, char[] annotationName, boolean isDeclaration, char[] genericTypeSignature, int start, int end) {
+			acceptType(new String[]  { new String(packageName), new String(annotationName) });
+		}
+		public void acceptClass(char[] packageName, char[] className, boolean isDeclaration, char[] genericTypeSignature, int start, int end) {
 			acceptType(new String[]  { new String(packageName), new String(className) });
 		}
-		
-		public void acceptInterface(char[] packageName, char[] interfaceName, boolean needQualification, boolean isDeclaration, int start, int end) {
+		public void acceptEnum(char[] packageName, char[] enumName, boolean isDeclaration, char[] genericTypeSignature, int start, int end) {
+			acceptType(new String[]  { new String(packageName), new String(enumName) });
+		}
+		public void acceptInterface(char[] packageName, char[] interfaceName, boolean isDeclaration, char[] genericTypeSignature, int start, int end) {
 			acceptType(new String[]  { new String(packageName), new String(interfaceName) });
 		}
 
 		public void acceptError(IProblem error) {
 			// ignore
 		}
-		public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] fieldName, boolean isDeclaration, int start, int end) {
+		public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] fieldName, boolean isDeclaration, char[] uniqueKey, int start, int end) {
 			// ignore
 		}
-		public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, boolean isConstructor, boolean isDeclaration, int start, int end) {
+		public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, String enclosingDeclaringTypeSignature, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, String[] parameterSignatures, boolean isConstructor, boolean isDeclaration, char[] uniqueKey, int start, int end) {
 			// ignore
 		}
 		public void acceptPackage(char[] packageName){
 			// ignore
 		}
+		public void acceptTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] typeParameterName, boolean isDeclaration, int start, int end) {
+			// ignore
+		}
+		public void acceptMethodTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, int selectorStart, int selcetorEnd, char[] typeParameterName, boolean isDeclaration, int start, int end) {
+			// ignore
+		}
 
 	}
 	TypeResolveRequestor requestor = new TypeResolveRequestor();
@@ -752,6 +815,8 @@
 	}
 		
 	engine.selectType(info, typeName.toCharArray(), topLevelInfos, false);
+	if (NameLookup.VERBOSE)
+		System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
 	return requestor.answers;
 }
 /**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java
index 428f07f..6af4f13 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java
@@ -10,11 +10,14 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IImportDeclaration;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.env.IConstants;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.env.ISourceField;
 import org.eclipse.jdt.internal.compiler.env.ISourceImport;
 import org.eclipse.jdt.internal.compiler.env.ISourceMethod;
@@ -27,9 +30,9 @@
 
 	protected static final ISourceImport[] NO_IMPORTS = new ISourceImport[0];
 	protected static final InitializerElementInfo[] NO_INITIALIZERS = new InitializerElementInfo[0];
-	protected static final ISourceField[] NO_FIELDS = new ISourceField[0];
-	protected static final ISourceMethod[] NO_METHODS = new ISourceMethod[0];
-	protected static final ISourceType[] NO_TYPES = new ISourceType[0];
+	protected static final SourceField[] NO_FIELDS = new SourceField[0];
+	protected static final SourceMethod[] NO_METHODS = new SourceMethod[0];
+	protected static final SourceType[] NO_TYPES = new SourceType[0];
 	/**
 	 * The name of the superclass for this type. This name
 	 * is fully qualified for binary types and is NOT
@@ -65,6 +68,11 @@
 	 * from info to handle.
 	 */
 	protected IType handle = null;
+	
+	/*
+	 * The type parameters of this source type. Empty if none.
+	 */
+	protected ITypeParameter[] typeParameters = TypeParameter.NO_TYPE_PARAMETERS;
 
 /**
  * Returns the ISourceType that is the enclosing type for this
@@ -86,27 +94,36 @@
  * @see ISourceType
  */
 public ISourceField[] getFields() {
+	SourceField[] fieldHandles = getFieldHandles();
+	int length = fieldHandles.length;
+	ISourceField[] fields = new ISourceField[length];
+	for (int i = 0; i < length; i++) {
+		try {
+			ISourceField field = (ISourceField) fieldHandles[i].getElementInfo();
+			fields[i] = field;
+		} catch (JavaModelException e) {
+			// ignore
+		}
+	}
+	return fields;
+}
+public SourceField[] getFieldHandles() {
 	int length = this.children.length;
 	if (length == 0) return NO_FIELDS;
-	ISourceField[] fields = new ISourceField[length];
+	SourceField[] fields = new SourceField[length];
 	int fieldIndex = 0;
 	for (int i = 0; i < length; i++) {
 		IJavaElement child = this.children[i];
-		if (child instanceof SourceField) {
-			try {
-				ISourceField field = (ISourceField)((SourceField)child).getElementInfo();
-				fields[fieldIndex++] = field;
-			} catch (JavaModelException e) {
-				// ignore
-			}
-		}
+		if (child instanceof SourceField)
+			fields[fieldIndex++] = (SourceField) child;
 	}
 	if (fieldIndex == 0) return NO_FIELDS;
-	System.arraycopy(fields, 0, fields = new ISourceField[fieldIndex], 0, fieldIndex);
+	if (fieldIndex < length)
+		System.arraycopy(fields, 0, fields = new SourceField[fieldIndex], 0, fieldIndex);
 	return fields;
 }
 /**
- * @see ISourceType
+ * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
  */
 public char[] getFileName() {
 	return this.sourceFileName;
@@ -174,51 +191,88 @@
 	return this.superInterfaceNames;
 }
 /**
+ * @see org.eclipse.jdt.internal.compiler.env.IGenericType#getKind()
+ */
+public int getKind() {
+	if ((this.flags & IConstants.AccInterface) != 0) {
+		if ((this.flags & IConstants.AccAnnotation) != 0)
+			return IGenericType.ANNOTATION_TYPE_DECL;
+		return IGenericType.INTERFACE_DECL;
+	}
+	if ((this.flags & IConstants.AccEnum) != 0) return IGenericType.ENUM_DECL;
+	return IGenericType.CLASS_DECL;
+}
+/**
  * @see ISourceType
  */
 public ISourceType[] getMemberTypes() {
+	SourceType[] memberTypeHandles = getMemberTypeHandles();
+	int length = memberTypeHandles.length;
+	ISourceType[] memberTypes = new ISourceType[length];
+	for (int i = 0; i < length; i++) {
+		try {
+			ISourceType type = (ISourceType) memberTypeHandles[i].getElementInfo();
+			memberTypes[i] = type;
+		} catch (JavaModelException e) {
+			// ignore
+		}
+	}
+	return memberTypes;
+}
+public SourceType[] getMemberTypeHandles() {
 	int length = this.children.length;
 	if (length == 0) return NO_TYPES;
-	ISourceType[] memberTypes = new ISourceType[length];
+	SourceType[] memberTypes = new SourceType[length];
 	int typeIndex = 0;
 	for (int i = 0; i < length; i++) {
 		IJavaElement child = this.children[i];
-		if (child instanceof SourceType) {
-			try {
-				ISourceType type = (ISourceType)((SourceType)child).getElementInfo();
-				memberTypes[typeIndex++] = type;
-			} catch (JavaModelException e) {
-				// ignore
-			}
-		}
+		if (child instanceof SourceType)
+			memberTypes[typeIndex++] = (SourceType)child;
 	}
 	if (typeIndex == 0) return NO_TYPES;
-	System.arraycopy(memberTypes, 0, memberTypes = new ISourceType[typeIndex], 0, typeIndex);
+	if (typeIndex < length)
+		System.arraycopy(memberTypes, 0, memberTypes = new SourceType[typeIndex], 0, typeIndex);
 	return memberTypes;
 }
 /**
  * @see ISourceType
  */
 public ISourceMethod[] getMethods() {
-	int length = this.children.length;
-	if (length == 0) return NO_METHODS;
+	SourceMethod[] methodHandles = getMethodHandles();
+	int length = methodHandles.length;
 	ISourceMethod[] methods = new ISourceMethod[length];
 	int methodIndex = 0;
 	for (int i = 0; i < length; i++) {
-		IJavaElement child = this.children[i];
-		if (child instanceof SourceMethod) {
-			try {
-				ISourceMethod method = (ISourceMethod)((SourceMethod)child).getElementInfo();
-				methods[methodIndex++] = method;
-			} catch (JavaModelException e) {
-				// ignore
-			}
+		try {
+			ISourceMethod method = (ISourceMethod) methodHandles[i].getElementInfo();
+			methods[methodIndex++] = method;
+		} catch (JavaModelException e) {
+			// ignore
 		}
 	}
-	if (methodIndex == 0) return NO_METHODS;
-	System.arraycopy(methods, 0, methods = new ISourceMethod[methodIndex], 0, methodIndex);
 	return methods;
 }
+public SourceMethod[] getMethodHandles() {
+	int length = this.children.length;
+	if (length == 0) return NO_METHODS;
+	SourceMethod[] methods = new SourceMethod[length];
+	int methodIndex = 0;
+	for (int i = 0; i < length; i++) {
+		IJavaElement child = this.children[i];
+		if (child instanceof SourceMethod)
+			methods[methodIndex++] = (SourceMethod) child;
+	}
+	if (methodIndex == 0) return NO_METHODS;
+	if (methodIndex < length)
+		System.arraycopy(methods, 0, methods = new SourceMethod[methodIndex], 0, methodIndex);
+	return methods;
+}
+/**
+ * @see org.eclipse.jdt.internal.compiler.env.ISourceType#getName()
+ */
+public char[] getName() {
+	return this.handle.getElementName().toCharArray();
+}
 /**
  * @see ISourceType
  */
@@ -237,6 +291,28 @@
 	} 
 	return this.superclassName;
 }
+public char[][][] getTypeParameterBounds() {
+	int length = this.typeParameters.length;
+	char[][][] typeParameterBounds = new char[length][][];
+	for (int i = 0; i < length; i++) {
+		try {
+			TypeParameterElementInfo info = (TypeParameterElementInfo) ((JavaElement)this.typeParameters[i]).getElementInfo();
+			typeParameterBounds[i] = info.bounds;
+		} catch (JavaModelException e) {
+			// type parameter does not exist: ignore
+		}
+	}
+	return typeParameterBounds;
+}
+public char[][] getTypeParameterNames() {
+	int length = this.typeParameters.length;
+	if (length == 0) return CharOperation.NO_CHAR_CHAR;
+	char[][] typeParameterNames = new char[length][];
+	for (int i = 0; i < length; i++) {
+		typeParameterNames[i] = this.typeParameters[i].getElementName().toCharArray();
+	}
+	return typeParameterNames;
+}
 /**
  * @see ISourceType
  */
@@ -244,18 +320,6 @@
 	return false;
 }
 /**
- * @see ISourceType
- */
-public boolean isClass() {
-	return (this.flags & IConstants.AccInterface) == 0;
-}
-/**
- * @see ISourceType
- */
-public boolean isInterface() {
-	return (this.flags & IConstants.AccInterface) != 0;
-}
-/**
  * Sets the handle for this type info
  */
 protected void setHandle(IType handle) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeParameter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeParameter.java
new file mode 100644
index 0000000..8b3fa07
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeParameter.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.ITypeParameter;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.CharOperation;
+
+public class TypeParameter extends SourceRefElement implements ITypeParameter {
+
+	static final ITypeParameter[] NO_TYPE_PARAMETERS = new ITypeParameter[0];
+	
+	protected String name;
+	
+	public TypeParameter(JavaElement parent, String name) {
+		super(parent);
+		this.name = name;
+	}
+
+	public boolean equals(Object o) {
+		if (!(o instanceof TypeParameter)) return false;
+		return super.equals(o);
+	}
+
+	public String[] getBounds() throws JavaModelException {
+		TypeParameterElementInfo info = (TypeParameterElementInfo) getElementInfo();
+		return CharOperation.toStrings(info.bounds);
+	}
+
+	public IMember getDeclaringMember() {
+			return (IMember) getParent();
+	}
+
+	public String getElementName() {
+		return this.name;
+	}
+
+	public int getElementType() {
+		return TYPE_PARAMETER;
+	}
+
+	protected char getHandleMementoDelimiter() {
+		return JavaElement.JEM_TYPE_PARAMETER;
+	}
+	
+	public ISourceRange getNameRange() throws JavaModelException {
+		TypeParameterElementInfo info = (TypeParameterElementInfo) getElementInfo();
+		return new SourceRange(info.nameStart, info.nameEnd - info.nameStart + 1);
+	}
+
+	protected void toStringName(StringBuffer buffer) {
+		buffer.append('<');
+		buffer.append(getElementName());
+		buffer.append('>');
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeParameterElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeParameterElementInfo.java
new file mode 100644
index 0000000..840c667
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeParameterElementInfo.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+public class TypeParameterElementInfo extends SourceRefElementInfo {
+	
+	/*
+	 * The start position of this type parameter's name in the its
+	 * openable's buffer.
+	 */
+	public int nameStart= -1;
+
+	/*
+	 * The last position of this type parameter name in the its
+	 * openable's buffer.
+	 */
+	public int nameEnd= -1;
+
+	/*
+	 * The bounds names of this type parameter.
+	 */
+	public char[][] bounds;
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryManager.java
index 6c22a3a..abe2f22 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryManager.java
@@ -22,16 +22,15 @@
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.Preferences;
 import org.eclipse.core.runtime.SubProgressMonitor;
-import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
-import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
 import org.eclipse.jdt.core.IClasspathContainer;
 import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.internal.core.util.Util;
+import org.osgi.service.prefs.BackingStoreException;
 
 /**
  *
@@ -43,10 +42,10 @@
 
 	private static Map userLibraries;
 	private static final boolean logProblems= false;
-	private static IPropertyChangeListener listener= new IPropertyChangeListener() {
+	private static IEclipsePreferences.IPreferenceChangeListener listener= new IEclipsePreferences.IPreferenceChangeListener() {
 
-		public void propertyChange(PropertyChangeEvent event) {
-			String key= event.getProperty();
+		public void preferenceChange(IEclipsePreferences.PreferenceChangeEvent event) {
+			String key= event.getKey();
 			if (key.startsWith(CP_USERLIBRARY_PREFERENCES_PREFIX)) {
 				try {
 					recreatePersistedUserLibraryEntry(key, (String) event.getNewValue(), false, true);
@@ -58,7 +57,6 @@
 				}
 			}
 		}
-		
 	};
 	
 	private UserLibraryManager() {
@@ -126,20 +124,26 @@
 		if (userLibraries == null) {
 			userLibraries= new HashMap();
 			// load variables and containers from preferences into cache
-			Preferences preferences = JavaCore.getPlugin().getPluginPreferences();
-			preferences.addPropertyChangeListener(listener);
+			IEclipsePreferences instancePreferences = JavaCore.getInstancePreferences();
+			instancePreferences.addPreferenceChangeListener(listener);
 
 			// only get variable from preferences not set to their default
-			String[] propertyNames = preferences.propertyNames();
-			for (int i = 0; i < propertyNames.length; i++) {
-				String propertyName = propertyNames[i];
-				if (propertyName.startsWith(CP_USERLIBRARY_PREFERENCES_PREFIX)) {
-					try {
-						recreatePersistedUserLibraryEntry(propertyName, preferences.getString(propertyName), false, false);
-					} catch (JavaModelException e) {
-						// won't happen: no rebinding
+			try {
+				String[] propertyNames = instancePreferences.keys();
+				for (int i = 0; i < propertyNames.length; i++) {
+					String propertyName = propertyNames[i];
+					if (propertyName.startsWith(CP_USERLIBRARY_PREFERENCES_PREFIX)) {
+						try {
+							String propertyValue = instancePreferences.get(propertyName, null);
+							if (propertyValue != null)
+								recreatePersistedUserLibraryEntry(propertyName,propertyValue, false, false);
+						} catch (JavaModelException e) {
+							// won't happen: no rebinding
+						}
 					}
 				}
+			} catch (BackingStoreException e) {
+				// TODO (frederic) see if it's necessary to report this exception
 			}
 		}
 		return userLibraries;
@@ -178,7 +182,7 @@
 			}
 		}
 		
-		Preferences preferences = JavaCore.getPlugin().getPluginPreferences();
+		IEclipsePreferences instancePreferences = JavaCore.getInstancePreferences();
 		String containerKey = CP_USERLIBRARY_PREFERENCES_PREFIX+name;
 		String containerString = CP_ENTRY_IGNORE;
 		if (library != null) {
@@ -188,19 +192,23 @@
 				// could not encode entry: leave it as CP_ENTRY_IGNORE
 			}
 		}
-		preferences.removePropertyChangeListener(listener);
+		instancePreferences.removePreferenceChangeListener(listener);
 		try {
-			preferences.setDefault(containerKey, CP_ENTRY_IGNORE); // use this default to get rid of removed ones
-			preferences.setValue(containerKey, containerString);
+			JavaCore.getDefaultPreferences().put(containerKey, CP_ENTRY_IGNORE); // TODO (frederic) verify if this is really necessary...
+			instancePreferences.put(containerKey, containerString);
 			if (save) {
-				JavaCore.getPlugin().savePluginPreferences();
+				try {
+					instancePreferences.flush();
+				} catch (BackingStoreException e) {
+					// TODO (frederic) see if it's necessary to report this exception
+				}
 			}
 			if (rebind) {
 				rebindClasspathEntries(name, library==null, monitor);
 			}
 			
 		} finally {
-			preferences.addPropertyChangeListener(listener);
+			instancePreferences.addPreferenceChangeListener(listener);
 		}
 	}
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbortIncrementalBuildException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbortIncrementalBuildException.java
index f6a11f6..9f25413 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbortIncrementalBuildException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbortIncrementalBuildException.java
@@ -18,6 +18,7 @@
 public class AbortIncrementalBuildException extends RuntimeException {
 
 protected String qualifiedTypeName;
+private static final long serialVersionUID = -8874662133883858502L; // backward compatible
 
 public AbortIncrementalBuildException(String qualifiedTypeName) {
 	this.qualifiedTypeName = qualifiedTypeName;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
index 1f08553..24e3585 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
@@ -84,6 +84,11 @@
 			throw internalException(e);
 		}
 
+		if (result.hasInconsistentToplevelHierarchies)
+			// ensure that this file is always retrieved from source for the rest of the build
+			if (!problemSourceFiles.contains(compilationUnit))
+				problemSourceFiles.add(compilationUnit);
+
 		String typeLocator = compilationUnit.typeLocator();
 		ClassFile[] classFiles = result.getClassFiles();
 		int length = classFiles.length;
@@ -91,6 +96,7 @@
 		ArrayList definedTypeNames = new ArrayList(length);
 		for (int i = 0; i < length; i++) {
 			ClassFile classFile = classFiles[i];
+
 			char[][] compoundName = classFile.getCompoundName();
 			char[] typeName = compoundName[compoundName.length - 1];
 			boolean isNestedType = classFile.enclosingClassFile != null;
@@ -106,7 +112,13 @@
 					if (duplicateTypeNames == null)
 						duplicateTypeNames = new ArrayList();
 					duplicateTypeNames.add(compoundName);
-					createProblemFor(compilationUnit.resource, Util.bind("build.duplicateClassFile", new String(typeName)), JavaCore.ERROR); //$NON-NLS-1$
+					IType type = null;
+					try {
+						type = javaBuilder.javaProject.findType(qualifiedTypeName.replace('/', '.'));
+					} catch (JavaModelException e) {
+						// ignore
+					}
+					createProblemFor(compilationUnit.resource, type, Util.bind("build.duplicateClassFile", new String(typeName)), JavaCore.ERROR); //$NON-NLS-1$
 					continue;
 				}
 				newState.recordLocatorForType(qualifiedTypeName, typeLocator);
@@ -116,9 +128,9 @@
 			} catch (CoreException e) {
 				Util.log(e, "JavaBuilder handling CoreException"); //$NON-NLS-1$
 				if (e.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS)
-					createProblemFor(compilationUnit.resource, Util.bind("build.classFileCollision", e.getMessage()), JavaCore.ERROR); //$NON-NLS-1$
+					createProblemFor(compilationUnit.resource, null, Util.bind("build.classFileCollision", e.getMessage()), JavaCore.ERROR); //$NON-NLS-1$
 				else
-					createProblemFor(compilationUnit.resource, Util.bind("build.inconsistentClassFile"), JavaCore.ERROR); //$NON-NLS-1$
+					createProblemFor(compilationUnit.resource, null, Util.bind("build.inconsistentClassFile"), JavaCore.ERROR); //$NON-NLS-1$
 			}
 		}
 		finishedWith(typeLocator, result, compilationUnit.getMainTypeName(), definedTypeNames, duplicateTypeNames);
@@ -212,14 +224,17 @@
 	notifier.checkCancel();
 }
 
-protected void createProblemFor(IResource resource, String message, String problemSeverity) {
+protected void createProblemFor(IResource resource, IMember javaElement, String message, String problemSeverity) {
 	try {
 		IMarker marker = resource.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
 		int severity = problemSeverity.equals(JavaCore.WARNING) ? IMarker.SEVERITY_WARNING : IMarker.SEVERITY_ERROR;
 
+		ISourceRange range = javaElement == null ? null : javaElement.getNameRange();
+		int start = range == null ? 0 : range.getOffset();
+		int end = range == null ? 1 : start + range.getLength();
 		marker.setAttributes(
 			new String[] {IMarker.MESSAGE, IMarker.SEVERITY, IMarker.CHAR_START, IMarker.CHAR_END},
-			new Object[] {message, new Integer(severity), new Integer(0), new Integer(1)});
+			new Object[] {message, new Integer(severity), new Integer(start), new Integer(end)});
 	} catch (CoreException e) {
 		throw internalException(e);
 	}
@@ -317,31 +332,10 @@
 	for (int i = 0, l = problems.length; i < l; i++) {
 		IProblem problem = problems[i];
 		int id = problem.getID();
-		switch (id) {
-			case IProblem.IsClassPathCorrect :
-				JavaBuilder.removeProblemsAndTasksFor(javaBuilder.currentProject); // make this the only problem for this project
-				String[] args = problem.getArguments();
-				missingClassFile = args[0];
-				break;
-			case IProblem.SuperclassMustBeAClass :
-			case IProblem.SuperInterfaceMustBeAnInterface :
-			case IProblem.HierarchyCircularitySelfReference :
-			case IProblem.HierarchyCircularity :
-			case IProblem.HierarchyHasProblems :
-			case IProblem.SuperclassNotFound :
-			case IProblem.SuperclassNotVisible :
-			case IProblem.SuperclassAmbiguous :
-			case IProblem.SuperclassInternalNameProvided :
-			case IProblem.SuperclassInheritedNameHidesEnclosingName :
-			case IProblem.InterfaceNotFound :
-			case IProblem.InterfaceNotVisible :
-			case IProblem.InterfaceAmbiguous :
-			case IProblem.InterfaceInternalNameProvided :
-			case IProblem.InterfaceInheritedNameHidesEnclosingName :
-				// ensure that this file is always retrieved from source for the rest of the build
-				if (!problemSourceFiles.contains(sourceFile))
-					problemSourceFiles.add(sourceFile);
-				break;
+		if (id == IProblem.IsClassPathCorrect) {
+			JavaBuilder.removeProblemsAndTasksFor(javaBuilder.currentProject); // make this the only problem for this project
+			String[] args = problem.getArguments();
+			missingClassFile = args[0];
 		}
 
 		if (id != IProblem.Task) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
index 5aa5cb4..156a194 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
@@ -74,7 +74,7 @@
 								resource = proxy.requestResource();
 								if (Util.isExcluded(resource, inclusionPatterns, exclusionPatterns)) return false;
 							}
-							if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(proxy.getName())) {
+							if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(proxy.getName())) {
 								if (resource == null)
 									resource = proxy.requestResource();
 								sourceFiles.add(new SourceFile((IFile) resource, sourceLocation));
@@ -200,7 +200,7 @@
 				IResource resource = null;
 				switch(proxy.getType()) {
 					case IResource.FILE :
-						if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(proxy.getName()) ||
+						if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(proxy.getName()) ||
 							org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(proxy.getName())) return false;
 
 						resource = proxy.requestResource();
@@ -217,6 +217,7 @@
 								String id = originalResource.getFullPath().removeFirstSegments(1).toString();
 								createProblemFor(
 									resource,
+									null,
 									Util.bind("build.duplicateResource", id), //$NON-NLS-1$
 									javaBuilder.javaProject.getOption(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE, true));
 								return false;
@@ -225,7 +226,7 @@
 						}
 						resource.copy(copiedResource.getFullPath(), IResource.FORCE, null);
 						copiedResource.setDerived(true);
-						copiedResource.setReadOnly(false); // just in case the original was read only
+						Util.setReadOnly(copiedResource, false); // just in case the original was read only
 						return false;
 					case IResource.FOLDER :
 						resource = proxy.requestResource();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
index 8cab8e2..c336942 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
@@ -14,24 +14,26 @@
 import org.eclipse.core.runtime.*;
 
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
-import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 
-class ClasspathDirectory extends ClasspathLocation {
+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];
+AccessRestriction accessRestriction;
 
-ClasspathDirectory(IContainer binaryFolder, boolean isOutputFolder) {
+ClasspathDirectory(IContainer binaryFolder, boolean isOutputFolder, AccessRestriction accessRule) {
 	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.accessRestriction = accessRule;
 }
 
 public void cleanup() {
@@ -81,7 +83,11 @@
 	if (this == o) return true;
 	if (!(o instanceof ClasspathDirectory)) return false;
 
-	return binaryFolder.equals(((ClasspathDirectory) o).binaryFolder);
+	ClasspathDirectory dir = (ClasspathDirectory) o;
+	if (this.accessRestriction != dir.accessRestriction)
+		if (this.accessRestriction == null || !this.accessRestriction.equals(dir.accessRestriction))
+			return false;
+	return this.binaryFolder.equals(dir.binaryFolder);
 } 
 
 public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String qualifiedBinaryFileName) {
@@ -89,7 +95,11 @@
 
 	try {
 		ClassFileReader reader = ClassFileReader.read(binaryLocation + qualifiedBinaryFileName);
-		if (reader != null) return new NameEnvironmentAnswer(reader);
+		if (reader != null) {
+			if (this.accessRestriction == null)
+				return new NameEnvironmentAnswer(reader, null);
+			return new NameEnvironmentAnswer(reader, this.accessRestriction.getViolatedRestriction(qualifiedBinaryFileName.toCharArray(), null));
+		}
 	} 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) {
@@ -99,7 +109,11 @@
 				if (location != null) {
 					try {
 						ClassFileReader reader = ClassFileReader.read(location.toString());
-						if (reader != null) return new NameEnvironmentAnswer(reader);
+						if (reader != null) {
+							if (this.accessRestriction == null)
+								return new NameEnvironmentAnswer(reader, null);
+							return new NameEnvironmentAnswer(reader, this.accessRestriction.getViolatedRestriction(qualifiedBinaryFileName.toCharArray(), null));
+						}
 					} catch (Exception ignored) { // treat as if class file is missing
 					}
 				}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
index 47ce39b..df76efe 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
@@ -15,8 +15,9 @@
 import org.eclipse.core.runtime.*;
 
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
-import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.core.util.SimpleSet;
 
 import java.io.*;
@@ -80,26 +81,30 @@
 ZipFile zipFile;
 boolean closeZipFileAtEnd;
 SimpleSet knownPackageNames;
+AccessRestriction accessRestriction;
 
-ClasspathJar(String zipFilename) {
+ClasspathJar(String zipFilename, AccessRestriction accessRestriction) {
 	this.zipFilename = zipFilename;
 	this.zipFile = null;
 	this.knownPackageNames = null;
+	this.accessRestriction = accessRestriction;
 }
 
-ClasspathJar(IFile resource) {
+ClasspathJar(IFile resource, AccessRestriction accessRestriction) {
 	this.resource = resource;
 	IPath location = resource.getLocation();
 	this.zipFilename = location != null ? location.toString() : ""; //$NON-NLS-1$
 	this.zipFile = null;
 	this.knownPackageNames = null;
+	this.accessRestriction = accessRestriction;
 }
 
-public ClasspathJar(ZipFile zipFile) {
+public ClasspathJar(ZipFile zipFile, AccessRestriction accessRestriction) {
 	this.zipFilename = zipFile.getName();
 	this.zipFile = zipFile;
 	this.closeZipFileAtEnd = false;
 	this.knownPackageNames = null;
+	this.accessRestriction = accessRestriction;
 }
 
 public void cleanup() {
@@ -117,7 +122,11 @@
 	if (this == o) return true;
 	if (!(o instanceof ClasspathJar)) return false;
 
-	return zipFilename.equals(((ClasspathJar) o).zipFilename);
+	ClasspathJar jar = (ClasspathJar) o;
+	if (this.accessRestriction != jar.accessRestriction)
+		if (this.accessRestriction == null || !this.accessRestriction.equals(jar.accessRestriction))
+			return false;
+	return this.zipFilename.equals(((ClasspathJar) o).zipFilename);
 } 
 
 public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String qualifiedBinaryFileName) {
@@ -125,7 +134,11 @@
 
 	try {
 		ClassFileReader reader = ClassFileReader.read(this.zipFile, qualifiedBinaryFileName);
-		if (reader != null) return new NameEnvironmentAnswer(reader);
+		if (reader != null) {
+			if (this.accessRestriction == null)
+				return new NameEnvironmentAnswer(reader, null);
+			return new NameEnvironmentAnswer(reader, this.accessRestriction.getViolatedRestriction(qualifiedBinaryFileName.toCharArray(), null));
+		}
 	} catch (Exception e) { // treat as if class file is missing
 	}
 	return null;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
index 291b775..4531bf6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
@@ -13,6 +13,7 @@
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.*;
 
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
 
 public abstract class ClasspathLocation {
@@ -21,16 +22,16 @@
 	return new ClasspathMultiDirectory(sourceFolder, outputFolder, inclusionPatterns, exclusionPatterns);
 }
 
-public static ClasspathLocation forBinaryFolder(IContainer binaryFolder, boolean isOutputFolder) {
-	return new ClasspathDirectory(binaryFolder, isOutputFolder);
+public static ClasspathLocation forBinaryFolder(IContainer binaryFolder, boolean isOutputFolder, AccessRestriction accessRestriction) {
+	return new ClasspathDirectory(binaryFolder, isOutputFolder, accessRestriction);
 }
 
-static ClasspathLocation forLibrary(String libraryPathname) {
-	return new ClasspathJar(libraryPathname);
+static ClasspathLocation forLibrary(String libraryPathname, AccessRestriction accessRestriction) {
+	return new ClasspathJar(libraryPathname, accessRestriction);
 }
 
-static ClasspathLocation forLibrary(IFile library) {
-	return new ClasspathJar(library);
+static ClasspathLocation forLibrary(IFile library, AccessRestriction accessRestriction) {
+	return new ClasspathJar(library, accessRestriction);
 }
 
 public abstract NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String qualifiedBinaryFileName);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
index ba22e37..d0f262a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
@@ -23,7 +23,7 @@
 boolean hasIndependentOutputFolder; // if output folder is not equal to any of the source folders
 
 ClasspathMultiDirectory(IContainer sourceFolder, IContainer binaryFolder, char[][] inclusionPatterns, char[][] exclusionPatterns) {
-	super(binaryFolder, true);
+	super(binaryFolder, true, null);
 
 	this.sourceFolder = sourceFolder;
 	this.inclusionPatterns = inclusionPatterns;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ImageBuilderInternalException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ImageBuilderInternalException.java
index 5e5ab23..bc0c0c3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ImageBuilderInternalException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ImageBuilderInternalException.java
@@ -18,6 +18,7 @@
  */
 public class ImageBuilderInternalException extends RuntimeException {
 
+private static final long serialVersionUID = 28252254530437336L; // backward compatible
 protected CoreException coreException;
 
 public ImageBuilderInternalException(CoreException e) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
index 3efff69..e302427 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
@@ -18,8 +18,8 @@
 import org.eclipse.jdt.internal.compiler.*;
 import org.eclipse.jdt.internal.compiler.classfmt.*;
 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.SimpleLookupTable;
 import org.eclipse.jdt.internal.core.util.Util;
 
 import java.io.*;
@@ -327,7 +327,7 @@
 				try {
 					for (int j = 0, m = children.length; j < m; j++)
 						findSourceFiles(children[j], md, segmentCount);
-				} catch (org.eclipse.core.internal.resources.ResourceException e) {
+				} catch (CoreException e) {
 					// catch the case that a package has been renamed and collides on disk with an as-yet-to-be-deleted package
 					if (e.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS) {
 						if (JavaBuilder.DEBUG)
@@ -406,7 +406,7 @@
 			if (isExcluded) return;
 
 			String resourceName = resource.getName();
-			if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(resourceName)) {
+			if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(resourceName)) {
 				IPath typePath = resource.getFullPath().removeFirstSegments(segmentCount).removeFileExtension();
 				String typeLocator = resource.getProjectRelativePath().toString();
 				switch (sourceDelta.getKind()) {
@@ -446,7 +446,8 @@
 						newState.removeLocator(typeLocator);
 						return;
 					case IResourceDelta.CHANGED :
-						if ((sourceDelta.getFlags() & IResourceDelta.CONTENT) == 0)
+						if ((sourceDelta.getFlags() & IResourceDelta.CONTENT) == 0
+								&& (sourceDelta.getFlags() & IResourceDelta.ENCODING) == 0)
 							return; // skip it since it really isn't changed
 						if (JavaBuilder.DEBUG)
 							System.out.println("Compile this changed source file " + typeLocator); //$NON-NLS-1$
@@ -473,7 +474,7 @@
 						createFolder(resourcePath.removeLastSegments(1), md.binaryFolder); // ensure package exists in the output folder
 						resource.copy(outputFile.getFullPath(), IResource.FORCE, null);
 						outputFile.setDerived(true);
-						outputFile.setReadOnly(false); // just in case the original was read only
+						Util.setReadOnly(outputFile, false); // just in case the original was read only
 						return;
 					case IResourceDelta.REMOVED :
 						if (outputFile.exists()) {
@@ -483,7 +484,8 @@
 						}
 						return;
 					case IResourceDelta.CHANGED :
-						if ((sourceDelta.getFlags() & IResourceDelta.CONTENT) == 0)
+						if ((sourceDelta.getFlags() & IResourceDelta.CONTENT) == 0
+								&& (sourceDelta.getFlags() & IResourceDelta.ENCODING) == 0)
 							return; // skip it since it really isn't changed
 						if (outputFile.exists()) {
 							if (JavaBuilder.DEBUG)
@@ -495,7 +497,7 @@
 						createFolder(resourcePath.removeLastSegments(1), md.binaryFolder); // ensure package exists in the output folder
 						resource.copy(outputFile.getFullPath(), IResource.FORCE, null);
 						outputFile.setDerived(true);
-						outputFile.setReadOnly(false); // just in case the original was read only
+						Util.setReadOnly(outputFile, false); // just in case the original was read only
 				}
 				return;
 			}
@@ -611,7 +613,7 @@
 			System.out.println("Writing new class file " + file.getName());//$NON-NLS-1$
 		try {
 			file.create(new ByteArrayInputStream(bytes), IResource.FORCE, null);
-		} catch (org.eclipse.core.internal.resources.ResourceException e) {
+		} catch (CoreException e) {
 			if (e.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS)
 				// catch the case that a nested type has been renamed and collides on disk with an as-yet-to-be-deleted type
 				throw new AbortCompilation(true, new AbortIncrementalBuildException(qualifiedFileName));
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
index faede61..fb3cf84 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
@@ -15,8 +15,8 @@
 
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.core.*;
-import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.core.util.Util;
 
 import java.io.*;
@@ -68,8 +68,7 @@
  * This hook is invoked during PRE_AUTO_BUILD notification
  */
 public static void buildStarting() {
-	// do nothing
-	// TODO (philippe) is it still needed?
+	// build is about to start
 }
 
 /**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/MissingClassFileException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/MissingClassFileException.java
index 2096e8b..aed06aa 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/MissingClassFileException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/MissingClassFileException.java
@@ -16,7 +16,8 @@
  */
 public class MissingClassFileException extends RuntimeException {
 
-protected String missingClassFile;
+	protected String missingClassFile;
+	private static final long serialVersionUID = 3060418973806972616L; // backward compatible
 
 public MissingClassFileException(String missingClassFile) {
 	this.missingClassFile = missingClassFile;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/MissingSourceFileException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/MissingSourceFileException.java
index 379c058..fd29527 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/MissingSourceFileException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/MissingSourceFileException.java
@@ -15,8 +15,9 @@
  */
 public class MissingSourceFileException extends RuntimeException {
 
-protected String missingSourceFile;
-
+	protected String missingSourceFile;
+	private static final long serialVersionUID = -1416609004971115719L; // backward compatible
+	
 public MissingSourceFileException(String missingSourceFile) {
 	this.missingSourceFile = missingSourceFile;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
index ab912f6..f8275fa 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
@@ -17,9 +17,10 @@
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.env.*;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.*;
-import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.core.util.Util;
 
 import java.io.*;
 import java.util.*;
@@ -29,7 +30,7 @@
 boolean isIncrementalBuild;
 ClasspathMultiDirectory[] sourceLocations;
 ClasspathLocation[] binaryLocations;
-
+	
 String[] initialTypeNames; // assumed that each name is of the form "a/b/ClassName"
 SourceFile[] additionalUnits;
 
@@ -135,7 +136,11 @@
 							: (IContainer) root.getFolder(prereqOutputPath);
 						if (binaryFolder.exists() && !seen.contains(binaryFolder)) {
 							seen.add(binaryFolder);
-							ClasspathLocation bLocation = ClasspathLocation.forBinaryFolder(binaryFolder, true);
+							ClasspathLocation bLocation = 
+								ClasspathLocation.forBinaryFolder(
+										binaryFolder, 
+										true, 
+										entry.getImportRestriction());
 							bLocations.add(bLocation);
 							if (binaryLocationsPerProject != null) { // normal builder mode
 								ClasspathLocation[] existingLocations = (ClasspathLocation[]) binaryLocationsPerProject.get(prereqProject);
@@ -160,9 +165,15 @@
 					if (resource instanceof IFile) {
 						if (!(org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(path.lastSegment())))
 							continue nextEntry;
-						bLocation = ClasspathLocation.forLibrary((IFile) resource);
+						AccessRestriction restriction = JavaCore.IGNORE.equals(javaProject.getOption(JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE, true))
+																			? null
+																			: entry.getImportRestriction();
+						bLocation = ClasspathLocation.forLibrary((IFile) resource, restriction);
 					} else if (resource instanceof IContainer) {
-						bLocation = ClasspathLocation.forBinaryFolder((IContainer) target, false); // is library folder not output folder
+						AccessRestriction restriction = JavaCore.IGNORE.equals(javaProject.getOption(JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE, true))
+																			? null
+																			: entry.getImportRestriction();
+						bLocation = ClasspathLocation.forBinaryFolder((IContainer) target, false, restriction);	 // is library folder not output folder
 					}
 					bLocations.add(bLocation);
 					if (binaryLocationsPerProject != null) { // normal builder mode
@@ -180,7 +191,10 @@
 				} else if (target instanceof File) {
 					if (!(org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(path.lastSegment())))
 						continue nextEntry;
-					bLocations.add(ClasspathLocation.forLibrary(path.toString()));
+					AccessRestriction restriction = JavaCore.IGNORE.equals(javaProject.getOption(JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE, true))
+																		? null
+																		: entry.getImportRestriction();
+					bLocations.add(ClasspathLocation.forLibrary(path.toString(), restriction));
 				}
 				continue nextEntry;
 		}
@@ -253,17 +267,19 @@
 		// if an additional source file is waiting to be compiled, answer it BUT not if this is a secondary type search
 		// if we answer X.java & it no longer defines Y then the binary type looking for Y will think the class path is wrong
 		// let the recompile loop fix up dependents when the secondary type Y has been deleted from X.java
-		IPath qSourceFilePath = new Path(qualifiedTypeName + SUFFIX_STRING_java);
+		IPath qSourceFilePath = new Path(qualifiedTypeName); // doesn't have file extension
 		int qSegmentCount = qSourceFilePath.segmentCount();
 		next : for (int i = 0, l = additionalUnits.length; i < l; i++) {
 			SourceFile additionalUnit = additionalUnits[i];
 			IPath fullPath = additionalUnit.resource.getFullPath();
 			int prefixCount = additionalUnit.sourceLocation.sourceFolder.getFullPath().segmentCount();
 			if (qSegmentCount == fullPath.segmentCount() - prefixCount) {
-				for (int j = 0; j < qSegmentCount; j++)
+				for (int j = 0; j < qSegmentCount - 1; j++)
 					if (!qSourceFilePath.segment(j).equals(fullPath.segment(j + prefixCount)))
 						continue next;
-				return new NameEnvironmentAnswer(additionalUnit);
+				if (!Util.equalsIgnoreJavaLikeExtension(fullPath.segment(qSegmentCount-1 + prefixCount), qSourceFilePath.segment(qSegmentCount-1)))
+					continue next;
+				return new NameEnvironmentAnswer(additionalUnit, null /*no access restriction*/);
 			}
 		}
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ProblemFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ProblemFactory.java
index ce6c6a3..7d47e62 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ProblemFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ProblemFactory.java
@@ -11,7 +11,7 @@
 package org.eclipse.jdt.internal.core.builder;
 
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
-import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 
 import java.util.*;
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java
index 6fea880..85f2ae2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java
@@ -52,13 +52,16 @@
 	IPath fullPath = this.resource.getFullPath();
 	int resourceSegmentCount = fullPath.segmentCount();
 	int sourceFolderSegmentCount = this.sourceLocation.sourceFolder.getFullPath().segmentCount();
-	int charCount = (resourceSegmentCount - sourceFolderSegmentCount - 1) - 5; // length of ".java"
+	int charCount = (resourceSegmentCount - sourceFolderSegmentCount - 1);
+	resourceSegmentCount--; // deal with the last segment separately
 	for (int i = sourceFolderSegmentCount; i < resourceSegmentCount; i++)
 		charCount += fullPath.segment(i).length();
+	String lastSegment = fullPath.segment(resourceSegmentCount);
+	int extensionIndex = Util.indexOfJavaLikeExtension(lastSegment);
+	charCount += extensionIndex;
 
 	char[] result = new char[charCount];
 	int offset = 0;
-	resourceSegmentCount--; // deal with the last segment separately
 	for (int i = sourceFolderSegmentCount; i < resourceSegmentCount; i++) {
 		String segment = fullPath.segment(i);
 		int size = segment.length();
@@ -66,9 +69,7 @@
 		offset += size;
 		result[offset++] = '/';
 	}
-	String segment = fullPath.segment(resourceSegmentCount);
-	int size = segment.length() - 5; // length of ".java"
-	segment.getChars(0, size, result, offset);
+	lastSegment.getChars(0, extensionIndex, result, offset);
 	return new String(result);
 }
 
@@ -81,6 +82,9 @@
 	}
 }
 
+/**
+ * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
+ */
 public char[] getFileName() {
 	return this.resource.getFullPath().toString().toCharArray(); // do not know what you want to return here
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
index fcc4894..fb01d61 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
@@ -14,7 +14,8 @@
 import org.eclipse.core.runtime.*;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 
 import java.io.*;
 import java.util.*;
@@ -40,7 +41,7 @@
 private StringSet structurallyChangedTypes;
 public static int MaxStructurallyChangedTypes = 100; // keep track of ? structurally changed types, otherwise consider all to be changed
 
-static final byte VERSION = 0x0008;
+static final byte VERSION = 0x0009; // added AccessRestrictions
 
 static final byte SOURCE_FOLDER = 1;
 static final byte BINARY_FOLDER = 2;
@@ -182,7 +183,7 @@
 			return;
 		case IResource.FILE :
 			IPath typeLocatorPath = resource.getProjectRelativePath();
-			if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(typeLocatorPath.lastSegment()))
+			if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(typeLocatorPath.lastSegment()))
 				removeLocator(typeLocatorPath.toString());
 	}
 }
@@ -238,13 +239,13 @@
 				IContainer outputFolder = path.segmentCount() == 1
 					? (IContainer) root.getProject(path.toString())
 					: (IContainer) root.getFolder(path);
-				newState.binaryLocations[i] = ClasspathLocation.forBinaryFolder(outputFolder, in.readBoolean());
+				newState.binaryLocations[i] = ClasspathLocation.forBinaryFolder(outputFolder, in.readBoolean(), readRestriction(in));
 				break;
 			case EXTERNAL_JAR :
-				newState.binaryLocations[i] = ClasspathLocation.forLibrary(in.readUTF());
+				newState.binaryLocations[i] = ClasspathLocation.forLibrary(in.readUTF(), readRestriction(in));
 				break;
 			case INTERNAL_JAR :
-				newState.binaryLocations[i] = ClasspathLocation.forLibrary(root.getFile(new Path(in.readUTF())));
+				newState.binaryLocations[i] = ClasspathLocation.forLibrary(root.getFile(new Path(in.readUTF())), readRestriction(in));
 		}
 	}
 
@@ -315,6 +316,14 @@
 	return names;
 }
 
+private static AccessRestriction readRestriction(DataInputStream in) throws IOException {
+	if (in.readBoolean())
+		// skip the AccessRestriction.furtherRestriction until we decide if it will be used
+		return new AccessRestriction(in.readUTF(), readNames(in), readNames(in), null);
+
+	return null; // no restriction specified
+}
+
 void tagAsNoopBuild() {
 	this.buildNumber = -1; // tag the project since it has no source folders and can be skipped
 }
@@ -399,6 +408,7 @@
 			ClasspathDirectory cd = (ClasspathDirectory) c;
 			out.writeUTF(cd.binaryFolder.getFullPath().toString());
 			out.writeBoolean(cd.isOutputFolder);
+			writeRestriction(cd.accessRestriction, out);
 		} else {
 			ClasspathJar jar = (ClasspathJar) c;
 			if (jar.resource == null) {
@@ -408,6 +418,7 @@
 				out.writeByte(INTERNAL_JAR);
 				out.writeUTF(jar.resource.getFullPath().toString());
 			}
+			writeRestriction(jar.accessRestriction, out);
 		}
 	}
 
@@ -562,6 +573,18 @@
 	}
 }
 
+private void writeRestriction(AccessRestriction restriction, DataOutputStream out) throws IOException {
+	if (restriction == null) {
+		out.writeBoolean(false);
+	} else {
+		out.writeBoolean(true);
+		out.writeUTF(restriction.getMessageTemplate());
+		writeNames(restriction.getExclusionPatterns(), out);
+		writeNames(restriction.getInclusionPatterns(), out);
+		// skip the AccessRestriction.furtherRestriction until we decide if it will be used
+	}
+}
+
 /**
  * Returns a string representation of the receiver.
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java
index ea0eb3d..cc0cc1b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java
@@ -19,7 +19,6 @@
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.ICompletionRequestor;
 import org.eclipse.jdt.core.IImportDeclaration;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaModelMarker;
@@ -37,7 +36,6 @@
 import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.BinaryType;
 import org.eclipse.jdt.internal.core.ClassFile;
-import org.eclipse.jdt.internal.core.CompletionRequestorWrapper;
 import org.eclipse.jdt.internal.core.JavaModelStatus;
 import org.eclipse.jdt.internal.core.JavaProject;
 import org.eclipse.jdt.internal.core.SelectionRequestor;
@@ -84,20 +82,37 @@
 }
 /**
  * @see org.eclipse.jdt.core.eval.IEvaluationContext#codeComplete(String, int, ICompletionRequestor)
+ * @deprecated
  */
 public void codeComplete(String codeSnippet, int position, ICompletionRequestor requestor) throws JavaModelException {
 	codeComplete(codeSnippet, position, requestor, DefaultWorkingCopyOwner.PRIMARY);
 }
 /**
  * @see org.eclipse.jdt.core.eval.IEvaluationContext#codeComplete(String, int, ICompletionRequestor, WorkingCopyOwner)
+ * @deprecated
  */
 public void codeComplete(String codeSnippet, int position, ICompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
-	SearchableEnvironment environment = (SearchableEnvironment) this.project.newSearchableNameEnvironment(owner);
+	if (requestor == null) {
+		throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$
+	}
+	codeComplete(codeSnippet, position, new org.eclipse.jdt.internal.codeassist.CompletionRequestorWrapper(requestor), owner);
+}
+/**
+ * @see org.eclipse.jdt.core.eval.IEvaluationContext#codeComplete(String, int, CompletionRequestor)
+ */
+public void codeComplete(String codeSnippet, int position, CompletionRequestor requestor) throws JavaModelException {
+	codeComplete(codeSnippet, position, requestor, DefaultWorkingCopyOwner.PRIMARY);
+}
+/**
+ * @see org.eclipse.jdt.core.eval.IEvaluationContext#codeComplete(String, int, CompletionRequestor, WorkingCopyOwner)
+ */
+public void codeComplete(String codeSnippet, int position, CompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
+	SearchableEnvironment environment = this.project.newSearchableNameEnvironment(owner);
 	this.context.complete(
 		codeSnippet.toCharArray(),
 		position,
 		environment,
-		new CompletionRequestorWrapper(requestor, environment.nameLookup),
+		requestor,
 		this.project.getOptions(true),
 		this.project
 	);
@@ -112,7 +127,7 @@
  * @see org.eclipse.jdt.core.eval.IEvaluationContext#codeSelect(String, int, int, WorkingCopyOwner)
  */
 public IJavaElement[] codeSelect(String codeSnippet, int offset, int length, WorkingCopyOwner owner) throws JavaModelException {
-	SearchableEnvironment environment = (SearchableEnvironment) this.project.newSearchableNameEnvironment(owner);
+	SearchableEnvironment environment = this.project.newSearchableNameEnvironment(owner);
 	SelectionRequestor requestor= new SelectionRequestor(environment.nameLookup, null); // null because there is no need to look inside the code snippet itself
 	this.context.select(
 		codeSnippet.toCharArray(),
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java
index 34f1d6e..bd821c6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java
@@ -10,26 +10,43 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.hierarchy;
 
+import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.env.IBinaryField;
 import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
 import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
 import org.eclipse.jdt.internal.compiler.env.IConstants;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
 
 public class HierarchyBinaryType implements IBinaryType {
 	private int modifiers;
-	private boolean isClass;
+	private int kind;
 	private char[] name;
 	private char[] enclosingTypeName;
 	private char[] superclass;
 	private char[][] superInterfaces = NoInterface;
+	private char[][] typeParameterSignatures;
+	private char[] genericSignature;
 	
-public HierarchyBinaryType(int modifiers, char[] qualification, char[] typeName, char[] enclosingTypeName, char classOrInterface){
+public HierarchyBinaryType(int modifiers, char[] qualification, char[] typeName, char[] enclosingTypeName, char[][] typeParameterSignatures, char typeSuffix){
 
 	this.modifiers = modifiers;
-	this.isClass = classOrInterface == IIndexConstants.CLASS_SUFFIX;
+	switch(typeSuffix) {
+		case IIndexConstants.CLASS_SUFFIX :
+			this.kind = IGenericType.CLASS_DECL;
+			break;
+		case IIndexConstants.INTERFACE_SUFFIX :
+			this.kind = IGenericType.INTERFACE_DECL;
+			break;
+		case IIndexConstants.ENUM_SUFFIX :
+			this.kind = IGenericType.ENUM_DECL;
+			break;
+		case IIndexConstants.ANNOTATION_TYPE_SUFFIX :
+			this.kind = IGenericType.ANNOTATION_TYPE_DECL;
+			break;
+	}
 	if (enclosingTypeName == null){
 		this.name = CharOperation.concat(qualification, typeName, '/');
 	} else {
@@ -37,6 +54,7 @@
 		this.enclosingTypeName = CharOperation.concat(qualification, enclosingTypeName,'/');
 		CharOperation.replace(this.enclosingTypeName, '.', '/');
 	}
+	this.typeParameterSignatures = typeParameterSignatures;
 	CharOperation.replace(this.name, '.', '/');
 }
 /**
@@ -56,18 +74,39 @@
 	return null;
 }
 /**
- * Answer the file name which defines the type.
- *
- * The path part (optional) must be separated from the actual
- * file proper name by a java.io.File.separator.
- *
- * The proper file name includes the suffix extension (e.g. ".java")
- *
- * e.g. "c:/com/ibm/compiler/java/api/Compiler.java" 
+ * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
  */
 public char[] getFileName() {
 	return null;
 }
+public char[] getGenericSignature() {
+	if (this.typeParameterSignatures != null && this.genericSignature == null) {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append('<');
+		for (int i = 0, length = this.typeParameterSignatures.length; i < length; i++) {
+			buffer.append(this.typeParameterSignatures[i]);
+			if (i != length-1)
+				buffer.append(',');
+		}
+		buffer.append('>');
+		if (this.superclass == null)
+			buffer.append(Signature.createTypeSignature("java.lang.Object", true/*resolved*/)); //$NON-NLS-1$
+		else
+			buffer.append(Signature.createTypeSignature(this.superclass, true/*resolved*/));
+		if (this.superInterfaces != null) 
+			for (int i = 0, length = this.superInterfaces.length; i < length; i++)
+				buffer.append(Signature.createTypeSignature(this.superInterfaces[i], true/*resolved*/));
+		this.genericSignature = buffer.toString().toCharArray();
+		CharOperation.replace(this.genericSignature, '.', '/');
+	}
+	return this.genericSignature;
+}
+/**
+ * @see org.eclipse.jdt.internal.compiler.env.IGenericType#getKind()
+ */
+public int getKind() {
+	return this.kind;
+}
 /**
  * Answer the resolved names of the receiver's interfaces in the
  * class file format as specified in section 4.2 of the Java 2 VM spec
@@ -130,18 +169,6 @@
 public boolean isBinaryType() {
 	return true;
 }
-/**
- * isClass method comment.
- */
-public boolean isClass() {
-	return this.isClass;
-}
-/**
- * isInterface method comment.
- */
-public boolean isInterface() {
-	return !this.isClass;
-}
 public boolean isLocal() {
 	return false;  // index did not record this information (since unused for hierarchies)
 }
@@ -164,7 +191,7 @@
 	if (superClassOrInterface == IIndexConstants.CLASS_SUFFIX){
 		// interfaces are indexed as having superclass references to Object by default,
 		// this is an artifact used for being able to query them only.
-		if (!this.isClass) return; 
+		if (this.kind == IGenericType.INTERFACE_DECL) return; 
 		char[] encodedName = CharOperation.concat(superQualification, superTypeName, '/');
 		CharOperation.replace(encodedName, '.', '/'); 
 		this.superclass = encodedName;
@@ -185,10 +212,16 @@
 	if (this.modifiers == IConstants.AccPublic) {
 		buffer.append("public "); //$NON-NLS-1$
 	}
-	if (this.isClass()) {
-		buffer.append("class "); //$NON-NLS-1$
-	} else {
-		buffer.append("interface "); //$NON-NLS-1$
+	switch (this.kind) {
+		case IGenericType.CLASS_DECL :
+			buffer.append("class "); //$NON-NLS-1$
+			break;		
+		case IGenericType.INTERFACE_DECL :
+			buffer.append("interface "); //$NON-NLS-1$
+			break;		
+		case IGenericType.ENUM_DECL :
+			buffer.append("enum "); //$NON-NLS-1$
+			break;		
 	}
 	if (this.name != null) {
 		buffer.append(this.name);
@@ -216,4 +249,8 @@
 public char[] sourceFileName() {
 	return null;
 }
+// TODO (jerome) please verify that we don't need the tagbits for the receiver
+public long getTagBits() {
+	return 0;
+}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
index b2d1383..23ab832 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
@@ -17,14 +17,13 @@
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.jdt.core.IClassFile;
-import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IType;
-//import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.BasicCompilationUnit;
 import org.eclipse.jdt.internal.core.ClassFile;
 import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
@@ -35,6 +34,7 @@
 import org.eclipse.jdt.internal.core.Openable;
 import org.eclipse.jdt.internal.core.SearchableEnvironment;
 import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
+import org.eclipse.jdt.internal.core.util.Util;
 
 public abstract class HierarchyBuilder implements IHierarchyRequestor {
 	/**
@@ -57,6 +57,11 @@
 	 * no supertypes outside the region).
 	 */
 	protected Map infoToHandle;
+	/*
+	 * The dot-separated fully qualified name of the focus type, or null of none.
+	 */
+	protected String focusQualifiedName;
+	
 	public HierarchyBuilder(TypeHierarchy hierarchy) throws JavaModelException {
 		
 		this.hierarchy = hierarchy;
@@ -78,7 +83,7 @@
 		} else {
 			unitsToLookInside = workingCopies;
 		}
-		SearchableEnvironment searchableEnvironment = (SearchableEnvironment) project.newSearchableNameEnvironment(unitsToLookInside);
+		SearchableEnvironment searchableEnvironment = project.newSearchableNameEnvironment(unitsToLookInside);
 		this.nameLookup = searchableEnvironment.nameLookup;
 		this.hierarchyResolver =
 			new HierarchyResolver(
@@ -87,6 +92,7 @@
 				this,
 				new DefaultProblemFactory());
 		this.infoToHandle = new HashMap(5);
+		this.focusQualifiedName = focusType == null ? null : focusType.getFullyQualifiedName();
 	}
 	
 	public abstract void build(boolean computeSubtypes)
@@ -186,15 +192,20 @@
 			}
 		}
 		// now do the caching
-		if (suppliedType.isClass()) {
-			if (superHandle == null) {
-				this.hierarchy.addRootClass(typeHandle);
-			} else {
-				this.hierarchy.cacheSuperclass(typeHandle, superHandle);
-			}
-		} else {
-			this.hierarchy.addInterface(typeHandle);
-		}
+		switch (suppliedType.getKind()) {
+			case IGenericType.CLASS_DECL :
+			case IGenericType.ENUM_DECL :
+				if (superHandle == null) {
+					this.hierarchy.addRootClass(typeHandle);
+				} else {
+					this.hierarchy.cacheSuperclass(typeHandle, superHandle);
+				}
+				break;
+			case IGenericType.INTERFACE_DECL :
+			case IGenericType.ANNOTATION_TYPE_DECL :
+				this.hierarchy.addInterface(typeHandle);
+				break;
+		}		
 		if (interfaceHandles == null) {
 			interfaceHandles = TypeHierarchy.NO_TYPE;
 		}
@@ -248,13 +259,24 @@
 	protected IType lookupBinaryHandle(IBinaryType typeInfo) {
 		int flag;
 		String qualifiedName;
-		if (typeInfo.isClass()) {
-			flag = NameLookup.ACCEPT_CLASSES;
-		} else {
-			flag = NameLookup.ACCEPT_INTERFACES;
-		}
+		switch (typeInfo.getKind()) {
+			case IGenericType.CLASS_DECL :
+				flag = NameLookup.ACCEPT_CLASSES;
+				break;
+			case IGenericType.INTERFACE_DECL :
+				flag = NameLookup.ACCEPT_INTERFACES;
+				break;
+			case IGenericType.ENUM_DECL :
+				flag = NameLookup.ACCEPT_ENUMS;
+				break;
+			default:
+				//case IGenericType.ANNOTATION :
+				flag = NameLookup.ACCEPT_ANNOTATIONS;
+				break;
+		}			
 		char[] bName = typeInfo.getName();
 		qualifiedName = new String(ClassFile.translatedName(bName));
+		if (qualifiedName.equals(this.focusQualifiedName)) return getType();
 		return this.nameLookup.findType(qualifiedName, false, flag);
 	}
 	protected void worked(IProgressMonitor monitor, int work) {
@@ -303,8 +325,8 @@
  * Create a type info from the given class file in a jar and adds it to the given list of infos.
  */
 protected IBinaryType createInfoFromClassFileInJar(Openable classFile) {
-	IJavaElement pkg = classFile.getParent();
-	String classFilePath = pkg.getElementName().replace('.', '/') + "/" + classFile.getElementName(); //$NON-NLS-1$
+	PackageFragment pkg = (PackageFragment) classFile.getParent();
+	String classFilePath = Util.concatWith(pkg.names, classFile.getElementName(), '/');
 	IBinaryType info = null;
 	java.util.zip.ZipFile zipFile = null;
 	try {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
index 33e7a62..b6efb5f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
@@ -33,6 +33,7 @@
 import org.eclipse.core.runtime.OperationCanceledException;
 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.CompilationResult;
 import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
@@ -42,6 +43,7 @@
 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;
 import org.eclipse.jdt.internal.compiler.env.IGenericType;
@@ -63,7 +65,6 @@
 import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.Member;
 import org.eclipse.jdt.internal.core.util.ASTNodeFinder;
-import org.eclipse.jdt.internal.core.util.ElementInfoConverter;
 import org.eclipse.jdt.internal.core.util.HandleFactory;
 
 public class HierarchyResolver implements ITypeRequestor {
@@ -78,39 +79,32 @@
 			this.simpleName = simpleName;
 		}
 	
-		/*
-		 * @see IDependent#getFileName()
+		/**
+		 * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
 		 */
 		public char[] getFileName() {
 			return null;
 		}
 		
-		/*
+		/**
 		 * @see IGenericType#getModifiers()
 		 */
 		public int getModifiers() {
 			return 0;
 		}
 	
-		/*
+		/**
 		 * @see IGenericType#isBinaryType()
 		 */
 		public boolean isBinaryType() {
 			return false;
 		}
 	
-		/*
-		 * @see IGenericType#isClass()
+		/**
+		 * @see org.eclipse.jdt.internal.compiler.env.IGenericType#getKind()
 		 */
-		public boolean isClass() {
-			return false;
-		}
-	
-		/*
-		 * @see IGenericType#isInterface()
-		 */
-		public boolean isInterface() {
-			return false;
+		public int getKind() {
+			return 0;
 		}
 		
 		public String toString() {
@@ -148,8 +142,8 @@
  * @param binaryType
  * @param packageBinding
  */
-public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
-	BinaryTypeBinding typeBinding = this.lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
+public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+	BinaryTypeBinding typeBinding = this.lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
 	try {
 		this.remember(binaryType, typeBinding);
 	} catch (AbortCompilation e) {
@@ -161,7 +155,7 @@
  * Add an additional compilation unit.
  * @param sourceUnit
  */
-public void accept(ICompilationUnit sourceUnit) {
+public void accept(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
 	//System.out.println("Cannot accept compilation units inside the HierarchyResolver.");
 	this.lookupEnvironment.problemReporter.abortDueToInternalError(
 		new StringBuffer(Util.bind("accept.cannot")) //$NON-NLS-1$
@@ -174,7 +168,7 @@
  * @param sourceTypes
  * @param packageBinding
  */
-public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
+public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
 	// find most enclosing type first (needed when explicit askForType(...) is done 
 	// with a member type (e.g. p.A$B))
 	ISourceType sourceType = sourceTypes[0];
@@ -194,7 +188,7 @@
 	// build bindings
 	if (unit != null) {
 		try {
-			this.lookupEnvironment.buildTypeBindings(unit);
+			this.lookupEnvironment.buildTypeBindings(unit, accessRestriction);
 			
 			org.eclipse.jdt.core.ICompilationUnit cu = ((SourceTypeElementInfo)sourceType).getHandle().getCompilationUnit();
 			rememberAllTypes(unit, cu, false);
@@ -213,6 +207,7 @@
 private IGenericType findSuperClass(IGenericType type, ReferenceBinding typeBinding) {
 	ReferenceBinding superBinding = typeBinding.superclass();
 	if (superBinding != null) {
+		superBinding = (ReferenceBinding) superBinding.erasure();
 		if (superBinding.id == TypeIds.T_JavaLangObject && typeBinding.isHierarchyInconsistent()) {
 			char[] superclassName;
 			char separator;
@@ -265,7 +260,10 @@
 				superInterfaceNames = sourceType.getInterfaceNames();
 			}
 		} else {
-			superInterfaceNames = sourceType.getInterfaceNames();
+			if (sourceType.getKind() == IGenericType.ANNOTATION_TYPE_DECL)
+				superInterfaceNames = new char[][] {TypeConstants.CharArray_JAVA_LANG_ANNOTATION_ANNOTATION};
+			else
+				superInterfaceNames = sourceType.getInterfaceNames();
 		}
 		separator = '.';
 	} else if (type instanceof HierarchyType) {
@@ -292,17 +290,21 @@
 	next : for (int i = 0; i < length; i++) {
 		char[] superInterfaceName = superInterfaceNames[i];
 		int lastSeparator = CharOperation.lastIndexOf(separator, superInterfaceName);
-		char[] simpleName = lastSeparator == -1 ? superInterfaceName : CharOperation.subarray(superInterfaceName, lastSeparator+1, superInterfaceName.length);
+		int start = lastSeparator + 1; 
+		int end = superInterfaceName.length;
 		
 		// case of binary inner type -> take the last part
-		int start = CharOperation.lastIndexOf('$', simpleName) + 1;
-		if (start != 0) {
-			int nameLength = simpleName.length - start;
-			System.arraycopy(simpleName, start, simpleName = new char[nameLength], 0, nameLength);
-		}
+		int lastDollar = CharOperation.lastIndexOf('$', superInterfaceName, start);
+		if (lastDollar != -1) start = lastDollar + 1;
+		
+		// case of a parameterized type -> take the first part
+		int genericStart = CharOperation.indexOf(Signature.C_GENERIC_START, superInterfaceName, start);
+		if (genericStart != -1) end = genericStart;
+		
+		char[] simpleName = CharOperation.subarray(superInterfaceName, start, end);
 		
 		if (bindingIndex < bindingLength) {
-			ReferenceBinding interfaceBinding = interfaceBindings[bindingIndex];
+			ReferenceBinding interfaceBinding = (ReferenceBinding) interfaceBindings[bindingIndex].erasure();
 
 			// ensure that the binding corresponds to the interface defined by the user
 			if (CharOperation.equals(simpleName, interfaceBinding.sourceName)) {
@@ -371,7 +373,7 @@
 	
 		HierarchyType hierarchyType = new HierarchyType(
 			type, 
-			!typeDeclaration.isInterface(),
+			typeDeclaration.kind(),
 			typeDeclaration.name,
 			typeDeclaration.binding.modifiers,
 			superclassName,
@@ -495,7 +497,7 @@
 public void resolve(IGenericType suppliedType) {
 	try {
 		if (suppliedType.isBinaryType()) {
-			BinaryTypeBinding binaryTypeBinding = this.lookupEnvironment.cacheBinaryType((IBinaryType) suppliedType);
+			BinaryTypeBinding binaryTypeBinding = this.lookupEnvironment.cacheBinaryType((IBinaryType) suppliedType, null /*no access restriction*/);
 			remember(suppliedType, binaryTypeBinding);
 			// We still need to add superclasses and superinterfaces bindings (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53095)
 			int startIndex = this.typeIndex;
@@ -594,23 +596,16 @@
 					} catch (JavaModelException e) {
 						// types/cu exist since cu is opened
 					}
-					if (!containsLocalType) {
-						parsedUnit = 
-							SourceTypeConverter.buildCompilationUnit(
-								typeInfos, 
-								SourceTypeConverter.MEMBER_TYPE, // need member types
-								// no need for field initialization
-								this.lookupEnvironment.problemReporter, 
-								result);
-					} else {
-						parsedUnit =
-							ElementInfoConverter.buildCompilationUnit(
-								typeInfos, 
-								true, // need local types
-								this.lookupEnvironment.problemReporter, 
-								result);
-						parsedUnit.bits |= ASTNode.HasAllMethodBodies;
-					}
+					int flags = !containsLocalType 
+						? SourceTypeConverter.MEMBER_TYPE 
+						: SourceTypeConverter.FIELD_AND_METHOD | SourceTypeConverter.MEMBER_TYPE | SourceTypeConverter.LOCAL_TYPE;
+					parsedUnit = 
+						SourceTypeConverter.buildCompilationUnit(
+							typeInfos, 
+							flags,
+							this.lookupEnvironment.problemReporter, 
+							result);
+					if (containsLocalType) 	parsedUnit.bits |= ASTNode.HasAllMethodBodies;
 				} else {
 					// create parsed unit from file
 					IResource file = cu.getResource();
@@ -626,7 +621,7 @@
 					cus[unitsIndex] = cu;
 					parsedUnits[unitsIndex++] = parsedUnit;
 					try {
-						this.lookupEnvironment.buildTypeBindings(parsedUnit);
+						this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
 						if (openable.equals(focusOpenable)) {
 							focusUnit = parsedUnit;
 						}
@@ -658,7 +653,7 @@
 				}
 				if (binaryType != null) {
 					try {
-						BinaryTypeBinding binaryTypeBinding = this.lookupEnvironment.cacheBinaryType(binaryType);
+						BinaryTypeBinding binaryTypeBinding = this.lookupEnvironment.cacheBinaryType(binaryType, null /*no access restriction*/);
 						remember(binaryType, binaryTypeBinding);
 						if (openable.equals(focusOpenable)) {
 							focusBinaryBinding = binaryTypeBinding;
@@ -721,13 +716,16 @@
 		if (focusBinaryBinding == null && focus != null && focus.isBinary()) {
 			char[] fullyQualifiedName = focus.getFullyQualifiedName().toCharArray();
 			focusBinaryBinding = this.lookupEnvironment.getCachedType(CharOperation.splitOn('.', fullyQualifiedName));
-			if (focusBinaryBinding == null) return;
+			if (focusBinaryBinding == null) 
+				return;
 		}
 
 		reportHierarchy(focus, focusUnit, focusBinaryBinding);
 		
 	} catch (ClassCastException e){ // work-around for 1GF5W1S - can happen in case duplicates are fed to the hierarchy with binaries hiding sources
 	} catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
+		if (TypeHierarchy.DEBUG)
+			e.printStackTrace();
 	} finally {
 		reset();
 	}
@@ -741,11 +739,9 @@
 	this.typeBindings = new ReferenceBinding[5];
 }
 
-/**
+/*
  * Set the focus type (ie. the type that this resolver is computing the hierarch for.
  * Returns the binding of this focus type or null if it could not be found.
- * @param compoundName
- * @return
  */
 public ReferenceBinding setFocusType(char[][] compoundName) {
 	if (compoundName == null || this.lookupEnvironment == null) return null;
@@ -769,12 +765,14 @@
 	if (typeBinding == null || subType == null) return false;
 	if (subType == typeBinding) return true;
 	ReferenceBinding superclass = subType.superclass();
+	if (superclass != null) superclass = (ReferenceBinding) superclass.erasure();
 //	if (superclass != null && superclass.id == TypeIds.T_JavaLangObject && subType.isHierarchyInconsistent()) return false;
 	if (this.subTypeOfType(superclass, typeBinding)) return true;
 	ReferenceBinding[] superInterfaces = subType.superInterfaces();
 	if (superInterfaces != null) {
 		for (int i = 0, length = superInterfaces.length; i < length; i++) {
-			if (this.subTypeOfType(superInterfaces[i], typeBinding)) return true;
+			ReferenceBinding superInterface = (ReferenceBinding) superInterfaces[i].erasure();
+			if (this.subTypeOfType(superInterface, typeBinding)) return true;
 		} 
 	}
 	return false;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java
index 9e67421..30760a2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java
@@ -21,7 +21,7 @@
 public class HierarchyType implements IGenericType {
 
 	public IType typeHandle;
-	public boolean isClass;
+	public int kind;
 	public char[] name;
 	public int modifiers;
 	public char[] superclassName;
@@ -29,33 +29,32 @@
 	
 public HierarchyType(
 	IType typeHandle, 
-	boolean isClass, 
+	int kind,
 	char[] name, 
 	int modifiers, 
 	char[] superclassName,
 	char[][] superInterfaceNames) {
 		
 	this.typeHandle = typeHandle;
-	this.isClass = isClass;
+	this.kind = kind;
 	this.name = name;
 	this.modifiers = modifiers;
 	this.superclassName = superclassName;
 	this.superInterfaceNames = superInterfaceNames;
 }
 /**
- * Answer the file name which defines the type.
- *
- * The path part (optional) must be separated from the actual
- * file proper name by a java.io.File.separator.
- *
- * The proper file name includes the suffix extension (e.g. ".java")
- *
- * e.g. "c:/com/ibm/compiler/java/api/Compiler.java" 
+ * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
  */
 public char[] getFileName() {
 	return this.typeHandle.getCompilationUnit().getElementName().toCharArray();
 }
 /**
+ * @see org.eclipse.jdt.internal.compiler.env.IGenericType#getKind()
+ */
+public int getKind() {
+	return this.kind;
+}
+/**
  * Answer an int whose bits are set according the access constants
  * defined by the VM spec.
  */
@@ -69,16 +68,4 @@
 public boolean isBinaryType() {
 	return false;
 }
-/**
- * isClass method comment.
- */
-public boolean isClass() {
-	return this.isClass;
-}
-/**
- * isInterface method comment.
- */
-public boolean isInterface() {
-	return !isClass;
-}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
index 69a85a0..749cf53 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
@@ -20,6 +20,7 @@
 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.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
@@ -34,6 +35,7 @@
 import org.eclipse.jdt.internal.core.search.matching.MatchLocator;
 import org.eclipse.jdt.internal.core.search.matching.SuperTypeReferencePattern;
 import org.eclipse.jdt.internal.core.util.HandleFactory;
+import org.eclipse.jdt.internal.core.util.Util;
 
 public class IndexBasedHierarchyBuilder extends HierarchyBuilder implements SuffixConstants {
 	public static final int MAXTICKS = 800; // heuristic so that there still progress for deep hierachies
@@ -165,7 +167,7 @@
 			}
 		}
 
-		SearchableEnvironment searchableEnvironment = (SearchableEnvironment)project.newSearchableNameEnvironment(unitsToLookInside);
+		SearchableEnvironment searchableEnvironment = project.newSearchableNameEnvironment(unitsToLookInside);
 		this.nameLookup = searchableEnvironment.nameLookup;
 		this.hierarchyResolver = 
 			new HierarchyResolver(searchableEnvironment, project.getOptions(true), this, new DefaultProblemFactory());
@@ -427,7 +429,7 @@
 
 	/* use a special collector to collect paths and queue new subtype names */
 	IndexQueryRequestor searchRequestor = new IndexQueryRequestor() {
-		public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant) {
+		public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant, AccessRestriction access) {
 			SuperTypeReferencePattern record = (SuperTypeReferencePattern)indexRecord;
 			pathRequestor.acceptPath(documentPath, record.enclosingTypeName == IIndexConstants.ONE_ZERO);
 			char[] typeName = record.simpleName;
@@ -446,10 +448,10 @@
 							typeName = documentPath.substring(lastSlash+1, suffix).toCharArray();
 						} else {
 							enclosingTypeName = documentPath.substring(lastSlash+1, lastDollar).toCharArray();
-							typeName = documentPath.substring(lastDollar+1, suffix).toCharArray();
+							typeName = Util.localTypeName(documentPath, lastDollar, suffix).toCharArray();
 						}
 					}
-					binaryType = new HierarchyBinaryType(record.modifiers, record.pkgName, typeName, enclosingTypeName, record.classOrInterface);
+					binaryType = new HierarchyBinaryType(record.modifiers, record.pkgName, typeName, enclosingTypeName, record.typeParameterSignatures, record.classOrInterface);
 					binariesFromIndexMatches.put(documentPath, binaryType);
 				}
 				binaryType.recordSuperType(record.superSimpleName, record.superQualification, record.superClassOrInterface);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java
index 512c05d..b616d8f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java
@@ -92,6 +92,7 @@
 }
 public void pruneDeadBranches() {
 	pruneDeadBranches(getRootClasses());
+	pruneDeadBranches(getRootInterfaces());
 }
 /*
  * Returns whether all subtypes of the given type have been pruned.
@@ -136,6 +137,7 @@
 			if (types != null) types.remove(type);
 		}
 	}
+	this.interfaces.remove(type);
 }
 
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java
index 2489c2e..4c5f51d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java
@@ -820,7 +820,7 @@
 		case IJavaElement.PACKAGE_FRAGMENT_ROOT:
 			return isAffectedByPackageFragmentRoot(delta, element);
 		case IJavaElement.PACKAGE_FRAGMENT:
-			return isAffectedByPackageFragment(delta, element);
+			return isAffectedByPackageFragment(delta, (PackageFragment) element);
 		case IJavaElement.CLASS_FILE:
 		case IJavaElement.COMPILATION_UNIT:
 			return isAffectedByOpenable(delta, element);
@@ -860,7 +860,15 @@
  * Returns true if the given java project delta could affect this type hierarchy
  */
 private boolean isAffectedByJavaProject(IJavaElementDelta delta, IJavaElement element) {
-	switch (delta.getKind()) {
+    int kind = delta.getKind();
+    int flags = delta.getFlags();
+    if ((flags & IJavaElementDelta.F_OPENED) != 0) {
+        kind = IJavaElementDelta.ADDED; // affected in the same way
+    }
+    if ((flags & IJavaElementDelta.F_CLOSED) != 0) {
+        kind = IJavaElementDelta.REMOVED; // affected in the same way
+    }
+	switch (kind) {
 		case IJavaElementDelta.ADDED :
 			try {
 				// if the added project is on the classpath, then the hierarchy has changed
@@ -894,7 +902,7 @@
 /**
  * Returns true if the given package fragment delta could affect this type hierarchy
  */
-private boolean isAffectedByPackageFragment(IJavaElementDelta delta, IJavaElement element) {
+private boolean isAffectedByPackageFragment(IJavaElementDelta delta, PackageFragment element) {
 	switch (delta.getKind()) {
 		case IJavaElementDelta.ADDED :
 			// if the package fragment is in the projects being considered, this could
@@ -971,7 +979,8 @@
 		try {
 			collector.addChange(cu, delta);
 		} catch (JavaModelException e) {
-			e.printStackTrace();
+			if (DEBUG)
+				e.printStackTrace();
 		}
 		if (cu.isWorkingCopy()) {
 			// changes to working copies are batched
@@ -1193,12 +1202,12 @@
  * Returns <code>true</code> if an equivalent package fragment is included in the package
  * region. Package fragments are equivalent if they both have the same name.
  */
-protected boolean packageRegionContainsSamePackageFragment(IJavaElement element) {
+protected boolean packageRegionContainsSamePackageFragment(PackageFragment element) {
 	IJavaElement[] pkgs = this.packageRegion.getElements();
 	for (int i = 0; i < pkgs.length; i++) {
-		if (pkgs[i].getElementName().equals(element.getElementName())) {
+		PackageFragment pkg = (PackageFragment) pkgs[i];
+		if (Util.equalArraysOrNull(pkg.names, element.names))
 			return true;
-		}
 	}
 	return false;
 }
@@ -1437,7 +1446,8 @@
 	try {
 		interfaceNames = type.getSuperInterfaceNames();
 	} catch (JavaModelException e) {
-		e.printStackTrace();
+		if (DEBUG)
+			e.printStackTrace();
 		return false;
 	}
 	for (int i = 0, length = interfaceNames.length; i < length; i++) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/CompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/CompilationUnit.java
index e5eaf1d..a5b0c95 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/CompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/CompilationUnit.java
@@ -39,6 +39,9 @@
 public char[] getContents() {
 	return fContents;
 }
+/**
+ * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
+ */
 public char[] getFileName() {
 	return fFileName;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMBuilder.java
index fdc627e..593a3b4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMBuilder.java
@@ -60,17 +60,17 @@
 	// Creates a new DOMBuilder
 }
 /**
- * @see IDocumentElementRequestor#acceptImport(int declarationStart, int declarationEnd, int[] javaDocPositions, char[] name, int nameStartPosition, boolean onDemand)
+ * @see IDocumentElementRequestor#acceptImport(int, int, int[], char[], int, boolean, int)
  */
 public void acceptImport(int declarationStart, int declarationEnd, int[] javaDocPositions, char[] name, 
-	int nameStart, boolean onDemand) {
+	int nameStart, boolean onDemand, int modifiers) {
 	int[] sourceRange = {declarationStart, declarationEnd};
 	int[] nameRange = {nameStart, declarationEnd - 1};
 	
 	/* See 1FVII1P */
 	String importName = new String(CharOperation.subarray(fDocument, nameRange[0], nameRange[1] + 1));
 
-	fNode= new DOMImport(fDocument, sourceRange, importName, nameRange, onDemand);
+	fNode= new DOMImport(fDocument, sourceRange, importName, nameRange, onDemand, modifiers);
 	addChild(fNode);
 	if (fBuildingSingleMember) {
 		fFinishedSingleMember= true;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMCompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMCompilationUnit.java
index aab682b..3dc3ef9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMCompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMCompilationUnit.java
@@ -108,7 +108,7 @@
 		topLevelType= firstType;
 	}
 	if (topLevelType != null) {
-		return topLevelType.getName() + SUFFIX_STRING_java;
+		return topLevelType.getName() + Util.defaultJavaExtension();
 	} else {
 		return null;
 	}
@@ -159,7 +159,7 @@
 	initalizeHeader();
 }
 /**
- * @see IDOMCompilationUnit@setHeader(String)
+ * @see IDOMCompilationUnit#setHeader(String)
  */
 public void setHeader(String comment) {
 	fHeader= comment;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMField.java
index 6f430e7..b1ec8d3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMField.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMField.java
@@ -91,7 +91,7 @@
  *		next part of this member declaration. If there are no modifiers present
  *		in this node's source code (that is, package default visibility), this array
  *		contains two -1's.
- * @param typeRange- a two element array describing the location of the
+ * @param typeRange - a two element array describing the location of the
  *		typeName in the document - the positions of the first and last characters
  *		of the typeName.
  * @param type - the type of the field, in normalized form, as defined in
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMImport.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMImport.java
index a3e76ef..8250fe0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMImport.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMImport.java
@@ -28,6 +28,7 @@
  */
 // TODO (jerome) - add implementation support for 1.5 features
 class DOMImport extends DOMNode implements IDOMImport {
+	
 	/**
 	 * Indicates if this import is an on demand type import
 	 */
@@ -64,9 +65,10 @@
  *		or -1's if this node does not have a name.
  * @param onDemand - indicates if this import is an on demand style import
  */
-DOMImport(char[] document, int[] sourceRange, String name, int[] nameRange, boolean onDemand) {
+DOMImport(char[] document, int[] sourceRange, String name, int[] nameRange, boolean onDemand, int modifiers) {
 	super(document, sourceRange, name, nameRange);
 	fOnDemand = onDemand;
+	fFlags = modifiers;
 	setMask(MASK_DETAILED_SOURCE_INDEXES, true);
 }
 /**
@@ -83,8 +85,8 @@
  *		<code>null</code> if this node does not have a name
  * @param onDemand - indicates if this import is an on demand style import
  */
-DOMImport(char[] document, int[] sourceRange, String name, boolean onDemand) {
-	this(document, sourceRange, name, new int[] {-1, -1}, onDemand);
+DOMImport(char[] document, int[] sourceRange, String name, boolean onDemand, int modifiers) {
+	this(document, sourceRange, name, new int[] {-1, -1}, onDemand, modifiers);
 	fOnDemand = onDemand;
 	setMask(MASK_DETAILED_SOURCE_INDEXES, false);
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMethod.java
index e78a655..8481784 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMethod.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.jdom;
 
+import org.eclipse.jdt.core.Flags;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.Signature;
@@ -410,7 +411,14 @@
 public String[] getExceptions() {
 	return fExceptions;
 }
-/**
+protected char[] generateFlags() {
+	char[] flags= Flags.toString(getFlags() & ~Flags.AccVarargs).toCharArray();
+	if (flags.length == 0) {
+		return flags;
+	} else {
+		return CharOperation.concat(flags, new char[] {' '});
+	}
+}/**
  * @see IDOMNode#getJavaElement
  */
 public IJavaElement getJavaElement(IJavaElement parent) throws IllegalArgumentException {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMType.java
index bc43ee3..4a398d2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMType.java
@@ -344,7 +344,11 @@
 				buffer.append(fDocument, fInterfacesRange[0], fInterfacesRange[1] + 1 - fInterfacesRange[0]);
 			}
 		} else {
-			buffer.append(fDocument, fNameRange[1] + 1, fOpenBodyRange[0] - fNameRange[1] - 1);
+			if (fImplementsRange[0] < 0) {
+				buffer.append(' ');
+			} else {
+				buffer.append(fDocument, fNameRange[1] + 1, fOpenBodyRange[0] - fNameRange[1] - 1);
+			}
 		}
 	}
 	
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java
index dd8a0df..dea4793 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java
@@ -19,6 +19,7 @@
 import org.eclipse.jdt.internal.compiler.ISourceElementRequestor;
 import org.eclipse.jdt.internal.compiler.SourceElementParser;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
 /**
@@ -43,7 +44,7 @@
 	if (onDemand) {
 		importName+=".*"; //$NON-NLS-1$
 	}
-	fNode= new DOMImport(fDocument, sourceRange, importName, onDemand);
+	fNode= new DOMImport(fDocument, sourceRange, importName, onDemand, modifiers);
 	addChild(fNode);	
 }
 public void acceptPackage(int declarationStart, int declarationEnd, char[] name) {
@@ -67,63 +68,44 @@
 }
 /**
  * Creates a new DOMMethod and inizializes.
- *
- * @param declarationStart - a source position corresponding to the first character 
- *		of this constructor declaration
- * @param modifiers - the modifiers for this constructor converted to a flag
- * @param returnType - the name of the return type
- * @param name - the name of this constructor
- * @param nameStart - a source position corresponding to the first character of the name
- * @param nameEnd - a source position corresponding to the last character of the name
- * @param parameterTypes - a list of parameter type names
- * @param parameterNames - a list of the names of the parameters
- * @param exceptionTypes - a list of the exception types
  */
-protected void enterAbstractMethod(int declarationStart, int modifiers,
-	char[] returnType, char[] name, int nameStart, int nameEnd, char[][] parameterTypes,
-	char[][] parameterNames, char[][] exceptionTypes, boolean isConstructor) {
+protected void enterAbstractMethod(MethodInfo methodInfo) {
 		
-	int[] sourceRange = {declarationStart, -1}; // will be fixed up on exit
-	int[] nameRange = {nameStart, nameEnd};
-	fNode = new DOMMethod(fDocument, sourceRange, CharOperation.charToString(name), nameRange, modifiers, 
-		isConstructor, CharOperation.charToString(returnType),
-		CharOperation.charArrayToStringArray(parameterTypes),
-		CharOperation.charArrayToStringArray(parameterNames), 
-		CharOperation.charArrayToStringArray(exceptionTypes));
+	int[] sourceRange = {methodInfo.declarationStart, -1}; // will be fixed up on exit
+	int[] nameRange = {methodInfo.nameSourceStart, methodInfo.nameSourceEnd};
+	fNode = new DOMMethod(fDocument, sourceRange, CharOperation.charToString(methodInfo.name), nameRange, methodInfo.modifiers, 
+		methodInfo.isConstructor, CharOperation.charToString(methodInfo.returnType),
+		CharOperation.charArrayToStringArray(methodInfo.parameterTypes),
+		CharOperation.charArrayToStringArray(methodInfo.parameterNames), 
+		CharOperation.charArrayToStringArray(methodInfo.exceptionTypes));
 	addChild(fNode);
 	fStack.push(fNode);
+	
+	// type parameters not supported by JDOM
 }
 /**
  */
-public void enterClass(int declarationStart, int modifiers, char[] name, int nameStart, int nameEnd, char[] superclass, char[][] superinterfaces) {
-	enterType(declarationStart, modifiers, name, nameStart, nameEnd, superclass,
-		superinterfaces, true);
-}
-/**
- */
-public void enterConstructor(int declarationStart, int modifiers, char[] name, int nameStart, int nameEnd, char[][] parameterTypes, char[][] parameterNames, char[][] exceptionTypes) {
+public void enterConstructor(MethodInfo methodInfo) {
 	/* see 1FVIIQZ */
-	String nameString = new String(fDocument, nameStart, nameEnd - nameStart);
+	String nameString = new String(fDocument, methodInfo.nameSourceStart, methodInfo.nameSourceEnd - methodInfo.nameSourceStart);
 	int openParenPosition = nameString.indexOf('(');
 	if (openParenPosition > -1)
-		nameEnd = nameStart + openParenPosition - 1;
+		methodInfo.nameSourceEnd = methodInfo.nameSourceStart + openParenPosition - 1;
 
-	enterAbstractMethod(declarationStart, modifiers, 
-		null, name, nameStart, nameEnd, parameterTypes,
-		parameterNames, exceptionTypes,true);
+	enterAbstractMethod(methodInfo);
 }
 /**
  */
-public void enterField(int declarationStart, int modifiers, char[] type, char[] name, int nameStart, int nameEnd) {
+public void enterField(FieldInfo fieldInfo) {
 
-	int[] sourceRange = {declarationStart, -1};
-	int[] nameRange = {nameStart, nameEnd};
+	int[] sourceRange = {fieldInfo.declarationStart, -1};
+	int[] nameRange = {fieldInfo.nameSourceStart, fieldInfo.nameSourceEnd};
 	boolean isSecondary= false;
 	if (fNode instanceof DOMField) {
-		isSecondary = declarationStart == fNode.fSourceRange[0];
+		isSecondary = fieldInfo.declarationStart == fNode.fSourceRange[0];
 	}
-	fNode = new DOMField(fDocument, sourceRange, CharOperation.charToString(name), nameRange, 
-		modifiers, CharOperation.charToString(type), isSecondary);
+	fNode = new DOMField(fDocument, sourceRange, CharOperation.charToString(fieldInfo.name), nameRange, 
+		fieldInfo.modifiers, CharOperation.charToString(fieldInfo.type), isSecondary);
 	addChild(fNode);
 	fStack.push(fNode);
 }
@@ -138,40 +120,24 @@
 }
 /**
  */
-public void enterInterface(int declarationStart, int modifiers, char[] name, int nameStart, int nameEnd, char[][] superinterfaces) {
-	enterType(declarationStart, modifiers, name, nameStart, nameEnd, null,
-		superinterfaces, false);
+public void enterMethod(MethodInfo methodInfo) {
+	enterAbstractMethod(methodInfo);
 }
 /**
  */
-public void enterMethod(int declarationStart, int modifiers, char[] returnType, char[] name, int nameStart, int nameEnd, char[][] parameterTypes, char[][] parameterNames, char[][] exceptionTypes) {
-	enterAbstractMethod(declarationStart, modifiers, 
-		returnType, name, nameStart, nameEnd, parameterTypes,
-		parameterNames, exceptionTypes,false);
-}
-/**
- */
-protected void enterType(int declarationStart, int modifiers, char[] name, 
-	int nameStart, int nameEnd, char[] superclass, char[][] superinterfaces, boolean isClass) {
+public void enterType(TypeInfo typeInfo) {
 	if (fBuildingType) {
-		int[] sourceRange = {declarationStart, -1}; // will be fixed in the exit
-		int[] nameRange = new int[] {nameStart, nameEnd};
-		fNode = new DOMType(fDocument, sourceRange, new String(name), nameRange,
-			modifiers, CharOperation.charArrayToStringArray(superinterfaces), isClass);
+		int[] sourceRange = {typeInfo.declarationStart, -1}; // will be fixed in the exit
+		int[] nameRange = new int[] {typeInfo.nameSourceStart, typeInfo.nameSourceEnd};
+		fNode = new DOMType(fDocument, sourceRange, new String(typeInfo.name), nameRange,
+			typeInfo.modifiers, CharOperation.charArrayToStringArray(typeInfo.superinterfaces), typeInfo.kind == IGenericType.CLASS_DECL); // TODO (jerome) should pass in kind
 		addChild(fNode);
 		fStack.push(fNode);
+		
+		// type parameters not supported by JDOM
 	}
 }
 /**
- * Finishes the configuration of the class DOM object which
- * was created by a previous enterClass call.
- *
- * @see ISourceElementRequestor#exitClass(int)
- */
-public void exitClass(int declarationEnd) {
-	exitType(declarationEnd);
-}
-/**
  * Finishes the configuration of the method DOM object which
  * was created by a previous enterConstructor call.
  *
@@ -191,11 +157,6 @@
 	exitMember(declarationEnd);
 }
 /**
- */
-public void exitInterface(int declarationEnd) {
-	exitType(declarationEnd);
-}
-/**
  * Finishes the configuration of the member.
  *
  * @param declarationEnd - a source position corresponding to the end of the method
@@ -208,7 +169,7 @@
 }
 /**
  */
-public void exitMethod(int declarationEnd) {
+public void exitMethod(int declarationEnd, int defaultValueStart, int defaultValueEnd) {
 	exitMember(declarationEnd);
 }
 /**
@@ -217,7 +178,7 @@
  * @param declarationEnd - a source position corresponding to the end of the class
  *		declaration.  This can include whitespace and comments following the closing bracket.
  */
-protected void exitType(int declarationEnd) {
+public void exitType(int declarationEnd) {
 	exitType(declarationEnd, declarationEnd);
 }
 /**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ASTNodeFinder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ASTNodeFinder.java
index e1476c3..07cf5b7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ASTNodeFinder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ASTNodeFinder.java
@@ -21,7 +21,7 @@
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
-import org.eclipse.jdt.internal.core.JavaElement;
+import org.eclipse.jdt.internal.core.SourceRefElement;
 import org.eclipse.jdt.internal.core.SourceType;
 
 /**
@@ -63,7 +63,7 @@
 		if (typeDecl == null) return null;
 		FieldDeclaration[] fields = typeDecl.fields;
 		if (fields != null) {
-			int occurenceCount = ((JavaElement)initializerHandle).occurrenceCount;
+			int occurenceCount = ((SourceRefElement)initializerHandle).occurrenceCount;
 			for (int i = 0, length = fields.length; i < length; i++) {
 				FieldDeclaration field = fields[i];
 				if (field instanceof Initializer && --occurenceCount == 0) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Annotation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Annotation.java
new file mode 100644
index 0000000..f90424d
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Annotation.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IAnnotation;
+import org.eclipse.jdt.core.util.IAnnotationComponent;
+import org.eclipse.jdt.core.util.IConstantPool;
+import org.eclipse.jdt.core.util.IConstantPoolConstant;
+import org.eclipse.jdt.core.util.IConstantPoolEntry;
+
+/**
+ * Default implementation of IAnnotation
+ */
+public class Annotation extends ClassFileStruct implements IAnnotation {
+
+	private static final IAnnotationComponent[] NO_ENTRIES = new IAnnotationComponent[0];
+	
+	private int typeIndex;
+	private char[] typeName;
+	private int componentsNumber;
+	private IAnnotationComponent[] components;
+	private int readOffset;
+	
+	/**
+	 * Constructor for Annotation.
+	 * 
+	 * @param classFileBytes
+	 * @param constantPool
+	 * @param offset
+	 * @throws ClassFormatException
+	 */
+	public Annotation(
+			byte[] classFileBytes,
+			IConstantPool constantPool,
+			int offset) throws ClassFormatException {
+		
+		final int index = u2At(classFileBytes, 0, offset);
+		this.typeIndex = index;
+		if (index != 0) {
+			IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(index);
+			if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Utf8) {
+				throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
+			}
+			this.typeName = constantPoolEntry.getUtf8Value();
+		} else {
+			throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
+		}
+		final int length = u2At(classFileBytes, 2, offset);
+		this.componentsNumber = length;
+		this.readOffset = 4;
+		if (length != 0) {
+			this.components = new IAnnotationComponent[length];
+			for (int i = 0; i < length; i++) {
+				AnnotationComponent component = new AnnotationComponent(classFileBytes, constantPool, offset + readOffset);
+				this.components[i] = component;
+				this.readOffset += component.sizeInBytes();
+			}
+		} else {
+			this.components = NO_ENTRIES;
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotation#getTypeIndex()
+	 */
+	public int getTypeIndex() {
+		return this.typeIndex;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotation#getComponentsNumber()
+	 */
+	public int getComponentsNumber() {
+		return this.componentsNumber;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotation#getComponents()
+	 */
+	public IAnnotationComponent[] getComponents() {
+		return this.components;
+	}
+	
+	int sizeInBytes() {
+		return this.readOffset;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotation#getTypeName()
+	 */
+	public char[] getTypeName() {
+		return this.typeName;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationComponent.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationComponent.java
new file mode 100644
index 0000000..10a4710
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationComponent.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IAnnotationComponent;
+import org.eclipse.jdt.core.util.IAnnotationComponentValue;
+import org.eclipse.jdt.core.util.IConstantPool;
+import org.eclipse.jdt.core.util.IConstantPoolConstant;
+import org.eclipse.jdt.core.util.IConstantPoolEntry;
+
+/**
+ * Default implementation of IAnnotationComponent
+ */
+public class AnnotationComponent extends ClassFileStruct implements IAnnotationComponent {
+	
+	private int componentNameIndex;
+	private char[] componentName;
+	private IAnnotationComponentValue componentValue;
+	private int readOffset;
+	
+	public AnnotationComponent(
+			byte[] classFileBytes,
+			IConstantPool constantPool,
+			int offset) throws ClassFormatException {
+		final int nameIndex = u2At(classFileBytes, 0, offset);
+		this.componentNameIndex = nameIndex;
+		if (nameIndex != 0) {
+			IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(nameIndex);
+			if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Utf8) {
+				throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
+			}
+			this.componentName = constantPoolEntry.getUtf8Value();
+		}
+		this.readOffset = 2;
+		AnnotationComponentValue value = new AnnotationComponentValue(classFileBytes, constantPool, offset + readOffset);
+		this.componentValue = value;
+		this.readOffset += value.sizeInBytes();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationComponent#getComponentNameIndex()
+	 */
+	public int getComponentNameIndex() {
+		return this.componentNameIndex;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationComponent#getComponentName()
+	 */
+	public char[] getComponentName() {
+		return this.componentName;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationComponent#getComponentValue()
+	 */
+	public IAnnotationComponentValue getComponentValue() {
+		return this.componentValue;
+	}
+	
+	int sizeInBytes() {
+		return this.readOffset;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationComponentValue.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationComponentValue.java
new file mode 100644
index 0000000..4fa7b11
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationComponentValue.java
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IAnnotation;
+import org.eclipse.jdt.core.util.IAnnotationComponentValue;
+import org.eclipse.jdt.core.util.IConstantPool;
+import org.eclipse.jdt.core.util.IConstantPoolConstant;
+import org.eclipse.jdt.core.util.IConstantPoolEntry;
+
+/**
+ * Default implementation of IAnnotationComponent
+ */
+public class AnnotationComponentValue extends ClassFileStruct implements IAnnotationComponentValue {
+	private static final IAnnotationComponentValue[] NO_VALUES = new AnnotationComponentValue[0];
+	
+	private IAnnotationComponentValue[] annotationComponentValues;
+	private IAnnotation annotationValue;
+	private IConstantPoolEntry classInfo;
+	private int classFileInfoIndex;
+	private IConstantPoolEntry constantValue;
+	private int constantValueIndex;
+	private int enumConstantTypeNameIndex;
+	private int enumConstantNameIndex;
+	private char[] enumConstantTypeName;
+	private char[] enumConstantName;
+
+	private int readOffset;
+	private int tag;
+	private int valuesNumber;
+	
+	public AnnotationComponentValue(
+			byte[] classFileBytes,
+			IConstantPool constantPool,
+			int offset) throws ClassFormatException {
+		final int t = u1At(classFileBytes, 0, offset);
+		this.tag = t;
+		this.readOffset = 1;
+		switch(t) {
+			case 'B' :
+			case 'C' :
+			case 'D' :
+			case 'F' :
+			case 'I' :
+			case 'J' :
+			case 'S' :
+			case 'Z' :
+			case 's' :
+				final int constantIndex = this.u2At(classFileBytes, this.readOffset, offset);
+				this.constantValueIndex = constantIndex;
+				if (constantIndex != 0) {
+					IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(constantIndex);
+					switch(constantPoolEntry.getKind()) {
+						case IConstantPoolConstant.CONSTANT_Long :
+						case IConstantPoolConstant.CONSTANT_Float :
+						case IConstantPoolConstant.CONSTANT_Double :
+						case IConstantPoolConstant.CONSTANT_Integer :
+						case IConstantPoolConstant.CONSTANT_Utf8 :
+							break;
+						default :
+							throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
+					}
+					this.constantValue = constantPoolEntry;
+				}
+				this.readOffset += 2;
+				break;
+			case 'e' :
+				int index = this.u2At(classFileBytes, this.readOffset, offset);
+				this.enumConstantTypeNameIndex = index;
+				if (index != 0) {
+					IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(index);
+					if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Utf8) {
+						throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
+					}
+					this.enumConstantTypeName = constantPoolEntry.getUtf8Value();
+				}
+				this.readOffset += 2;
+				index = this.u2At(classFileBytes, this.readOffset, offset);
+				this.enumConstantNameIndex = index;
+				if (index != 0) {
+					IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(index);
+					if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Utf8) {
+						throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
+					}
+					this.enumConstantName = constantPoolEntry.getUtf8Value();
+				}
+				this.readOffset += 2;
+				break;
+			case 'c' :
+				final int classFileIndex = this.u2At(classFileBytes, this.readOffset, offset);
+				this.classFileInfoIndex = classFileIndex;
+				if (classFileIndex != 0) {
+					IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(classFileIndex);
+					if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Utf8) {
+						throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
+					}
+					this.classInfo = constantPoolEntry;
+				}
+				this.readOffset += 2;
+				break;
+			case '@' :
+				Annotation annotation = new Annotation(classFileBytes, constantPool, this.readOffset + offset);
+				this.annotationValue = annotation;
+				this.readOffset += annotation.sizeInBytes();
+				break;
+			case '[' :
+				final int numberOfValues = this.u2At(classFileBytes, this.readOffset, offset);
+				this.valuesNumber = numberOfValues;
+				if (numberOfValues != 0) {
+					this.readOffset += 2;
+					this.annotationComponentValues = new IAnnotationComponentValue[numberOfValues];
+					for (int i = 0; i < numberOfValues; i++) {
+						AnnotationComponentValue value = new AnnotationComponentValue(classFileBytes, constantPool, offset + readOffset);
+						this.annotationComponentValues[i] = value;
+						this.readOffset += value.sizeInBytes();
+					}
+				} else {
+					this.annotationComponentValues = NO_VALUES;
+				}
+				break;
+		}
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationComponentValue#getAnnotationComponentValues()
+	 */
+	public IAnnotationComponentValue[] getAnnotationComponentValues() {
+		return this.annotationComponentValues;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationComponentValue#getAnnotationValue()
+	 */
+	public IAnnotation getAnnotationValue() {
+		return this.annotationValue;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationComponentValue#getAnnotationValue()
+	 */
+	public IAnnotation getAttributeValue() {
+		return this.annotationValue;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationComponentValue#getClassInfo()
+	 */
+	public IConstantPoolEntry getClassInfo() {
+		return this.classInfo;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationComponentValue#getClassInfoIndex()
+	 */
+	public int getClassInfoIndex() {
+		return this.classFileInfoIndex;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationComponentValue#getConstantValue()
+	 */
+	public IConstantPoolEntry getConstantValue() {
+		return this.constantValue;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationComponentValue#getConstantValueIndex()
+	 */
+	public int getConstantValueIndex() {
+		return this.constantValueIndex;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationComponentValue#getEnumConstantName()
+	 */
+	public char[] getEnumConstantName() {
+		return this.enumConstantName;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationComponentValue#getEnumConstantNameIndex()
+	 */
+	public int getEnumConstantNameIndex() {
+		return this.enumConstantNameIndex;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationComponentValue#getEnumConstantTypeName()
+	 */
+	public char[] getEnumConstantTypeName() {
+		return this.enumConstantTypeName;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationComponentValue#getEnumConstantTypeNameIndex()
+	 */
+	public int getEnumConstantTypeNameIndex() {
+		return enumConstantTypeNameIndex;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationComponentValue#getTag()
+	 */
+	public int getTag() {
+		return this.tag;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationComponentValue#getValuesNumber()
+	 */
+	public int getValuesNumber() {
+		return this.valuesNumber;
+	}
+	
+	int sizeInBytes() {
+		return this.readOffset;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationDefaultAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationDefaultAttribute.java
new file mode 100644
index 0000000..f8f5ac1
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationDefaultAttribute.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IAnnotationComponentValue;
+import org.eclipse.jdt.core.util.IAnnotationDefaultAttribute;
+import org.eclipse.jdt.core.util.IConstantPool;
+
+/**
+ * Default implementation of AnnotationDefaultAttribute.
+ * 
+ * @since 3.0
+ */
+public class AnnotationDefaultAttribute extends ClassFileAttribute
+		implements
+			IAnnotationDefaultAttribute {
+
+	private IAnnotationComponentValue memberValue;
+	
+	/**
+	 * Constructor for AnnotationDefaultAttribute.
+	 * @param classFileBytes
+	 * @param constantPool
+	 * @param offset
+	 * @throws ClassFormatException
+	 */
+	public AnnotationDefaultAttribute(
+			byte[] classFileBytes,
+			IConstantPool constantPool,
+			int offset)
+			throws ClassFormatException {
+		super(classFileBytes, constantPool, offset);
+		this.memberValue = new AnnotationComponentValue(classFileBytes, constantPool, offset + 6);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IAnnotationDefaultAttribute#getMemberValue()
+	 */
+	public IAnnotationComponentValue getMemberValue() {
+		return this.memberValue;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java
index 27e104b..5a4e660 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java
@@ -28,30 +28,30 @@
 
 public class ClassFileReader extends ClassFileStruct implements IClassFileReader {
 	private static final IFieldInfo[] NO_FIELD_INFOS = new IFieldInfo[0];
-	private static final IMethodInfo[] NO_METHOD_INFOS = new IMethodInfo[0];
 	private static final int[] NO_INTERFACE_INDEXES = new int[0];
 	private static final char[][] NO_INTERFACES_NAMES = CharOperation.NO_CHAR_CHAR;
+	private static final IMethodInfo[] NO_METHOD_INFOS = new IMethodInfo[0];
+	private int accessFlags;
+	private IClassFileAttribute[] attributes;
+	private int attributesCount;
+	private char[] className;
+	private int classNameIndex;
 
 	private IConstantPool constantPool;
-	private int magicNumber;
-	private int accessFlags;
-	private char[] className;
-	private char[] superclassName;
-	private int interfacesCount;
-	private char[][] interfaceNames;
-	private int[] interfaceIndexes;
-	private int fieldsCount;
 	private IFieldInfo[] fields;
-	private int methodsCount;
-	private IMethodInfo[] methods;
+	private int fieldsCount;
 	private IInnerClassesAttribute innerClassesAttribute;
-	private ISourceAttribute sourceFileAttribute;
-	private int classNameIndex;
+	private int[] interfaceIndexes;
+	private char[][] interfaceNames;
+	private int interfacesCount;
+	private int magicNumber;
 	private int majorVersion;
+	private IMethodInfo[] methods;
+	private int methodsCount;
 	private int minorVersion;
+	private ISourceAttribute sourceFileAttribute;
+	private char[] superclassName;
 	private int superclassNameIndex;
-	private int attributesCount;
-	private IClassFileAttribute[] attributes;
 	
 	/**
 	 * Constructor for ClassFileReader.
@@ -74,6 +74,10 @@
 		int[] constantPoolOffsets;
 		try {
 			this.magicNumber = (int) u4At(classFileBytes, 0, 0);
+			if (this.magicNumber != 0xCAFEBABE) {
+				throw new ClassFormatException(ClassFormatException.INVALID_MAGIC_NUMBER);
+			}
+			
 			int readOffset = 10;
 			this.minorVersion = this.u2At(classFileBytes, 4, 0);
 			this.majorVersion = this.u2At(classFileBytes, 6, 0);
@@ -156,7 +160,7 @@
 			if (superclassNameIndex != 0) {
 				this.superclassName = getConstantClassNameAt(classFileBytes, constantPoolOffsets, this.superclassNameIndex);
 			}
-
+	
 			// Read the interfaces, use exception handlers to catch bad format
 			this.interfacesCount = u2At(classFileBytes, readOffset, 0);
 			readOffset += 2;
@@ -231,7 +235,7 @@
 			// Read the attributes
 			this.attributesCount = u2At(classFileBytes, readOffset, 0);
 			readOffset += 2;
-
+	
 			int attributesIndex = 0;
 			this.attributes = ClassFileAttribute.NO_ATTRIBUTES;
 			if (this.attributesCount != 0) {
@@ -240,16 +244,20 @@
 					for (int i = 0; i < attributesCount; i++) {
 						int utf8Offset = constantPoolOffsets[u2At(classFileBytes, readOffset, 0)];
 						char[] attributeName = utf8At(classFileBytes, utf8Offset + 3, 0, u2At(classFileBytes, utf8Offset + 1, 0));
-						if (equals(attributeName, IAttributeNamesConstants.DEPRECATED)) {
-							this.attributes[attributesIndex++] = new ClassFileAttribute(classFileBytes, this.constantPool, readOffset);
-						} else if (equals(attributeName, IAttributeNamesConstants.INNER_CLASSES)) {
+						if (equals(attributeName, IAttributeNamesConstants.INNER_CLASSES)) {
 							this.innerClassesAttribute = new InnerClassesAttribute(classFileBytes, this.constantPool, readOffset);
 							this.attributes[attributesIndex++] = this.innerClassesAttribute;
 						} else if (equals(attributeName, IAttributeNamesConstants.SOURCE)) {
-								this.sourceFileAttribute = new SourceFileAttribute(classFileBytes, this.constantPool, readOffset);
-								this.attributes[attributesIndex++] = this.sourceFileAttribute;
-						} else if (equals(attributeName, IAttributeNamesConstants.SYNTHETIC)) {
-								this.attributes[attributesIndex++] = new ClassFileAttribute(classFileBytes, this.constantPool, readOffset);
+							this.sourceFileAttribute = new SourceFileAttribute(classFileBytes, this.constantPool, readOffset);
+							this.attributes[attributesIndex++] = this.sourceFileAttribute;
+						} else if (equals(attributeName, IAttributeNamesConstants.ENCLOSING_METHOD)) {
+							this.attributes[attributesIndex++] = new EnclosingMethodAttribute(classFileBytes, this.constantPool, readOffset);
+						} else if (equals(attributeName, IAttributeNamesConstants.SIGNATURE)) {
+							this.attributes[attributesIndex++] = new SignatureAttribute(classFileBytes, this.constantPool, readOffset);
+						} else if (equals(attributeName, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS)) {
+							this.attributes[attributesIndex++] = new RuntimeVisibleAnnotationsAttribute(classFileBytes, this.constantPool, readOffset);
+						} else if (equals(attributeName, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS)) {
+							this.attributes[attributesIndex++] = new RuntimeInvisibleAnnotationsAttribute(classFileBytes, this.constantPool, readOffset);
 						} else {
 							this.attributes[attributesIndex++] = new ClassFileAttribute(classFileBytes, this.constantPool, readOffset);
 						}
@@ -277,12 +285,37 @@
 	public int getAccessFlags() {
 		return this.accessFlags;
 	}
+	/**
+	 * @see IClassFileReader#getAttributeCount()
+	 */
+	public int getAttributeCount() {
+		return this.attributesCount;
+	}
 
 	/**
-	 * @see IClassFileReader#getSourceFileAttribute()
+	 * @see IClassFileReader#getAttributes()
 	 */
-	public ISourceAttribute getSourceFileAttribute() {
-		return this.sourceFileAttribute;
+	public IClassFileAttribute[] getAttributes() {
+		return this.attributes;
+	}
+
+	/**
+	 * @see IClassFileReader#getClassIndex()
+	 */
+	public int getClassIndex() {
+		return this.classNameIndex;
+	}
+
+	/**
+	 * @see IClassFileReader#getClassName()
+	 */
+	public char[] getClassName() {
+		return this.className;
+	}
+
+	private char[] getConstantClassNameAt(byte[] classFileBytes, int[] constantPoolOffsets, int constantPoolIndex) {
+		int utf8Offset = constantPoolOffsets[u2At(classFileBytes, constantPoolOffsets[constantPoolIndex] + 1, 0)];
+		return utf8At(classFileBytes, utf8Offset + 3, 0, u2At(classFileBytes, utf8Offset + 1, 0));
 	}
 
 	/**
@@ -291,7 +324,6 @@
 	public IConstantPool getConstantPool() {
 		return this.constantPool;
 	}
-
 	/**
 	 * @see IClassFileReader#getFieldInfos()
 	 */
@@ -300,6 +332,13 @@
 	}
 
 	/**
+	 * @see IClassFileReader#getFieldsCount()
+	 */
+	public int getFieldsCount() {
+		return this.fieldsCount;
+	}
+
+	/**
 	 * @see IClassFileReader#getInnerClassesAttribute()
 	 */
 	public IInnerClassesAttribute getInnerClassesAttribute() {
@@ -307,6 +346,13 @@
 	}
 
 	/**
+	 * @see IClassFileReader#getInterfaceIndexes()
+	 */
+	public int[] getInterfaceIndexes() {
+		return this.interfaceIndexes;
+	}
+
+	/**
 	 * @see IClassFileReader#getInterfaceNames()
 	 */
 	public char[][] getInterfaceNames() {
@@ -314,6 +360,20 @@
 	}
 
 	/**
+	 * @see IClassFileReader#getMagic()
+	 */
+	public int getMagic() {
+		return this.magicNumber;
+	}
+
+	/**
+	 * @see IClassFileReader#getMajorVersion()
+	 */
+	public int getMajorVersion() {
+		return this.majorVersion;
+	}
+
+	/**
 	 * @see IClassFileReader#getMethodInfos()
 	 */
 	public IMethodInfo[] getMethodInfos() {
@@ -321,10 +381,31 @@
 	}
 
 	/**
-	 * @see IClassFileReader#getClassName()
+	 * @see IClassFileReader#getMethodsCount()
 	 */
-	public char[] getClassName() {
-		return this.className;
+	public int getMethodsCount() {
+		return this.methodsCount;
+	}
+
+	/**
+	 * @see IClassFileReader#getMinorVersion()
+	 */
+	public int getMinorVersion() {
+		return this.minorVersion;
+	}
+
+	/**
+	 * @see IClassFileReader#getSourceFileAttribute()
+	 */
+	public ISourceAttribute getSourceFileAttribute() {
+		return this.sourceFileAttribute;
+	}
+
+	/**
+	 * @see IClassFileReader#getSuperclassIndex()
+	 */
+	public int getSuperclassIndex() {
+		return this.superclassNameIndex;
 	}
 
 	/**
@@ -346,79 +427,4 @@
 	public boolean isInterface() {
 		return (getAccessFlags() & IModifierConstants.ACC_INTERFACE) != 0;
 	}
-
-	/**
-	 * @see IClassFileReader#getMajorVersion()
-	 */
-	public int getMajorVersion() {
-		return this.majorVersion;
-	}
-
-	/**
-	 * @see IClassFileReader#getMinorVersion()
-	 */
-	public int getMinorVersion() {
-		return this.minorVersion;
-	}
-
-	private char[] getConstantClassNameAt(byte[] classFileBytes, int[] constantPoolOffsets, int constantPoolIndex) {
-		int utf8Offset = constantPoolOffsets[u2At(classFileBytes, constantPoolOffsets[constantPoolIndex] + 1, 0)];
-		return utf8At(classFileBytes, utf8Offset + 3, 0, u2At(classFileBytes, utf8Offset + 1, 0));
-	}
-	/**
-	 * @see IClassFileReader#getAttributeCount()
-	 */
-	public int getAttributeCount() {
-		return this.attributesCount;
-	}
-
-	/**
-	 * @see IClassFileReader#getClassIndex()
-	 */
-	public int getClassIndex() {
-		return this.classNameIndex;
-	}
-
-	/**
-	 * @see IClassFileReader#getInterfaceIndexes()
-	 */
-	public int[] getInterfaceIndexes() {
-		return this.interfaceIndexes;
-	}
-
-	/**
-	 * @see IClassFileReader#getSuperclassIndex()
-	 */
-	public int getSuperclassIndex() {
-		return this.superclassNameIndex;
-	}
-
-	/**
-	 * @see IClassFileReader#getMagic()
-	 */
-	public int getMagic() {
-		return this.magicNumber;
-	}
-
-	/**
-	 * @see IClassFileReader#getFieldsCount()
-	 */
-	public int getFieldsCount() {
-		return this.fieldsCount;
-	}
-
-	/**
-	 * @see IClassFileReader#getMethodsCount()
-	 */
-	public int getMethodsCount() {
-		return this.methodsCount;
-	}
-
-	/**
-	 * @see IClassFileReader#getAttributes()
-	 */
-	public IClassFileAttribute[] getAttributes() {
-		return this.attributes;
-	}
-
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java
index e712318..549a190 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java
@@ -28,19 +28,19 @@
  */
 public class CodeAttribute extends ClassFileAttribute implements ICodeAttribute {
 	private static final IExceptionTableEntry[] NO_EXCEPTION_TABLE = new IExceptionTableEntry[0];
-	private int maxLocals;
-	private int maxStack;
+	private IClassFileAttribute[] attributes;
+	private int attributesCount;
+	private byte[] bytecodes;
+	private byte[] classFileBytes;
+	private long codeLength;
+	private int codeOffset;
+	private IConstantPool constantPool;
+	private IExceptionTableEntry[] exceptionTableEntries;
+	private int exceptionTableLength;
 	private ILineNumberAttribute lineNumberAttribute;
 	private ILocalVariableAttribute localVariableAttribute;
-	private IExceptionTableEntry[] exceptionTableEntries;
-	private long codeLength;
-	private int attributesCount;
-	private int exceptionTableLength;
-	private byte[] bytecodes;
-	private IConstantPool constantPool;
-	private int codeOffset;
-	private byte[] classFileBytes;
-	private IClassFileAttribute[] attributes;
+	private int maxLocals;
+	private int maxStack;
 	
 	CodeAttribute(byte[] classFileBytes, IConstantPool constantPool, int offset) throws ClassFormatException {
 		super(classFileBytes, constantPool, offset);
@@ -80,6 +80,8 @@
 			} else if (equals(attributeName, IAttributeNamesConstants.LOCAL_VARIABLE)) {
 				this.localVariableAttribute = new LocalVariableAttribute(classFileBytes, constantPool, offset + readOffset);
 				this.attributes[attributesIndex++] = this.localVariableAttribute;
+			} else if (equals(attributeName, IAttributeNamesConstants.LOCAL_VARIABLE_TYPE_TABLE)) {
+				this.attributes[attributesIndex++] = new LocalVariableTypeAttribute(classFileBytes, constantPool, offset + readOffset);
 			} else {
 				this.attributes[attributesIndex++] = new ClassFileAttribute(classFileBytes, constantPool, offset + readOffset);
 			}
@@ -87,19 +89,49 @@
 		}
 		
 	}
-	
 	/**
-	 * @see ICodeAttribute#getMaxLocals()
+	 * @see ICodeAttribute#getAttributes()
 	 */
-	public int getMaxLocals() {
-		return this.maxLocals;
+	public IClassFileAttribute[] getAttributes() {
+		return this.attributes;
 	}
 
 	/**
-	 * @see ICodeAttribute#getMaxStack()
+	 * @see ICodeAttribute#getAttributesCount()
 	 */
-	public int getMaxStack() {
-		return this.maxStack;
+	public int getAttributesCount() {
+		return this.attributesCount;
+	}
+
+	/**
+	 * @see ICodeAttribute#getBytecodes()
+	 */
+	public byte[] getBytecodes() {
+		if (this.bytecodes == null) {
+			System.arraycopy(this.classFileBytes, this.codeOffset, (this.bytecodes = new byte[(int) this.codeLength]), 0, (int) this.codeLength); 
+		}
+		return this.bytecodes;
+	}
+
+	/**
+	 * @see ICodeAttribute#getCodeLength()
+	 */
+	public long getCodeLength() {
+		return this.codeLength;
+	}
+
+	/**
+	 * @see ICodeAttribute#getExceptionTable()
+	 */
+	public IExceptionTableEntry[] getExceptionTable() {
+		return this.exceptionTableEntries;
+	}
+
+	/**
+	 * @see ICodeAttribute#getExceptionTableLength()
+	 */
+	public int getExceptionTableLength() {
+		return this.exceptionTableLength;
 	}
 
 	/**
@@ -115,18 +147,22 @@
 	public ILocalVariableAttribute getLocalVariableAttribute() {
 		return this.localVariableAttribute;
 	}
-
+	
 	/**
-	 * @see ICodeAttribute#getBytecodes()
+	 * @see ICodeAttribute#getMaxLocals()
 	 */
-	public byte[] getBytecodes() {
-		if (this.bytecodes == null) {
-			System.arraycopy(this.classFileBytes, this.codeOffset, (this.bytecodes = new byte[(int) this.codeLength]), 0, (int) this.codeLength); 
-		}
-		return this.bytecodes;
+	public int getMaxLocals() {
+		return this.maxLocals;
 	}
 
 	/**
+	 * @see ICodeAttribute#getMaxStack()
+	 */
+	public int getMaxStack() {
+		return this.maxStack;
+	}
+	
+	/**
 	 * @see ICodeAttribute#traverse(IBytecodeVisitor visitor)
 	 */
 	public void traverse(IBytecodeVisitor visitor) throws ClassFormatException {
@@ -213,7 +249,8 @@
 					constantPoolEntry = this.constantPool.decodeEntry(index);
 					if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Float
 						&& constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Integer
-						&& constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_String) {
+						&& constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_String
+						&& constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Class) {
 							throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
 					}
 					visitor._ldc(pc - this.codeOffset, index, constantPoolEntry);
@@ -1126,46 +1163,4 @@
 			}
 		}
 	}
-
-	/**
-	 * @see ICodeAttribute#getExceptionTable()
-	 */
-	public IExceptionTableEntry[] getExceptionTable() {
-		return this.exceptionTableEntries;
-	}
-
-	/**
-	 * @see ICodeAttribute#getAttributesCount()
-	 */
-	public int getAttributesCount() {
-		return this.attributesCount;
-	}
-
-	/**
-	 * @see ICodeAttribute#getCodeLength()
-	 */
-	public long getCodeLength() {
-		return this.codeLength;
-	}
-
-	/**
-	 * @see ICodeAttribute#getExceptionTableLength()
-	 */
-	public int getExceptionTableLength() {
-		return this.exceptionTableLength;
-	}
-
-	/**
-	 * @see IClassFileAttribute#getAttributeName()
-	 */
-	public char[] getAttributeName() {
-		return IAttributeNamesConstants.CODE;
-	}
-	/**
-	 * @see ICodeAttribute#getAttributes()
-	 */
-	public IClassFileAttribute[] getAttributes() {
-		return this.attributes;
-	}
-
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeSnippetParsingUtil.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeSnippetParsingUtil.java
index 8842843..badf6d1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeSnippetParsingUtil.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeSnippetParsingUtil.java
@@ -112,7 +112,7 @@
 		
 		//fill the methods bodies in order for the code to be generated
 		//real parse of the method....
-		parser.scanner.setSource(source);
+		parser.scanner.setSource(compilationResult);
 		org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
 		if (types != null) {
 			for (int i = types.length; --i >= 0;) {
@@ -188,7 +188,7 @@
 		constructorDeclaration.bodyStart = offset;
 		constructorDeclaration.bodyEnd = offset + length - 1;
 		
-		parser.scanner.setSource(source);
+		parser.scanner.setSource(compilationResult);
 		parser.scanner.resetTo(offset, offset + length);
 		parser.parse(constructorDeclaration, compilationUnitDeclaration, true);
 		
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderParser.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderParser.java
index c926580..2932b90 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderParser.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderParser.java
@@ -41,8 +41,9 @@
 	// for backward compatibility with 2.1 DOM 
 	public void checkComment() {
 
-		if (this.currentElement != null && this.scanner.commentPtr >= 0) {
-			flushCommentsDefinedPriorTo(this.endStatementPosition); // discard obsolete comments
+		// discard obsolete comments while inside methods or fields initializer (see bug 74369)
+		if (!(this.diet && this.dietInt==0) && this.scanner.commentPtr >= 0) {
+			flushCommentsDefinedPriorTo(this.endStatementPosition);
 		}
 		boolean deprecated = false;
 		boolean checkDeprecated = false;
@@ -64,6 +65,8 @@
 			checkDeprecated = true;
 			int commentSourceEnd = this.scanner.commentStops[lastCommentIndex] - 1; //stop is one over
 			
+			// do not report problem before last parsed comment while recovering code...
+			this.javadocParser.reportProblems = this.currentElement == null || commentSourceEnd > this.lastJavadocEnd;
 			deprecated = this.javadocParser.checkDeprecation(commentSourceStart, commentSourceEnd);
 			this.javadoc = this.javadocParser.docComment;
 			break nextComment;
@@ -78,7 +81,6 @@
 				this.modifiersSourceStart = -this.modifiersSourceStart;
 			}
 		}
-
 	}
 
 	/* (non-Javadoc)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java
index 2b92bd3..c9e91fa 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java
@@ -22,73 +22,72 @@
 	private int constantPoolCount;
 	private int[] constantPoolOffset;
 	private byte[] classFileBytes;
-	private ConstantPoolEntry constantPoolEntry;
 	
 	ConstantPool(byte[] reference, int[] constantPoolOffset) {
 		this.constantPoolCount = constantPoolOffset.length;
 		this.constantPoolOffset = constantPoolOffset;
 		this.classFileBytes = reference;
-		this.constantPoolEntry = new ConstantPoolEntry();
 	}
 
 	/**
 	 * @see IConstantPool#decodeEntry(int)
 	 */
 	public IConstantPoolEntry decodeEntry(int index) {
-		this.constantPoolEntry.reset();
+		ConstantPoolEntry constantPoolEntry = new ConstantPoolEntry();
+		constantPoolEntry.reset();
 		int kind = getEntryKind(index);
-		this.constantPoolEntry.setKind(kind);
+		constantPoolEntry.setKind(kind);
 		switch(kind) {
 			case IConstantPoolConstant.CONSTANT_Class :
-				this.constantPoolEntry.setClassInfoNameIndex(u2At(this.classFileBytes,  1, this.constantPoolOffset[index]));
-				this.constantPoolEntry.setClassInfoName(getUtf8ValueAt(this.constantPoolEntry.getClassInfoNameIndex()));
+				constantPoolEntry.setClassInfoNameIndex(u2At(this.classFileBytes,  1, this.constantPoolOffset[index]));
+				constantPoolEntry.setClassInfoName(getUtf8ValueAt(constantPoolEntry.getClassInfoNameIndex()));
 				break;
 			case IConstantPoolConstant.CONSTANT_Double :
-				this.constantPoolEntry.setDoubleValue(doubleAt(classFileBytes, 1, this.constantPoolOffset[index]));
+				constantPoolEntry.setDoubleValue(doubleAt(classFileBytes, 1, this.constantPoolOffset[index]));
 				break;
 			case IConstantPoolConstant.CONSTANT_Fieldref :
-				this.constantPoolEntry.setClassIndex(u2At(this.classFileBytes,  1, this.constantPoolOffset[index]));
-				int declaringClassIndex = u2At(this.classFileBytes,  1, this.constantPoolOffset[this.constantPoolEntry.getClassIndex()]);
-				this.constantPoolEntry.setClassName(getUtf8ValueAt(declaringClassIndex));
-				this.constantPoolEntry.setNameAndTypeIndex(u2At(this.classFileBytes,  3, this.constantPoolOffset[index]));
-				int fieldNameIndex = u2At(this.classFileBytes,  1, this.constantPoolOffset[this.constantPoolEntry.getNameAndTypeIndex()]);
-				int fieldDescriptorIndex = u2At(this.classFileBytes,  3, this.constantPoolOffset[this.constantPoolEntry.getNameAndTypeIndex()]);
-				this.constantPoolEntry.setFieldName(getUtf8ValueAt(fieldNameIndex));
-				this.constantPoolEntry.setFieldDescriptor(getUtf8ValueAt(fieldDescriptorIndex));
+				constantPoolEntry.setClassIndex(u2At(this.classFileBytes,  1, this.constantPoolOffset[index]));
+				int declaringClassIndex = u2At(this.classFileBytes,  1, this.constantPoolOffset[constantPoolEntry.getClassIndex()]);
+				constantPoolEntry.setClassName(getUtf8ValueAt(declaringClassIndex));
+				constantPoolEntry.setNameAndTypeIndex(u2At(this.classFileBytes,  3, this.constantPoolOffset[index]));
+				int fieldNameIndex = u2At(this.classFileBytes,  1, this.constantPoolOffset[constantPoolEntry.getNameAndTypeIndex()]);
+				int fieldDescriptorIndex = u2At(this.classFileBytes,  3, this.constantPoolOffset[constantPoolEntry.getNameAndTypeIndex()]);
+				constantPoolEntry.setFieldName(getUtf8ValueAt(fieldNameIndex));
+				constantPoolEntry.setFieldDescriptor(getUtf8ValueAt(fieldDescriptorIndex));
 				break;
 			case IConstantPoolConstant.CONSTANT_Methodref :
 			case IConstantPoolConstant.CONSTANT_InterfaceMethodref :
-				this.constantPoolEntry.setClassIndex(u2At(this.classFileBytes,  1, this.constantPoolOffset[index]));
-				declaringClassIndex = u2At(this.classFileBytes,  1, this.constantPoolOffset[this.constantPoolEntry.getClassIndex()]);
-				this.constantPoolEntry.setClassName(getUtf8ValueAt(declaringClassIndex));
-				this.constantPoolEntry.setNameAndTypeIndex(u2At(this.classFileBytes,  3, this.constantPoolOffset[index]));
-				int methodNameIndex = u2At(this.classFileBytes,  1, this.constantPoolOffset[this.constantPoolEntry.getNameAndTypeIndex()]);
-				int methodDescriptorIndex = u2At(this.classFileBytes,  3, this.constantPoolOffset[this.constantPoolEntry.getNameAndTypeIndex()]);
-				this.constantPoolEntry.setMethodName(getUtf8ValueAt(methodNameIndex));
-				this.constantPoolEntry.setMethodDescriptor(getUtf8ValueAt(methodDescriptorIndex));
+				constantPoolEntry.setClassIndex(u2At(this.classFileBytes,  1, this.constantPoolOffset[index]));
+				declaringClassIndex = u2At(this.classFileBytes,  1, this.constantPoolOffset[constantPoolEntry.getClassIndex()]);
+				constantPoolEntry.setClassName(getUtf8ValueAt(declaringClassIndex));
+				constantPoolEntry.setNameAndTypeIndex(u2At(this.classFileBytes,  3, this.constantPoolOffset[index]));
+				int methodNameIndex = u2At(this.classFileBytes,  1, this.constantPoolOffset[constantPoolEntry.getNameAndTypeIndex()]);
+				int methodDescriptorIndex = u2At(this.classFileBytes,  3, this.constantPoolOffset[constantPoolEntry.getNameAndTypeIndex()]);
+				constantPoolEntry.setMethodName(getUtf8ValueAt(methodNameIndex));
+				constantPoolEntry.setMethodDescriptor(getUtf8ValueAt(methodDescriptorIndex));
 				break;
 			case IConstantPoolConstant.CONSTANT_Float :
-				this.constantPoolEntry.setFloatValue(floatAt(classFileBytes, 1, this.constantPoolOffset[index]));
+				constantPoolEntry.setFloatValue(floatAt(classFileBytes, 1, this.constantPoolOffset[index]));
 				break;
 			case IConstantPoolConstant.CONSTANT_Integer :
-				this.constantPoolEntry.setIntegerValue(i4At(classFileBytes, 1, this.constantPoolOffset[index]));
+				constantPoolEntry.setIntegerValue(i4At(classFileBytes, 1, this.constantPoolOffset[index]));
 				break;
 			case IConstantPoolConstant.CONSTANT_Long :
-				this.constantPoolEntry.setLongValue(i8At(classFileBytes, 1, this.constantPoolOffset[index]));
+				constantPoolEntry.setLongValue(i8At(classFileBytes, 1, this.constantPoolOffset[index]));
 				break;
 			case IConstantPoolConstant.CONSTANT_NameAndType :
-				this.constantPoolEntry.setNameAndTypeNameIndex(u2At(this.classFileBytes,  1, this.constantPoolOffset[index]));
-				this.constantPoolEntry.setNameAndTypeDescriptorIndex(u2At(this.classFileBytes,  3, this.constantPoolOffset[index]));
+				constantPoolEntry.setNameAndTypeNameIndex(u2At(this.classFileBytes,  1, this.constantPoolOffset[index]));
+				constantPoolEntry.setNameAndTypeDescriptorIndex(u2At(this.classFileBytes,  3, this.constantPoolOffset[index]));
 				break;
 			case IConstantPoolConstant.CONSTANT_String :
-				this.constantPoolEntry.setStringIndex(u2At(this.classFileBytes,  1, this.constantPoolOffset[index]));
-				this.constantPoolEntry.setStringValue(getUtf8ValueAt(this.constantPoolEntry.getStringIndex()));
+				constantPoolEntry.setStringIndex(u2At(this.classFileBytes,  1, this.constantPoolOffset[index]));
+				constantPoolEntry.setStringValue(getUtf8ValueAt(constantPoolEntry.getStringIndex()));
 				break;
 			case IConstantPoolConstant.CONSTANT_Utf8 :
-				this.constantPoolEntry.setUtf8Length(u2At(this.classFileBytes,  1, this.constantPoolOffset[index]));
-				this.constantPoolEntry.setUtf8Value(getUtf8ValueAt(index));
+				constantPoolEntry.setUtf8Length(u2At(this.classFileBytes,  1, this.constantPoolOffset[index]));
+				constantPoolEntry.setUtf8Value(getUtf8ValueAt(index));
 		}
-		return this.constantPoolEntry;
+		return constantPoolEntry;
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantValueAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantValueAttribute.java
index d8688ef..014d4a2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantValueAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantValueAttribute.java
@@ -11,7 +11,6 @@
 package org.eclipse.jdt.internal.core.util;
 
 import org.eclipse.jdt.core.util.ClassFormatException;
-import org.eclipse.jdt.core.util.IAttributeNamesConstants;
 import org.eclipse.jdt.core.util.IConstantPool;
 import org.eclipse.jdt.core.util.IConstantPoolEntry;
 import org.eclipse.jdt.core.util.IConstantValueAttribute;
@@ -24,19 +23,19 @@
 	implements IConstantValueAttribute {
 	
 	private int constantValueIndex;
-	private IConstantPool constantPool;
+	private IConstantPoolEntry constantPoolEntry;
 
 	
 	ConstantValueAttribute(byte[] classFileBytes, IConstantPool constantPool, int offset) throws ClassFormatException {
 		super(classFileBytes, constantPool, offset);
 		this.constantValueIndex = u2At(classFileBytes, 6, offset);
-		this.constantPool = constantPool;	
+		this.constantPoolEntry = constantPool.decodeEntry(this.constantValueIndex);
 	}
 	/**
 	 * @see IConstantValueAttribute#getConstantValue()
 	 */
 	public IConstantPoolEntry getConstantValue() {
-		return this.constantPool.decodeEntry(this.constantValueIndex);
+		return this.constantPoolEntry;
 	}
 
 	/**
@@ -45,11 +44,4 @@
 	public int getConstantValueIndex() {
 		return this.constantValueIndex;
 	}
-
-	/**
-	 * @see org.eclipse.jdt.core.util.IClassFileAttribute#getAttributeName()
-	 */
-	public char[] getAttributeName() {
-		return IAttributeNamesConstants.CONSTANT_VALUE;
-	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java
index f9fa129..232f4fc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java
@@ -39,7 +39,7 @@
 		this.buffer = buffer;
 		this.lineSeparator = lineSeparator;
 		this.tabNumber = tabNumber + 1;
-		this.digitNumberForPC = (int) (Math.log(codeLength - 1) / Math.log(10));
+		this.digitNumberForPC = Long.toString(codeLength).length();
 	}
 	/**
 	 * @see IBytecodeVisitor#_aaload(int)
@@ -51,15 +51,15 @@
 	}
 	private void dumpPcNumber(int pc) {
 		writeTabs();
-		int digitForPC = 0;
+		int digitForPC = 1;
 		if (pc != 0) {
-			digitForPC = (int) (Math.log(pc) / Math.log(10));
+			digitForPC = Integer.toString(pc).length();
 		}
 		for (int i = 0, max = this.digitNumberForPC - digitForPC; i < max; i++) {
 			buffer.append(' ');
 		}
 		buffer.append(pc);
-		buffer.append(Util.bind("disassembler.identation")); //$NON-NLS-1$
+		buffer.append(Util.bind("disassembler.indentation")); //$NON-NLS-1$		
 	}
 
 	/**
@@ -2272,13 +2272,13 @@
 
 	private void writeTabs() {
 		for (int i = 0, max = this.tabNumber; i < max; i++) {
-			this.buffer.append(Util.bind("disassembler.identation")); //$NON-NLS-1$
+			this.buffer.append(Util.bind("disassembler.indentation")); //$NON-NLS-1$
 		}
 	}	
 
 	private void writeExtraTabs(int extraTabs) {
 		for (int i = 0, max = this.tabNumber + extraTabs; i < max; i++) {
-			this.buffer.append(Util.bind("disassembler.identation")); //$NON-NLS-1$
+			this.buffer.append(Util.bind("disassembler.indentation")); //$NON-NLS-1$
 		}
 	}	
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
index a571781..72e2eaa 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
@@ -275,15 +275,6 @@
 			}
 			buffer.append("bridge"); //$NON-NLS-1$
 		}		
-		if ((accessFlags & IModifierConstants.ACC_VARARGS) != 0) {
-			if (!firstModifier) {
-				buffer.append(Util.bind("disassembler.space")); //$NON-NLS-1$
-			}
-			if (firstModifier) {
-				firstModifier = false;
-			}
-			buffer.append("varargs"); //$NON-NLS-1$
-		}
 		if (!firstModifier) {
 			buffer.append(Util.bind("disassembler.space")); //$NON-NLS-1$
 		}
@@ -318,23 +309,13 @@
 			}
 			buffer.append("public"); //$NON-NLS-1$
 		}
-		if ((accessFlags & IModifierConstants.ACC_ANNOTATION) != 0) {
-			if (!firstModifier) {
-				buffer.append(Util.bind("disassembler.space")); //$NON-NLS-1$
-			}
-			if (firstModifier) {
-				firstModifier = false;
-			}
-			buffer.append("@"); //$NON-NLS-1$
-		}
 		if (!firstModifier) {
 			buffer.append(Util.bind("disassembler.space")); //$NON-NLS-1$
 		}
 	}
 
-	private String decodeStringValue(String s) {
+	private String decodeStringValue(char[] chars) {
 		StringBuffer buffer = new StringBuffer();
-		char[] chars = s.toCharArray();
 		for (int i = 0, max = chars.length; i < max; i++) {
 			char c = chars[i];
 			switch(c) {
@@ -393,6 +374,10 @@
 		return buffer.toString();
 	}
 
+	private String decodeStringValue(String s) {
+		return decodeStringValue(s.toCharArray());
+	}
+
 	/**
 	 * @see org.eclipse.jdt.core.util.ClassFileBytesDisassembler#disassemble(byte[], java.lang.String)
 	 */
@@ -407,374 +392,139 @@
 		return disassemble(new ClassFileReader(classFileBytes, IClassFileReader.ALL), lineSeparator, mode);
 	}
 
-	/**
-	 * @see #disassemble(org.eclipse.jdt.core.util.IClassFileReader, java.lang.String, int)
-	 */
-	public String disassemble(IClassFileReader classFileReader, String lineSeparator) {
-		return disassemble(classFileReader, lineSeparator, ClassFileBytesDisassembler.DEFAULT);
-	}
-
-	/**
-	 * Answers back the disassembled string of the IClassFileReader according to the
-	 * mode.
-	 * This is an output quite similar to the javap tool.
-	 * 
-	 * @param classFileReader The classFileReader to be disassembled
-	 * @param lineSeparator the line separator to use.
-	 * @param mode the mode used to disassemble the IClassFileReader
-	 * 
-	 * @return the disassembled string of the IClassFileReader according to the mode
-	 */
-	public String disassemble(IClassFileReader classFileReader, String lineSeparator, int mode) {
-		if (classFileReader == null) return EMPTY_OUTPUT;
-		StringBuffer buffer = new StringBuffer();
-
-		ISourceAttribute sourceAttribute = classFileReader.getSourceFileAttribute();
-		IClassFileAttribute classFileAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.SIGNATURE);
-		ISignatureAttribute signatureAttribute = (ISignatureAttribute) classFileAttribute;
-		final int accesssFlags = classFileReader.getAccessFlags();
-		if (mode == ClassFileBytesDisassembler.DETAILED) {
-			int minorVersion = classFileReader.getMinorVersion();
-			int majorVersion = classFileReader.getMajorVersion();
-			buffer.append(Util.bind("disassembler.begincommentline")); //$NON-NLS-1$
-			if (sourceAttribute != null) {
-				buffer.append(Util.bind("disassembler.sourceattributeheader")); //$NON-NLS-1$
-				buffer.append(sourceAttribute.getSourceFileName());
-			}
-			String versionNumber = VERSION_UNKNOWN;//$NON-NLS-1$
-			if (minorVersion == 3 && majorVersion == 45) {
-				versionNumber = JavaCore.VERSION_1_1;
-			} else if (minorVersion == 0 && majorVersion == 46) {
-				versionNumber = JavaCore.VERSION_1_2;
-			} else if (minorVersion == 0 && majorVersion == 47) {
-				versionNumber = JavaCore.VERSION_1_3;
-			} else if (minorVersion == 0 && majorVersion == 48) {
-				versionNumber = JavaCore.VERSION_1_4;
-			} else if (minorVersion == 0 && majorVersion == 49) {
-				versionNumber = JavaCore.VERSION_1_5;
-			}
-			buffer.append(
-				Util.bind("classfileformat.versiondetails",//$NON-NLS-1$
-				new String[] {
-					versionNumber,
-					Integer.toString(majorVersion),
-					Integer.toString(minorVersion),
-					((accesssFlags & IModifierConstants.ACC_SUPER) != 0
-							? Util.bind("classfileformat.superflagisset")//$NON-NLS-1$
-							: Util.bind("classfileformat.superflagisnotset"))//$NON-NLS-1$
-					+ (isDeprecated(classFileReader) ? ", deprecated" : EMPTY_OUTPUT)//$NON-NLS-1$
-				}));
-			writeNewLine(buffer, lineSeparator, 0);
-			if (signatureAttribute != null) {
-				buffer
-					.append(Util.bind("disassembler.begincommentline"))	 //$NON-NLS-1$
-					.append(Util.bind("disassembler.signatureattributeheader")) //$NON-NLS-1$
-					.append(signatureAttribute.getSignature());
-				writeNewLine(buffer, lineSeparator, 0);
-			}
-		}
-		char[] className = classFileReader.getClassName();
-		if (className == null) {
-			// incomplete initialization. We cannot go further.
-			return buffer.toString();
-		}
-		
-		IInnerClassesAttribute innerClassesAttribute = classFileReader.getInnerClassesAttribute();
-		
-		if (innerClassesAttribute != null) {
-			// search the right entry
-			IInnerClassesAttributeEntry[] entries = innerClassesAttribute.getInnerClassAttributesEntries();
-			for (int i = 0, max = entries.length; i < max ; i++) {
-				IInnerClassesAttributeEntry entry = entries[i];
-				char[] innerClassName = entry.getInnerClassName();
-				if (innerClassName != null) {
-					if (CharOperation.equals(classFileReader.getClassName(), innerClassName)) {
-						decodeModifiersForInnerClasses(buffer, entry.getAccessFlags());
-					}
-				}
-			}
-		} else {
-			decodeModifiersForType(buffer, accesssFlags);
-			if (isSynthetic(classFileReader)) {
-				buffer.append("synthetic"); //$NON-NLS-1$
-				buffer.append(Util.bind("disassembler.space")); //$NON-NLS-1$
-			}
-		}
-		if ((accesssFlags & IModifierConstants.ACC_ENUM) != 0) {
-			buffer.append("enum "); //$NON-NLS-1$
-		} else if (classFileReader.isClass()) {
-			buffer.append("class "); //$NON-NLS-1$
-		} else {
-			buffer.append("interface "); //$NON-NLS-1$
-		}
-		CharOperation.replace(className, '/', '.');
-		buffer.append(className);
-		
-		char[] superclassName = classFileReader.getSuperclassName();
-		if (superclassName != null) {
-			buffer.append(" extends "); //$NON-NLS-1$
-			CharOperation.replace(superclassName, '/', '.');
-			buffer.append(superclassName);
-		}
-		char[][] superclassInterfaces = classFileReader.getInterfaceNames();
-		int length = superclassInterfaces.length;
-		if (length != 0) {
-			buffer.append(" implements "); //$NON-NLS-1$
-			for (int i = 0; i < length - 1; i++) {
-				char[] superinterface = superclassInterfaces[i];
-				CharOperation.replace(superinterface, '/', '.');
-				buffer
-					.append(superinterface)
-					.append(Util.bind("disassembler.comma"))//$NON-NLS-1$
-					.append(Util.bind("disassembler.space")); //$NON-NLS-1$
-			}
-			char[] superinterface = superclassInterfaces[length - 1];
-			CharOperation.replace(superinterface, '/', '.');
-			buffer.append(superinterface);
-		}
-		buffer.append(Util.bind("disassembler.opentypedeclaration")); //$NON-NLS-1$
-		disassembleTypeMembers(classFileReader, buffer, lineSeparator, 1, mode);
-		if (mode == ClassFileBytesDisassembler.DETAILED) {
-			IClassFileAttribute[] attributes = classFileReader.getAttributes();
-			length = attributes.length;
-			IEnclosingMethodAttribute enclosingMethodAttribute = getEnclosingMethodAttribute(classFileReader);
-			int remainingAttributesLength = length;
-			if (innerClassesAttribute != null) {
-				remainingAttributesLength--;
-			}
-			if (enclosingMethodAttribute != null) {
-				remainingAttributesLength--;
-			}
-			if (sourceAttribute != null) {
-				remainingAttributesLength--;
-			}
-			if (signatureAttribute != null) {
-				remainingAttributesLength--;
-			}
-			if (innerClassesAttribute != null || enclosingMethodAttribute != null || remainingAttributesLength != 0) {
-				writeNewLine(buffer, lineSeparator, 0);
-			}
-			if (innerClassesAttribute != null) {
-				disassemble(innerClassesAttribute, buffer, lineSeparator, 1);
-			}
-			if (enclosingMethodAttribute != null) {
-				disassemble(enclosingMethodAttribute, buffer, lineSeparator, 0);
-			}
-			if (length != 0) {
-				for (int i = 0; i < length; i++) {
-					IClassFileAttribute attribute = attributes[i];
-					if (attribute != innerClassesAttribute
-						&& attribute != sourceAttribute
-						&& attribute != signatureAttribute
-						&& attribute != enclosingMethodAttribute
-						&& !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED)
-						&& !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) {
-						disassemble(attribute, buffer, lineSeparator, 0);
-					}
-				}
-			}		
-		}
-		writeNewLine(buffer, lineSeparator, 0);
-		buffer.append(Util.bind("disassembler.closetypedeclaration")); //$NON-NLS-1$
-		return buffer.toString();
-	}
-	
-	private void disassemble(IInnerClassesAttribute innerClassesAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
-		writeNewLine(buffer, lineSeparator, tabNumber);
-		buffer.append(Util.bind("disassembler.innerattributesheader")); //$NON-NLS-1$
+	private void disassemble(IAnnotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber) {
 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
-		IInnerClassesAttributeEntry[] innerClassesAttributeEntries = innerClassesAttribute.getInnerClassAttributesEntries();
-		int length = innerClassesAttributeEntries.length;
-		int innerClassNameIndex, outerClassNameIndex, innerNameIndex, accessFlags;
-		IInnerClassesAttributeEntry innerClassesAttributeEntry;
-		for (int i = 0; i < length - 1; i++) {
-			innerClassesAttributeEntry = innerClassesAttributeEntries[i];
-			innerClassNameIndex = innerClassesAttributeEntry.getInnerClassNameIndex();
-			outerClassNameIndex = innerClassesAttributeEntry.getOuterClassNameIndex();
-			innerNameIndex = innerClassesAttributeEntry.getInnerNameIndex();
-			accessFlags = innerClassesAttributeEntry.getAccessFlags();
-			buffer
-				.append(Util.bind("disassembler.openinnerclassentry")) //$NON-NLS-1$
-				.append(Util.bind("disassembler.inner_class_info_name")) //$NON-NLS-1$
-				.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
-				.append(innerClassNameIndex);
-			if (innerClassNameIndex != 0) {
-				buffer
-					.append(Util.bind("disassembler.space")) //$NON-NLS-1$
-					.append(innerClassesAttributeEntry.getInnerClassName());
+		final int typeIndex = annotation.getTypeIndex();
+		final char[] typeName = CharOperation.replaceOnCopy(annotation.getTypeName(), '/', '.');
+		buffer.append(
+			Util.bind("disassembler.annotationentrystart", //$NON-NLS-1$
+			new String[] {
+				Integer.toString(typeIndex),
+				new String(Signature.toCharArray(typeName))
 			}
-			buffer
-				.append(Util.bind("disassembler.comma")) //$NON-NLS-1$
-				.append(Util.bind("disassembler.space")) //$NON-NLS-1$
-				.append(Util.bind("disassembler.outer_class_info_name")) //$NON-NLS-1$
-				.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
-				.append(outerClassNameIndex);
-			if (outerClassNameIndex != 0) {
-				buffer	
-					.append(Util.bind("disassembler.space")) //$NON-NLS-1$
-					.append(innerClassesAttributeEntry.getOuterClassName());
+		));
+		final IAnnotationComponent[] components = annotation.getComponents();
+		for (int i = 0, max = components.length; i < max; i++) {
+			disassemble(components[i], buffer, lineSeparator, tabNumber + 1);
+		}
+		writeNewLine(buffer, lineSeparator, tabNumber + 1);
+		buffer.append(Util.bind("disassembler.annotationentryend")); //$NON-NLS-1$
+	}
+
+	private void disassemble(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber) {
+		writeNewLine(buffer, lineSeparator, tabNumber + 1);
+		buffer.append(
+			Util.bind("disassembler.annotationcomponent", //$NON-NLS-1$
+			new String[] {
+				Integer.toString(annotationComponent.getComponentNameIndex()),
+				new String(annotationComponent.getComponentName())
 			}
-			writeNewLine(buffer, lineSeparator, tabNumber);
-			dumpTab(tabNumber, buffer);
-			buffer.append(Util.bind("disassembler.space")); //$NON-NLS-1$
-			buffer
-				.append(Util.bind("disassembler.inner_name")) //$NON-NLS-1$
-				.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
-				.append(innerNameIndex);
-			if (innerNameIndex != 0) {
-				buffer
-					.append(Util.bind("disassembler.space")) //$NON-NLS-1$
-					.append(innerClassesAttributeEntry.getInnerName());
-			}
-			buffer
-				.append(Util.bind("disassembler.comma")) //$NON-NLS-1$
-				.append(Util.bind("disassembler.space")) //$NON-NLS-1$
-				.append(Util.bind("disassembler.inner_accessflags")) //$NON-NLS-1$
-				.append(accessFlags)
-				.append(Util.bind("disassembler.space")); //$NON-NLS-1$
-			decodeModifiersForInnerClasses(buffer, accessFlags);
-			buffer
-				.append(Util.bind("disassembler.closeinnerclassentry")) //$NON-NLS-1$
-				.append(Util.bind("disassembler.comma")); //$NON-NLS-1$
-			writeNewLine(buffer, lineSeparator, tabNumber + 1);
+		));
+		disassemble(annotationComponent.getComponentValue(), buffer, lineSeparator, tabNumber + 1);
+	}
+
+	private void disassemble(IAnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber) {
+		switch(annotationComponentValue.getTag()) {
+			case IAnnotationComponentValue.BYTE_TAG:
+			case IAnnotationComponentValue.CHAR_TAG:
+			case IAnnotationComponentValue.DOUBLE_TAG:
+			case IAnnotationComponentValue.FLOAT_TAG:
+			case IAnnotationComponentValue.INTEGER_TAG:
+			case IAnnotationComponentValue.LONG_TAG:
+			case IAnnotationComponentValue.SHORT_TAG:
+			case IAnnotationComponentValue.BOOLEAN_TAG:
+			case IAnnotationComponentValue.STRING_TAG:
+				IConstantPoolEntry constantPoolEntry = annotationComponentValue.getConstantValue();
+				String value = null;
+				switch(constantPoolEntry.getKind()) {
+					case IConstantPoolConstant.CONSTANT_Long :
+						value = constantPoolEntry.getLongValue() + "L"; //$NON-NLS-1$
+						break;
+					case IConstantPoolConstant.CONSTANT_Float :
+						value = constantPoolEntry.getFloatValue() + "f"; //$NON-NLS-1$
+						break;
+					case IConstantPoolConstant.CONSTANT_Double :
+						value = Double.toString(constantPoolEntry.getDoubleValue());
+						break;
+					case IConstantPoolConstant.CONSTANT_Integer:
+						switch(annotationComponentValue.getTag()) {
+							case IAnnotationComponentValue.CHAR_TAG :
+								value = "'" + (char) constantPoolEntry.getIntegerValue() + "'"; //$NON-NLS-1$//$NON-NLS-2$
+								break;
+							case IAnnotationComponentValue.BOOLEAN_TAG :
+								value = constantPoolEntry.getIntegerValue() == 1 ? "true" : "false";//$NON-NLS-1$//$NON-NLS-2$
+								break;
+							case IAnnotationComponentValue.BYTE_TAG :
+								value = "(byte) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
+								break;
+							case IAnnotationComponentValue.SHORT_TAG :
+								value =  "(short) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
+								break;
+							case IAnnotationComponentValue.INTEGER_TAG :
+								value =  "(int) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
+						}
+						break;
+					case IConstantPoolConstant.CONSTANT_Utf8:
+						value = "\"" + decodeStringValue(constantPoolEntry.getUtf8Value()) + "\"";//$NON-NLS-1$//$NON-NLS-2$
+				}
+				buffer.append(Util.bind("disassembler.annotationdefaultvalue", value)); //$NON-NLS-1$
+				break;
+			case IAnnotationComponentValue.ENUM_TAG:
+				final int enumConstantTypeNameIndex = annotationComponentValue.getEnumConstantTypeNameIndex();
+				final char[] typeName = CharOperation.replaceOnCopy(annotationComponentValue.getEnumConstantTypeName(), '/', '.');
+				final int enumConstantNameIndex = annotationComponentValue.getEnumConstantNameIndex();
+				final char[] constantName = annotationComponentValue.getEnumConstantName();
+				buffer.append(Util.bind("disassembler.annotationenumvalue", //$NON-NLS-1$
+					new String[] {
+						Integer.toString(enumConstantTypeNameIndex),
+						Integer.toString(enumConstantNameIndex),
+						new String(Signature.toCharArray(typeName)),
+						new String(constantName)
+				})); //$NON-NLS-1$
+				break;
+			case IAnnotationComponentValue.CLASS_TAG:
+				final int classIndex = annotationComponentValue.getClassInfoIndex();
+				constantPoolEntry = annotationComponentValue.getClassInfo();
+				final char[] className = CharOperation.replaceOnCopy(constantPoolEntry.getUtf8Value(), '/', '.');
+				buffer.append(Util.bind("disassembler.annotationclassvalue", //$NON-NLS-1$
+					new String[] {
+						Integer.toString(classIndex),
+						new String(Signature.toCharArray(className))
+				})); //$NON-NLS-1$
+				break;
+			case IAnnotationComponentValue.ANNOTATION_TAG:
+				buffer.append(Util.bind("disassembler.annotationannotationvalue")); //$NON-NLS-1$
+				IAnnotation annotation = annotationComponentValue.getAnnotationValue();
+				disassemble(annotation, buffer, lineSeparator, tabNumber + 1);
+				break;
+			case IAnnotationComponentValue.ARRAY_TAG:
+				buffer.append(Util.bind("disassembler.annotationarrayvaluestart")); //$NON-NLS-1$
+				final IAnnotationComponentValue[] annotationComponentValues = annotationComponentValue.getAnnotationComponentValues();
+				for (int i = 0, max = annotationComponentValues.length; i < max; i++) {
+					writeNewLine(buffer, lineSeparator, tabNumber + 1);
+					disassemble(annotationComponentValues[i], buffer, lineSeparator, tabNumber + 1);
+				}
+				writeNewLine(buffer, lineSeparator, tabNumber + 1);
+				buffer.append(Util.bind("disassembler.annotationarrayvalueend")); //$NON-NLS-1$
 		}
-		// last entry
-		innerClassesAttributeEntry = innerClassesAttributeEntries[length - 1];
-		innerClassNameIndex = innerClassesAttributeEntry.getInnerClassNameIndex();
-		outerClassNameIndex = innerClassesAttributeEntry.getOuterClassNameIndex();
-		innerNameIndex = innerClassesAttributeEntry.getInnerNameIndex();
-		accessFlags = innerClassesAttributeEntry.getAccessFlags();
-		buffer
-			.append(Util.bind("disassembler.openinnerclassentry")) //$NON-NLS-1$
-			.append(Util.bind("disassembler.inner_class_info_name")) //$NON-NLS-1$
-			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
-			.append(innerClassNameIndex);
-		if (innerClassNameIndex != 0) {
-			buffer
-				.append(Util.bind("disassembler.space")) //$NON-NLS-1$
-				.append(innerClassesAttributeEntry.getInnerClassName());
-		}
-		buffer
-			.append(Util.bind("disassembler.comma")) //$NON-NLS-1$
-			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
-			.append(Util.bind("disassembler.outer_class_info_name")) //$NON-NLS-1$
-			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
-			.append(outerClassNameIndex);
-		if (outerClassNameIndex != 0) {
-			buffer	
-				.append(Util.bind("disassembler.space")) //$NON-NLS-1$
-				.append(innerClassesAttributeEntry.getOuterClassName());
-		}
-		writeNewLine(buffer, lineSeparator, tabNumber);
-		dumpTab(tabNumber, buffer);
-		buffer.append(Util.bind("disassembler.space")); //$NON-NLS-1$
-		buffer
-			.append(Util.bind("disassembler.inner_name")) //$NON-NLS-1$
-			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
-			.append(innerNameIndex);
-		if (innerNameIndex != 0) {
-			buffer
-				.append(Util.bind("disassembler.space")) //$NON-NLS-1$
-				.append(innerClassesAttributeEntry.getInnerName());
-		}
-		buffer
-			.append(Util.bind("disassembler.comma")) //$NON-NLS-1$
-			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
-			.append(Util.bind("disassembler.inner_accessflags")) //$NON-NLS-1$
-			.append(accessFlags)
-			.append(Util.bind("disassembler.space")); //$NON-NLS-1$
-		decodeModifiersForInnerClasses(buffer, accessFlags);
-		buffer.append(Util.bind("disassembler.closeinnerclassentry")); //$NON-NLS-1$
 	}
 	
-	/**
-	 * Disassemble a field info
-	 */
-	private void disassemble(IFieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
-		writeNewLine(buffer, lineSeparator, tabNumber);
-		char[] fieldDescriptor = fieldInfo.getDescriptor();
-		IClassFileAttribute classFileAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.SIGNATURE);
-		ISignatureAttribute signatureAttribute = (ISignatureAttribute) classFileAttribute;
-		if (mode == DETAILED) {
-			buffer
-				.append(Util.bind("disassembler.begincommentline")) //$NON-NLS-1$
-				.append(Util.bind("classfileformat.fieldddescriptor")) //$NON-NLS-1$
-				.append(Util.bind("classfileformat.fielddescriptorindex")) //$NON-NLS-1$
-				.append(fieldInfo.getDescriptorIndex())
-				.append(Util.bind("disassembler.space")) //$NON-NLS-1$
-				.append(fieldDescriptor);
-			if (fieldInfo.isDeprecated()) {
-				buffer.append(Util.bind("disassembler.deprecated"));//$NON-NLS-1$
-			}
-			writeNewLine(buffer, lineSeparator, tabNumber);
-			if (signatureAttribute != null) {
-				buffer
-					.append(Util.bind("disassembler.begincommentline"))	 //$NON-NLS-1$
-					.append(Util.bind("disassembler.signatureattributeheader")) //$NON-NLS-1$
-					.append(signatureAttribute.getSignature());
-				writeNewLine(buffer, lineSeparator, tabNumber);
-			}
-		}
-		decodeModifiersForField(buffer, fieldInfo.getAccessFlags());
-		if (fieldInfo.isSynthetic()) {
-			buffer.append("synthetic"); //$NON-NLS-1$
-			buffer.append(Util.bind("disassembler.space")); //$NON-NLS-1$
-		}
-		buffer.append(getSignatureForField(fieldDescriptor));
-		buffer.append(Util.bind("disassembler.space")); //$NON-NLS-1$
-		buffer.append(new String(fieldInfo.getName()));
-		IConstantValueAttribute constantValueAttribute = fieldInfo.getConstantValueAttribute();
-		if (constantValueAttribute != null) {
-			buffer.append(Util.bind("disassembler.fieldhasconstant")); //$NON-NLS-1$
-			IConstantPoolEntry constantPoolEntry = constantValueAttribute.getConstantValue();
-			switch(constantPoolEntry.getKind()) {
-				case IConstantPoolConstant.CONSTANT_Long :
-					buffer.append(constantPoolEntry.getLongValue() + "L"); //$NON-NLS-1$
-					break;
-				case IConstantPoolConstant.CONSTANT_Float :
-					buffer.append(constantPoolEntry.getFloatValue() + "f"); //$NON-NLS-1$
-					break;
-				case IConstantPoolConstant.CONSTANT_Double :
-					buffer.append(constantPoolEntry.getDoubleValue());
-					break;
-				case IConstantPoolConstant.CONSTANT_Integer:
-					switch(fieldDescriptor[0]) {
-						case 'C' :
-							buffer.append("'" + (char) constantPoolEntry.getIntegerValue() + "'"); //$NON-NLS-1$//$NON-NLS-2$
-							break;
-						case 'Z' :
-							buffer.append(constantPoolEntry.getIntegerValue() == 1 ? "true" : "false");//$NON-NLS-1$//$NON-NLS-2$
-							break;
-						case 'B' :
-							buffer.append(constantPoolEntry.getIntegerValue());
-							break;
-						case 'S' :
-							buffer.append(constantPoolEntry.getIntegerValue());
-							break;
-						case 'I' :
-							buffer.append(constantPoolEntry.getIntegerValue());
-					}
-					break;
-				case IConstantPoolConstant.CONSTANT_String:
-					buffer.append("\"" + decodeStringValue(constantPoolEntry.getStringValue()) + "\"" );//$NON-NLS-1$//$NON-NLS-2$
-			}
-		}
-		buffer.append(Util.bind("disassembler.endoffieldheader")); //$NON-NLS-1$
-		if (mode == DETAILED) {
-			IClassFileAttribute[] attributes = fieldInfo.getAttributes();
-			int length = attributes.length;
-			if (length != 0) {
-				for (int i = 0; i < length; i++) {
-					IClassFileAttribute attribute = attributes[i];
-					if (attribute != constantValueAttribute
-						&& attribute != signatureAttribute
-						&& !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED)
-						&& !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) {
-						disassemble(attribute, buffer, lineSeparator, tabNumber);
-					}
-				}
-			}
-		}
+	private void disassemble(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+		writeNewLine(buffer, lineSeparator, tabNumber + 1);
+		buffer.append(Util.bind("disassembler.annotationdefaultheader")); //$NON-NLS-1$
+		IAnnotationComponentValue componentValue = annotationDefaultAttribute.getMemberValue();
+		writeNewLine(buffer, lineSeparator, tabNumber + 2);
+		disassemble(componentValue, buffer, lineSeparator, tabNumber + 1);
+	}
+
+	private void disassemble(IClassFileAttribute classFileAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+		writeNewLine(buffer, lineSeparator, tabNumber + 1);
+		buffer.append(Util.bind("disassembler.genericattributeheader")); //$NON-NLS-1$
+		buffer
+			.append(Util.bind("disassembler.genericattributename")) //$NON-NLS-1$
+			.append(classFileAttribute.getAttributeName())
+			.append(Util.bind("disassembler.genericattributelength")) //$NON-NLS-1$
+			.append(classFileAttribute.getAttributeLength());
 	}
 
 	/**
@@ -786,7 +536,12 @@
 		char[] methodDescriptor = methodInfo.getDescriptor();
 		IClassFileAttribute classFileAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.SIGNATURE);
 		ISignatureAttribute signatureAttribute = (ISignatureAttribute) classFileAttribute;
-		if (mode == DETAILED) {
+		IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
+		IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
+		IClassFileAttribute runtimeVisibleParameterAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS);
+		IClassFileAttribute runtimeInvisibleParameterAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS);
+		IClassFileAttribute annotationDefaultAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.ANNOTATION_DEFAULT);
+		if (mode == DETAILED || mode == SYSTEM) {
 			buffer
 				.append(Util.bind("disassembler.begincommentline")) //$NON-NLS-1$
 				.append(Util.bind("classfileformat.methoddescriptor")) //$NON-NLS-1$
@@ -816,7 +571,18 @@
 					.append(codeAttribute.getMaxLocals());
 				writeNewLine(buffer, lineSeparator, tabNumber);
 			}
-		}		
+		}
+		if (mode == DETAILED) {
+			// disassemble compact version of annotations
+			if (runtimeInvisibleAnnotationsAttribute != null) {
+				disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1);
+				writeNewLine(buffer, lineSeparator, tabNumber);
+			}
+			if (runtimeVisibleAnnotationsAttribute != null) {
+				disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1);
+				writeNewLine(buffer, lineSeparator, tabNumber);
+			}
+		}
 		int accessFlags = methodInfo.getAccessFlags();
 		decodeModifiersForMethod(buffer, accessFlags);
 		if (methodInfo.isSynthetic()) {
@@ -827,13 +593,13 @@
 		char[] methodName = null;
 		if (methodInfo.isConstructor()) {
 			methodName = classFileReader.getClassName();
-			buffer.append(Signature.toCharArray(methodDescriptor, methodName, getParameterNames(methodDescriptor, codeAttribute, accessFlags) , true, false));
+			buffer.append(Signature.toCharArray(methodDescriptor, methodName, getParameterNames(methodDescriptor, codeAttribute, accessFlags) , false, false, (accessFlags & IModifierConstants.ACC_VARARGS) != 0));
 		} else if (methodInfo.isClinit()) {
 			methodName = Util.bind("classfileformat.clinitname").toCharArray(); //$NON-NLS-1$
 			buffer.append(methodName);
 		} else {
 			methodName = methodInfo.getName();
-			buffer.append(Signature.toCharArray(methodDescriptor, methodName, getParameterNames(methodDescriptor, codeAttribute, accessFlags) , false, true));
+			buffer.append(Signature.toCharArray(methodDescriptor, methodName, getParameterNames(methodDescriptor, codeAttribute, accessFlags) , false, true, (accessFlags & IModifierConstants.ACC_VARARGS) != 0));
 		}
 		IExceptionAttribute exceptionAttribute = methodInfo.getExceptionAttribute();
 		if (exceptionAttribute != null) {
@@ -852,8 +618,20 @@
 			CharOperation.replace(exceptionName, '/', '.');
 			buffer.append(exceptionName);
 		}
-		buffer.append(Util.bind("disassembler.endofmethodheader")); //$NON-NLS-1$
 		if (mode == DETAILED) {
+			if (annotationDefaultAttribute != null) {
+				buffer.append(" default "); //$NON-NLS-1$
+				disassembleAsModifier((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber);
+			}
+		}
+		buffer.append(Util.bind("disassembler.endofmethodheader")); //$NON-NLS-1$
+		
+		if (mode == DETAILED || mode == SYSTEM) {
+			if (codeAttribute != null) {
+				disassemble(codeAttribute, buffer, lineSeparator, tabNumber);
+			}
+		}
+		if (mode == SYSTEM) {
 			IClassFileAttribute[] attributes = methodInfo.getAttributes();
 			int length = attributes.length;
 			if (length != 0) {
@@ -862,6 +640,11 @@
 					if (attribute != codeAttribute
 							&& attribute != exceptionAttribute
 							&& attribute != signatureAttribute
+							&& attribute != annotationDefaultAttribute
+							&& attribute != runtimeInvisibleAnnotationsAttribute
+							&& attribute != runtimeVisibleAnnotationsAttribute
+							&& attribute != runtimeInvisibleParameterAnnotationsAttribute
+							&& attribute != runtimeVisibleParameterAnnotationsAttribute
 							&& !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED)
 							&& !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) {
 						disassemble(attribute, buffer, lineSeparator, tabNumber);
@@ -869,20 +652,227 @@
 					}
 				}
 			}
-			if (codeAttribute != null) {
-				disassemble(codeAttribute, buffer, lineSeparator, tabNumber);
+			if (annotationDefaultAttribute != null) {
+				disassemble((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber);
+			}
+			if (runtimeVisibleAnnotationsAttribute != null) {
+				disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber);
+			}
+			if (runtimeInvisibleAnnotationsAttribute != null) {
+				disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber);
+			}
+			if (runtimeVisibleParameterAnnotationsAttribute != null) {
+				disassemble((IRuntimeVisibleParameterAnnotationsAttribute) runtimeVisibleParameterAnnotationsAttribute, buffer, lineSeparator, tabNumber);
+			}
+			if (runtimeInvisibleParameterAnnotationsAttribute != null) {
+				disassemble((IRuntimeInvisibleParameterAnnotationsAttribute) runtimeInvisibleParameterAnnotationsAttribute, buffer, lineSeparator, tabNumber);
 			}
 		}
 	}
 
-	private void disassemble(IClassFileAttribute classFileAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
-		writeNewLine(buffer, lineSeparator, tabNumber + 1);
-		buffer.append(Util.bind("disassembler.genericattributeheader")); //$NON-NLS-1$
-		buffer
-			.append(Util.bind("disassembler.genericattributename")) //$NON-NLS-1$
-			.append(classFileAttribute.getAttributeName())
-			.append(Util.bind("disassembler.genericattributelength")) //$NON-NLS-1$
-			.append(classFileAttribute.getAttributeLength());
+	/**
+	 * @see #disassemble(org.eclipse.jdt.core.util.IClassFileReader, java.lang.String, int)
+	 */
+	public String disassemble(IClassFileReader classFileReader, String lineSeparator) {
+		return disassemble(classFileReader, lineSeparator, ClassFileBytesDisassembler.DEFAULT);
+	}
+
+	/**
+	 * Answers back the disassembled string of the IClassFileReader according to the
+	 * mode.
+	 * This is an output quite similar to the javap tool.
+	 * 
+	 * @param classFileReader The classFileReader to be disassembled
+	 * @param lineSeparator the line separator to use.
+	 * @param mode the mode used to disassemble the IClassFileReader
+	 * 
+	 * @return the disassembled string of the IClassFileReader according to the mode
+	 */
+	public String disassemble(IClassFileReader classFileReader, String lineSeparator, int mode) {
+		if (classFileReader == null) return EMPTY_OUTPUT;
+		StringBuffer buffer = new StringBuffer();
+	
+		ISourceAttribute sourceAttribute = classFileReader.getSourceFileAttribute();
+		IClassFileAttribute classFileAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.SIGNATURE);
+		ISignatureAttribute signatureAttribute = (ISignatureAttribute) classFileAttribute;
+		final int accessFlags = classFileReader.getAccessFlags();
+		if (mode == DETAILED || mode == SYSTEM) {
+			int minorVersion = classFileReader.getMinorVersion();
+			int majorVersion = classFileReader.getMajorVersion();
+			buffer.append(Util.bind("disassembler.begincommentline")); //$NON-NLS-1$
+			if (sourceAttribute != null) {
+				buffer.append(Util.bind("disassembler.sourceattributeheader")); //$NON-NLS-1$
+				buffer.append(sourceAttribute.getSourceFileName());
+			}
+			String versionNumber = VERSION_UNKNOWN;//$NON-NLS-1$
+			if (minorVersion == 3 && majorVersion == 45) {
+				versionNumber = JavaCore.VERSION_1_1;
+			} else if (minorVersion == 0 && majorVersion == 46) {
+				versionNumber = JavaCore.VERSION_1_2;
+			} else if (minorVersion == 0 && majorVersion == 47) {
+				versionNumber = JavaCore.VERSION_1_3;
+			} else if (minorVersion == 0 && majorVersion == 48) {
+				versionNumber = JavaCore.VERSION_1_4;
+			} else if (minorVersion == 0 && majorVersion == 49) {
+				versionNumber = JavaCore.VERSION_1_5;
+			}
+			buffer.append(
+				Util.bind("classfileformat.versiondetails",//$NON-NLS-1$
+				new String[] {
+					versionNumber,
+					Integer.toString(majorVersion),
+					Integer.toString(minorVersion),
+					((accessFlags & IModifierConstants.ACC_SUPER) != 0
+							? Util.bind("classfileformat.superflagisset")//$NON-NLS-1$
+							: Util.bind("classfileformat.superflagisnotset"))//$NON-NLS-1$
+					+ (isDeprecated(classFileReader) ? ", deprecated" : EMPTY_OUTPUT)//$NON-NLS-1$
+				}));
+			writeNewLine(buffer, lineSeparator, 0);
+			if (signatureAttribute != null) {
+				buffer
+					.append(Util.bind("disassembler.begincommentline"))	 //$NON-NLS-1$
+					.append(Util.bind("disassembler.signatureattributeheader")) //$NON-NLS-1$
+					.append(signatureAttribute.getSignature());
+				writeNewLine(buffer, lineSeparator, 0);
+			}
+		}
+		char[] className = classFileReader.getClassName();
+		if (className == null) {
+			// incomplete initialization. We cannot go further.
+			return buffer.toString();
+		}
+		
+		IInnerClassesAttribute innerClassesAttribute = classFileReader.getInnerClassesAttribute();
+		IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
+		IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
+		
+		if (mode == DETAILED) {
+			// disassemble compact version of annotations
+			if (runtimeInvisibleAnnotationsAttribute != null) {
+				disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 1);
+				writeNewLine(buffer, lineSeparator, 0);
+			}
+			if (runtimeVisibleAnnotationsAttribute != null) {
+				disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 1);
+				writeNewLine(buffer, lineSeparator, 0);
+			}
+		}
+		boolean decoded = false;
+		if (innerClassesAttribute != null) {
+			// search the right entry
+			IInnerClassesAttributeEntry[] entries = innerClassesAttribute.getInnerClassAttributesEntries();
+			for (int i = 0, max = entries.length; i < max ; i++) {
+				IInnerClassesAttributeEntry entry = entries[i];
+				char[] innerClassName = entry.getInnerClassName();
+				if (innerClassName != null) {
+					if (CharOperation.equals(classFileReader.getClassName(), innerClassName)) {
+						decodeModifiersForInnerClasses(buffer, entry.getAccessFlags());
+						decoded = true;
+					}
+				}
+			}
+		}
+		if (!decoded) {
+			decodeModifiersForType(buffer, accessFlags);
+			if (isSynthetic(classFileReader)) {
+				buffer.append("synthetic"); //$NON-NLS-1$
+				buffer.append(Util.bind("disassembler.space")); //$NON-NLS-1$
+			}
+		}
+		
+		if ((accessFlags & IModifierConstants.ACC_ENUM) != 0) {
+			buffer.append("enum "); //$NON-NLS-1$
+		} else if (classFileReader.isClass()) {
+			buffer.append("class "); //$NON-NLS-1$
+		} else {
+			if ((accessFlags & IModifierConstants.ACC_ANNOTATION) != 0) {
+				buffer.append("@"); //$NON-NLS-1$
+			}
+			buffer.append("interface "); //$NON-NLS-1$
+		}
+		CharOperation.replace(className, '/', '.');
+		buffer.append(className);
+		
+		char[] superclassName = classFileReader.getSuperclassName();
+		if (superclassName != null) {
+			buffer.append(" extends "); //$NON-NLS-1$
+			CharOperation.replace(superclassName, '/', '.');
+			buffer.append(superclassName);
+		}
+		char[][] superclassInterfaces = classFileReader.getInterfaceNames();
+		int length = superclassInterfaces.length;
+		if (length != 0) {
+			buffer.append(" implements "); //$NON-NLS-1$
+			for (int i = 0; i < length - 1; i++) {
+				char[] superinterface = superclassInterfaces[i];
+				CharOperation.replace(superinterface, '/', '.');
+				buffer
+					.append(superinterface)
+					.append(Util.bind("disassembler.comma"))//$NON-NLS-1$
+					.append(Util.bind("disassembler.space")); //$NON-NLS-1$
+			}
+			char[] superinterface = superclassInterfaces[length - 1];
+			CharOperation.replace(superinterface, '/', '.');
+			buffer.append(superinterface);
+		}
+		buffer.append(Util.bind("disassembler.opentypedeclaration")); //$NON-NLS-1$
+		if (mode == SYSTEM) {
+			disassemble(classFileReader.getConstantPool(), buffer, lineSeparator, 1);
+		}
+		disassembleTypeMembers(classFileReader, buffer, lineSeparator, 1, mode);
+		if (mode == DETAILED || mode == SYSTEM) {
+			IClassFileAttribute[] attributes = classFileReader.getAttributes();
+			length = attributes.length;
+			IEnclosingMethodAttribute enclosingMethodAttribute = getEnclosingMethodAttribute(classFileReader);
+			int remainingAttributesLength = length;
+			if (innerClassesAttribute != null) {
+				remainingAttributesLength--;
+			}
+			if (enclosingMethodAttribute != null) {
+				remainingAttributesLength--;
+			}
+			if (sourceAttribute != null) {
+				remainingAttributesLength--;
+			}
+			if (signatureAttribute != null) {
+				remainingAttributesLength--;
+			}
+			if (innerClassesAttribute != null || enclosingMethodAttribute != null || remainingAttributesLength != 0) {
+				writeNewLine(buffer, lineSeparator, 0);
+			}
+			if (innerClassesAttribute != null) {
+				disassemble(innerClassesAttribute, buffer, lineSeparator, 1);
+			}
+			if (enclosingMethodAttribute != null) {
+				disassemble(enclosingMethodAttribute, buffer, lineSeparator, 0);
+			}
+			if (mode == SYSTEM) {
+				if (runtimeVisibleAnnotationsAttribute != null) {
+					disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 0);
+				}
+				if (runtimeInvisibleAnnotationsAttribute != null) {
+					disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 0);
+				}
+				if (length != 0) {
+					for (int i = 0; i < length; i++) {
+						IClassFileAttribute attribute = attributes[i];
+						if (attribute != innerClassesAttribute
+							&& attribute != sourceAttribute
+							&& attribute != signatureAttribute
+							&& attribute != enclosingMethodAttribute
+							&& attribute != runtimeInvisibleAnnotationsAttribute
+							&& attribute != runtimeVisibleAnnotationsAttribute
+							&& !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED)
+							&& !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) {
+							disassemble(attribute, buffer, lineSeparator, 0);
+						}
+					}
+				}
+			}
+		}
+		writeNewLine(buffer, lineSeparator, 0);
+		buffer.append(Util.bind("disassembler.closetypedeclaration")); //$NON-NLS-1$
+		return buffer.toString();
 	}
 	
 	private void disassemble(ICodeAttribute codeAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
@@ -1049,6 +1039,118 @@
 		} 
 	}
 
+	private void disassemble(IConstantPool constantPool, StringBuffer buffer, String lineSeparator, int tabNumber) {
+		writeNewLine(buffer, lineSeparator, tabNumber);
+		int length = constantPool.getConstantPoolCount();
+		buffer.append(Util.bind("disassembler.constantpoolheader")); //$NON-NLS-1$
+		writeNewLine(buffer, lineSeparator, tabNumber + 1);
+		for (int i = 1; i < length; i++) {
+			IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(i);
+			switch (constantPool.getEntryKind(i)) {
+				case IConstantPoolConstant.CONSTANT_Class :
+					buffer.append(
+						Util.bind("disassembler.constantpool.class", //$NON-NLS-1$
+						new String[] {
+							Integer.toString(i),
+							Integer.toString(constantPoolEntry.getClassInfoNameIndex()),
+							new String(constantPoolEntry.getClassInfoName())})); //$NON-NLS-1$
+					break;
+				case IConstantPoolConstant.CONSTANT_Double :
+					buffer.append(
+						Util.bind("disassembler.constantpool.double", //$NON-NLS-1$
+						new String[] {
+							Integer.toString(i),
+							Double.toString(constantPoolEntry.getDoubleValue())})); //$NON-NLS-1$
+					break;
+				case IConstantPoolConstant.CONSTANT_Fieldref :
+					buffer.append(
+						Util.bind("disassembler.constantpool.fieldref", //$NON-NLS-1$
+						new String[] {
+							Integer.toString(i),
+							Integer.toString(constantPoolEntry.getClassIndex()),
+							Integer.toString(constantPoolEntry.getNameAndTypeIndex()),
+							new String(constantPoolEntry.getClassName()),
+							getFieldRefNameAndType(constantPoolEntry)})); //$NON-NLS-1$
+					break;
+				case IConstantPoolConstant.CONSTANT_Float :
+					buffer.append(
+						Util.bind("disassembler.constantpool.float", //$NON-NLS-1$
+						new String[] {
+							Integer.toString(i),
+							Float.toString(constantPoolEntry.getFloatValue())})); //$NON-NLS-1$
+					break;
+				case IConstantPoolConstant.CONSTANT_Integer :
+					buffer.append(
+						Util.bind("disassembler.constantpool.integer", //$NON-NLS-1$
+						new String[] {
+							Integer.toString(i),
+							Integer.toString(constantPoolEntry.getIntegerValue())})); //$NON-NLS-1$
+					break;
+				case IConstantPoolConstant.CONSTANT_InterfaceMethodref :
+					buffer.append(
+							Util.bind("disassembler.constantpool.interfacemethodref", //$NON-NLS-1$
+							new String[] {
+								Integer.toString(i),
+								Integer.toString(constantPoolEntry.getClassIndex()),
+								Integer.toString(constantPoolEntry.getNameAndTypeIndex()),
+								new String(constantPoolEntry.getClassName()),
+								getMethodRefNameAndType(constantPoolEntry)})); //$NON-NLS-1$
+					break;
+				case IConstantPoolConstant.CONSTANT_Long :
+					buffer.append(
+						Util.bind("disassembler.constantpool.long", //$NON-NLS-1$
+						new String[] {
+							Integer.toString(i),
+							Long.toString(constantPoolEntry.getLongValue())})); //$NON-NLS-1$
+					break;
+				case IConstantPoolConstant.CONSTANT_Methodref :
+					buffer.append(
+							Util.bind("disassembler.constantpool.methodref", //$NON-NLS-1$
+							new String[] {
+								Integer.toString(i),
+								Integer.toString(constantPoolEntry.getClassIndex()),
+								Integer.toString(constantPoolEntry.getNameAndTypeIndex()),
+								new String(constantPoolEntry.getClassName()),
+								getMethodRefNameAndType(constantPoolEntry)})); //$NON-NLS-1$
+					break;
+				case IConstantPoolConstant.CONSTANT_NameAndType :
+					int nameIndex = constantPoolEntry.getNameAndTypeInfoNameIndex();
+					int typeIndex = constantPoolEntry.getNameAndTypeInfoDescriptorIndex();
+					IConstantPoolEntry entry = constantPool.decodeEntry(nameIndex);
+					char[] nameValue = entry.getUtf8Value();
+					entry = constantPool.decodeEntry(typeIndex);
+					char[] typeValue = entry.getUtf8Value();
+					buffer.append(
+						Util.bind("disassembler.constantpool.name_and_type", //$NON-NLS-1$
+						new String[] {
+							Integer.toString(i),
+							Integer.toString(nameIndex),
+							Integer.toString(typeIndex),
+							String.valueOf(nameValue),
+							String.valueOf(typeValue)})); //$NON-NLS-1$
+					break;
+				case IConstantPoolConstant.CONSTANT_String :
+					buffer.append(
+						Util.bind("disassembler.constantpool.string", //$NON-NLS-1$
+						new String[] {
+							Integer.toString(i),
+							Integer.toString(constantPoolEntry.getStringIndex()),
+							constantPoolEntry.getStringValue()})); //$NON-NLS-1$
+					break;
+				case IConstantPoolConstant.CONSTANT_Utf8 :
+					buffer.append(
+						Util.bind("disassembler.constantpool.utf8", //$NON-NLS-1$
+						new String[] {
+							Integer.toString(i),
+							new String(constantPoolEntry.getUtf8Value())})); //$NON-NLS-1$
+					break;
+			}
+			if (i < length - 1) {
+				writeNewLine(buffer, lineSeparator, tabNumber + 1);
+			}
+		}
+	}
+
 	private void disassemble(IEnclosingMethodAttribute enclosingMethodAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
 		buffer.append(Util.bind("disassembler.enclosingmethodheader")); //$NON-NLS-1$
@@ -1059,12 +1161,393 @@
 			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 			.append(enclosingMethodAttribute.getMethodNameAndTypeIndex())
 			.append(" ")//$NON-NLS-1$
-			.append(enclosingMethodAttribute.getEnclosingClass()) //$NON-NLS-1$
-			.append(".")//$NON-NLS-1$
-			.append(enclosingMethodAttribute.getMethodName()) //$NON-NLS-1$
-			.append(enclosingMethodAttribute.getMethodDescriptor()); //$NON-NLS-1$
+			.append(enclosingMethodAttribute.getEnclosingClass()); //$NON-NLS-1$
+		if (enclosingMethodAttribute.getMethodNameAndTypeIndex() != 0) {
+			buffer
+				.append(".")//$NON-NLS-1$
+				.append(enclosingMethodAttribute.getMethodName()) //$NON-NLS-1$
+				.append(enclosingMethodAttribute.getMethodDescriptor()); //$NON-NLS-1$
+		}
 	}
 	
+	/**
+	 * Disassemble a field info
+	 */
+	private void disassemble(IFieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+		writeNewLine(buffer, lineSeparator, tabNumber);
+		char[] fieldDescriptor = fieldInfo.getDescriptor();
+		IClassFileAttribute classFileAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.SIGNATURE);
+		ISignatureAttribute signatureAttribute = (ISignatureAttribute) classFileAttribute;
+		if (mode == DETAILED || mode == SYSTEM) {
+			buffer
+				.append(Util.bind("disassembler.begincommentline")) //$NON-NLS-1$
+				.append(Util.bind("classfileformat.fieldddescriptor")) //$NON-NLS-1$
+				.append(Util.bind("classfileformat.fielddescriptorindex")) //$NON-NLS-1$
+				.append(fieldInfo.getDescriptorIndex())
+				.append(Util.bind("disassembler.space")) //$NON-NLS-1$
+				.append(fieldDescriptor);
+			if (fieldInfo.isDeprecated()) {
+				buffer.append(Util.bind("disassembler.deprecated"));//$NON-NLS-1$
+			}
+			writeNewLine(buffer, lineSeparator, tabNumber);
+			if (signatureAttribute != null) {
+				buffer
+					.append(Util.bind("disassembler.begincommentline"))	 //$NON-NLS-1$
+					.append(Util.bind("disassembler.signatureattributeheader")) //$NON-NLS-1$
+					.append(signatureAttribute.getSignature());
+				writeNewLine(buffer, lineSeparator, tabNumber);
+			}
+		}
+		IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
+		IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
+		if (mode == DETAILED) {
+			// disassemble compact version of annotations
+			if (runtimeInvisibleAnnotationsAttribute != null) {
+				disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1);
+				writeNewLine(buffer, lineSeparator, tabNumber);
+			}
+			if (runtimeVisibleAnnotationsAttribute != null) {
+				disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1);
+				writeNewLine(buffer, lineSeparator, tabNumber);
+			}
+		}
+		decodeModifiersForField(buffer, fieldInfo.getAccessFlags());
+		if (fieldInfo.isSynthetic()) {
+			buffer.append("synthetic"); //$NON-NLS-1$
+			buffer.append(Util.bind("disassembler.space")); //$NON-NLS-1$
+		}
+		buffer.append(getSignatureForField(fieldDescriptor));
+		buffer.append(Util.bind("disassembler.space")); //$NON-NLS-1$
+		buffer.append(new String(fieldInfo.getName()));
+		IConstantValueAttribute constantValueAttribute = fieldInfo.getConstantValueAttribute();
+		if (constantValueAttribute != null) {
+			buffer.append(Util.bind("disassembler.fieldhasconstant")); //$NON-NLS-1$
+			IConstantPoolEntry constantPoolEntry = constantValueAttribute.getConstantValue();
+			switch(constantPoolEntry.getKind()) {
+				case IConstantPoolConstant.CONSTANT_Long :
+					buffer.append(constantPoolEntry.getLongValue() + "L"); //$NON-NLS-1$
+					break;
+				case IConstantPoolConstant.CONSTANT_Float :
+					buffer.append(constantPoolEntry.getFloatValue() + "f"); //$NON-NLS-1$
+					break;
+				case IConstantPoolConstant.CONSTANT_Double :
+					buffer.append(constantPoolEntry.getDoubleValue());
+					break;
+				case IConstantPoolConstant.CONSTANT_Integer:
+					switch(fieldDescriptor[0]) {
+						case 'C' :
+							buffer.append("'" + (char) constantPoolEntry.getIntegerValue() + "'"); //$NON-NLS-1$//$NON-NLS-2$
+							break;
+						case 'Z' :
+							buffer.append(constantPoolEntry.getIntegerValue() == 1 ? "true" : "false");//$NON-NLS-1$//$NON-NLS-2$
+							break;
+						case 'B' :
+							buffer.append(constantPoolEntry.getIntegerValue());
+							break;
+						case 'S' :
+							buffer.append(constantPoolEntry.getIntegerValue());
+							break;
+						case 'I' :
+							buffer.append(constantPoolEntry.getIntegerValue());
+					}
+					break;
+				case IConstantPoolConstant.CONSTANT_String:
+					buffer.append("\"" + decodeStringValue(constantPoolEntry.getStringValue()) + "\"" );//$NON-NLS-1$//$NON-NLS-2$
+			}
+		}
+		buffer.append(Util.bind("disassembler.endoffieldheader")); //$NON-NLS-1$
+		if (mode == SYSTEM) {
+			IClassFileAttribute[] attributes = fieldInfo.getAttributes();
+			int length = attributes.length;
+			if (length != 0) {
+				for (int i = 0; i < length; i++) {
+					IClassFileAttribute attribute = attributes[i];
+					if (attribute != constantValueAttribute
+						&& attribute != signatureAttribute
+						&& attribute != runtimeInvisibleAnnotationsAttribute
+						&& attribute != runtimeVisibleAnnotationsAttribute
+						&& !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED)
+						&& !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) {
+						disassemble(attribute, buffer, lineSeparator, tabNumber);
+					}
+				}
+			}
+			if (runtimeVisibleAnnotationsAttribute != null) {
+				disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber);
+			}
+			if (runtimeInvisibleAnnotationsAttribute != null) {
+				disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber);
+			}
+		}
+	}
+	
+	private void disassemble(IInnerClassesAttribute innerClassesAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+		writeNewLine(buffer, lineSeparator, tabNumber);
+		buffer.append(Util.bind("disassembler.innerattributesheader")); //$NON-NLS-1$
+		writeNewLine(buffer, lineSeparator, tabNumber + 1);
+		IInnerClassesAttributeEntry[] innerClassesAttributeEntries = innerClassesAttribute.getInnerClassAttributesEntries();
+		int length = innerClassesAttributeEntries.length;
+		int innerClassNameIndex, outerClassNameIndex, innerNameIndex, accessFlags;
+		IInnerClassesAttributeEntry innerClassesAttributeEntry;
+		for (int i = 0; i < length - 1; i++) {
+			innerClassesAttributeEntry = innerClassesAttributeEntries[i];
+			innerClassNameIndex = innerClassesAttributeEntry.getInnerClassNameIndex();
+			outerClassNameIndex = innerClassesAttributeEntry.getOuterClassNameIndex();
+			innerNameIndex = innerClassesAttributeEntry.getInnerNameIndex();
+			accessFlags = innerClassesAttributeEntry.getAccessFlags();
+			buffer
+				.append(Util.bind("disassembler.openinnerclassentry")) //$NON-NLS-1$
+				.append(Util.bind("disassembler.inner_class_info_name")) //$NON-NLS-1$
+				.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
+				.append(innerClassNameIndex);
+			if (innerClassNameIndex != 0) {
+				buffer
+					.append(Util.bind("disassembler.space")) //$NON-NLS-1$
+					.append(innerClassesAttributeEntry.getInnerClassName());
+			}
+			buffer
+				.append(Util.bind("disassembler.comma")) //$NON-NLS-1$
+				.append(Util.bind("disassembler.space")) //$NON-NLS-1$
+				.append(Util.bind("disassembler.outer_class_info_name")) //$NON-NLS-1$
+				.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
+				.append(outerClassNameIndex);
+			if (outerClassNameIndex != 0) {
+				buffer	
+					.append(Util.bind("disassembler.space")) //$NON-NLS-1$
+					.append(innerClassesAttributeEntry.getOuterClassName());
+			}
+			writeNewLine(buffer, lineSeparator, tabNumber);
+			dumpTab(tabNumber, buffer);
+			buffer.append(Util.bind("disassembler.space")); //$NON-NLS-1$
+			buffer
+				.append(Util.bind("disassembler.inner_name")) //$NON-NLS-1$
+				.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
+				.append(innerNameIndex);
+			if (innerNameIndex != 0) {
+				buffer
+					.append(Util.bind("disassembler.space")) //$NON-NLS-1$
+					.append(innerClassesAttributeEntry.getInnerName());
+			}
+			buffer
+				.append(Util.bind("disassembler.comma")) //$NON-NLS-1$
+				.append(Util.bind("disassembler.space")) //$NON-NLS-1$
+				.append(Util.bind("disassembler.inner_accessflags")) //$NON-NLS-1$
+				.append(accessFlags)
+				.append(Util.bind("disassembler.space")); //$NON-NLS-1$
+			decodeModifiersForInnerClasses(buffer, accessFlags);
+			buffer
+				.append(Util.bind("disassembler.closeinnerclassentry")) //$NON-NLS-1$
+				.append(Util.bind("disassembler.comma")); //$NON-NLS-1$
+			writeNewLine(buffer, lineSeparator, tabNumber + 1);
+		}
+		// last entry
+		innerClassesAttributeEntry = innerClassesAttributeEntries[length - 1];
+		innerClassNameIndex = innerClassesAttributeEntry.getInnerClassNameIndex();
+		outerClassNameIndex = innerClassesAttributeEntry.getOuterClassNameIndex();
+		innerNameIndex = innerClassesAttributeEntry.getInnerNameIndex();
+		accessFlags = innerClassesAttributeEntry.getAccessFlags();
+		buffer
+			.append(Util.bind("disassembler.openinnerclassentry")) //$NON-NLS-1$
+			.append(Util.bind("disassembler.inner_class_info_name")) //$NON-NLS-1$
+			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
+			.append(innerClassNameIndex);
+		if (innerClassNameIndex != 0) {
+			buffer
+				.append(Util.bind("disassembler.space")) //$NON-NLS-1$
+				.append(innerClassesAttributeEntry.getInnerClassName());
+		}
+		buffer
+			.append(Util.bind("disassembler.comma")) //$NON-NLS-1$
+			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
+			.append(Util.bind("disassembler.outer_class_info_name")) //$NON-NLS-1$
+			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
+			.append(outerClassNameIndex);
+		if (outerClassNameIndex != 0) {
+			buffer	
+				.append(Util.bind("disassembler.space")) //$NON-NLS-1$
+				.append(innerClassesAttributeEntry.getOuterClassName());
+		}
+		writeNewLine(buffer, lineSeparator, tabNumber);
+		dumpTab(tabNumber, buffer);
+		buffer.append(Util.bind("disassembler.space")); //$NON-NLS-1$
+		buffer
+			.append(Util.bind("disassembler.inner_name")) //$NON-NLS-1$
+			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
+			.append(innerNameIndex);
+		if (innerNameIndex != 0) {
+			buffer
+				.append(Util.bind("disassembler.space")) //$NON-NLS-1$
+				.append(innerClassesAttributeEntry.getInnerName());
+		}
+		buffer
+			.append(Util.bind("disassembler.comma")) //$NON-NLS-1$
+			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
+			.append(Util.bind("disassembler.inner_accessflags")) //$NON-NLS-1$
+			.append(accessFlags)
+			.append(Util.bind("disassembler.space")); //$NON-NLS-1$
+		decodeModifiersForInnerClasses(buffer, accessFlags);
+		buffer.append(Util.bind("disassembler.closeinnerclassentry")); //$NON-NLS-1$
+	}
+
+	private void disassemble(int index, IParameterAnnotation parameterAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber) {
+		IAnnotation[] annotations = parameterAnnotation.getAnnotations();
+		writeNewLine(buffer, lineSeparator, tabNumber + 1);
+		buffer.append(
+			Util.bind("disassembler.parameterannotationentrystart", //$NON-NLS-1$
+			Integer.toString(index),
+			Integer.toString(annotations.length)));
+		for (int i = 0, max = annotations.length; i < max; i++) {
+			disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1);
+		}
+	}
+
+	private void disassemble(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+		writeNewLine(buffer, lineSeparator, tabNumber + 1);
+		buffer.append(Util.bind("disassembler.runtimeinvisibleannotationsattributeheader")); //$NON-NLS-1$
+		IAnnotation[] annotations = runtimeInvisibleAnnotationsAttribute.getAnnotations();
+		for (int i = 0, max = annotations.length; i < max; i++) {
+			disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1);
+		}
+	}
+
+	private void disassemble(IRuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+		writeNewLine(buffer, lineSeparator, tabNumber + 1);
+		buffer.append(Util.bind("disassembler.runtimeinvisibleparameterannotationsattributeheader")); //$NON-NLS-1$
+		IParameterAnnotation[] parameterAnnotations = runtimeInvisibleParameterAnnotationsAttribute.getParameterAnnotations();
+		for (int i = 0, max = parameterAnnotations.length; i < max; i++) {
+			disassemble(i, parameterAnnotations[i], buffer, lineSeparator, tabNumber + 1);
+		}
+	}
+	
+	private void disassemble(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+		writeNewLine(buffer, lineSeparator, tabNumber + 1);
+		buffer.append(Util.bind("disassembler.runtimevisibleannotationsattributeheader")); //$NON-NLS-1$
+		IAnnotation[] annotations = runtimeVisibleAnnotationsAttribute.getAnnotations();
+		for (int i = 0, max = annotations.length; i < max; i++) {
+			disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1);
+		}
+	}
+
+	private void disassemble(IRuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+		writeNewLine(buffer, lineSeparator, tabNumber + 1);
+		buffer.append(Util.bind("disassembler.runtimevisibleparameterannotationsattributeheader")); //$NON-NLS-1$
+		IParameterAnnotation[] parameterAnnotations = runtimeVisibleParameterAnnotationsAttribute.getParameterAnnotations();
+		for (int i = 0, max = parameterAnnotations.length; i < max; i++) {
+			disassemble(i, parameterAnnotations[i], buffer, lineSeparator, tabNumber + 1);
+		}
+	}
+
+	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);
+			}
+			disassembleAsModifier(components[i], buffer, lineSeparator, tabNumber + 1);
+		}
+		buffer.append(')');
+	}
+
+	private void disassembleAsModifier(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber) {
+		buffer.append(annotationComponent.getComponentName()).append('=');
+		disassembleAsModifier(annotationComponent.getComponentValue(), buffer, lineSeparator, tabNumber + 1);
+	}
+
+	private void disassembleAsModifier(IAnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber) {
+		switch(annotationComponentValue.getTag()) {
+			case IAnnotationComponentValue.BYTE_TAG:
+			case IAnnotationComponentValue.CHAR_TAG:
+			case IAnnotationComponentValue.DOUBLE_TAG:
+			case IAnnotationComponentValue.FLOAT_TAG:
+			case IAnnotationComponentValue.INTEGER_TAG:
+			case IAnnotationComponentValue.LONG_TAG:
+			case IAnnotationComponentValue.SHORT_TAG:
+			case IAnnotationComponentValue.BOOLEAN_TAG:
+			case IAnnotationComponentValue.STRING_TAG:
+				IConstantPoolEntry constantPoolEntry = annotationComponentValue.getConstantValue();
+				String value = null;
+				switch(constantPoolEntry.getKind()) {
+					case IConstantPoolConstant.CONSTANT_Long :
+						value = constantPoolEntry.getLongValue() + "L"; //$NON-NLS-1$
+						break;
+					case IConstantPoolConstant.CONSTANT_Float :
+						value = constantPoolEntry.getFloatValue() + "f"; //$NON-NLS-1$
+						break;
+					case IConstantPoolConstant.CONSTANT_Double :
+						value = Double.toString(constantPoolEntry.getDoubleValue());
+						break;
+					case IConstantPoolConstant.CONSTANT_Integer:
+						switch(annotationComponentValue.getTag()) {
+							case IAnnotationComponentValue.CHAR_TAG :
+								value = "'" + (char) constantPoolEntry.getIntegerValue() + "'"; //$NON-NLS-1$//$NON-NLS-2$
+								break;
+							case IAnnotationComponentValue.BOOLEAN_TAG :
+								value = constantPoolEntry.getIntegerValue() == 1 ? "true" : "false";//$NON-NLS-1$//$NON-NLS-2$
+								break;
+							case IAnnotationComponentValue.BYTE_TAG :
+								value = "(byte) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
+								break;
+							case IAnnotationComponentValue.SHORT_TAG :
+								value =  "(short) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
+								break;
+							case IAnnotationComponentValue.INTEGER_TAG :
+								value =  "(int) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
+						}
+						break;
+					case IConstantPoolConstant.CONSTANT_Utf8:
+						value = "\"" + decodeStringValue(constantPoolEntry.getUtf8Value()) + "\"";//$NON-NLS-1$//$NON-NLS-2$
+				}
+				buffer.append(value); //$NON-NLS-1$
+				break;
+			case IAnnotationComponentValue.ENUM_TAG:
+				final char[] typeName = CharOperation.replaceOnCopy(annotationComponentValue.getEnumConstantTypeName(), '/', '.');
+				final char[] constantName = annotationComponentValue.getEnumConstantName();
+				buffer.append(Signature.toCharArray(typeName)).append('.').append(constantName);
+				break;
+			case IAnnotationComponentValue.CLASS_TAG:
+				constantPoolEntry = annotationComponentValue.getClassInfo();
+				final char[] className = CharOperation.replaceOnCopy(constantPoolEntry.getUtf8Value(), '/', '.');
+				buffer.append(Signature.toCharArray(className));
+				break;
+			case IAnnotationComponentValue.ANNOTATION_TAG:
+				IAnnotation annotation = annotationComponentValue.getAnnotationValue();
+				disassembleAsModifier(annotation, buffer, lineSeparator, tabNumber + 1);
+				break;
+			case IAnnotationComponentValue.ARRAY_TAG:
+				final IAnnotationComponentValue[] annotationComponentValues = annotationComponentValue.getAnnotationComponentValues();
+				buffer.append('{');
+				for (int i = 0, max = annotationComponentValues.length; i < max; i++) {
+					if (i > 0) {
+						buffer.append(',');
+					}
+					disassembleAsModifier(annotationComponentValues[i], buffer, lineSeparator, tabNumber + 1);
+				}
+				buffer.append('}');
+		}
+	}
+
+	private void disassembleAsModifier(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+		IAnnotationComponentValue componentValue = annotationDefaultAttribute.getMemberValue();
+		disassembleAsModifier(componentValue, buffer, lineSeparator, tabNumber + 1);
+	}
+	
+	private void disassembleAsModifier(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+		IAnnotation[] annotations = runtimeInvisibleAnnotationsAttribute.getAnnotations();
+		for (int i = 0, max = annotations.length; i < max; i++) {
+			disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1);
+		}
+	}
+
+	private void disassembleAsModifier(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+		IAnnotation[] annotations = runtimeVisibleAnnotationsAttribute.getAnnotations();
+		for (int i = 0, max = annotations.length; i < max; i++) {
+			disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1);
+		}
+	}
+
 	private void disassembleTypeMembers(IClassFileReader classFileReader, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
 		IFieldInfo[] fields = classFileReader.getFieldInfos();
 		for (int i = 0, max = fields.length; i < max; i++) {
@@ -1080,7 +1563,7 @@
 	
 	private final void dumpTab(int tabNumber, StringBuffer buffer) {
 		for (int i = 0; i < tabNumber; i++) {
-			buffer.append(Util.bind("disassembler.identation")); //$NON-NLS-1$
+			buffer.append(Util.bind("disassembler.indentation")); //$NON-NLS-1$
 		}
 	} 
 	
@@ -1118,6 +1601,14 @@
 			}
 			return null;
 	}
+	private String getFieldRefNameAndType(IConstantPoolEntry entry) {
+		StringBuffer stringBuffer = new StringBuffer();
+		stringBuffer
+			.append(entry.getFieldName())
+			.append(' ')
+			.append(entry.getFieldDescriptor());
+		return String.valueOf(stringBuffer);
+	}
 	private ILocalVariableTypeTableAttribute getLocalVariableTypeAttribute(ICodeAttribute codeAttribute) {
 		IClassFileAttribute[] attributes = codeAttribute.getAttributes();
 		for (int i = 0, max = attributes.length; i < max; i++) {
@@ -1128,39 +1619,13 @@
 		return null;
 	}
 
-	private char[] getSignatureForField(char[] fieldDescriptor) {
-		final int length = fieldDescriptor.length;
-		char[] newFieldDescriptor = new char[length];
-		System.arraycopy(fieldDescriptor, 0, newFieldDescriptor, 0, length);
-		CharOperation.replace(newFieldDescriptor, '/', '.');
-		CharOperation.replace(newFieldDescriptor, '$', '~');
-		char[] fieldDescriptorSignature = Signature.toCharArray(newFieldDescriptor);
-		CharOperation.replace(fieldDescriptorSignature, '~', '$');
-		return fieldDescriptorSignature;
-	}
-	
-	private boolean isDeprecated(IClassFileReader classFileReader) {
-		IClassFileAttribute[] attributes = classFileReader.getAttributes();
-		for (int i = 0, max = attributes.length; i < max; i++) {
-			if (CharOperation.equals(attributes[i].getAttributeName(), IAttributeNamesConstants.DEPRECATED)) {
-				return true;
-			}
-		}
-		return false;
-	}
-	
-	private boolean isSynthetic(IClassFileReader classFileReader) {
-		int flags = classFileReader.getAccessFlags();
-		if ((flags & IModifierConstants.ACC_SYNTHETIC) != 0) {
-			return true;
-		}
-		IClassFileAttribute[] attributes = classFileReader.getAttributes();
-		for (int i = 0, max = attributes.length; i < max; i++) {
-			if (CharOperation.equals(attributes[i].getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) {
-				return true;
-			}
-		}
-		return false;
+	private String getMethodRefNameAndType(IConstantPoolEntry entry) {
+		StringBuffer stringBuffer = new StringBuffer();
+		stringBuffer
+			.append(entry.getMethodName())
+			.append(' ')
+			.append(entry.getMethodDescriptor());
+		return String.valueOf(stringBuffer);
 	}
 	
 	private char[][] getParameterNames(char[] methodDescriptor, ICodeAttribute codeAttribute, int accessFlags) {
@@ -1192,6 +1657,38 @@
 		}
 		return parameterNames;
 	}
+
+	private char[] getSignatureForField(char[] fieldDescriptor) {
+		char[] newFieldDescriptor = CharOperation.replaceOnCopy(fieldDescriptor, '/', '.');
+		newFieldDescriptor = CharOperation.replaceOnCopy(newFieldDescriptor, '$', '~');
+		char[] fieldDescriptorSignature = Signature.toCharArray(newFieldDescriptor);
+		CharOperation.replace(fieldDescriptorSignature, '~', '$');
+		return fieldDescriptorSignature;
+	}
+	
+	private boolean isDeprecated(IClassFileReader classFileReader) {
+		IClassFileAttribute[] attributes = classFileReader.getAttributes();
+		for (int i = 0, max = attributes.length; i < max; i++) {
+			if (CharOperation.equals(attributes[i].getAttributeName(), IAttributeNamesConstants.DEPRECATED)) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	private boolean isSynthetic(IClassFileReader classFileReader) {
+		int flags = classFileReader.getAccessFlags();
+		if ((flags & IModifierConstants.ACC_SYNTHETIC) != 0) {
+			return true;
+		}
+		IClassFileAttribute[] attributes = classFileReader.getAttributes();
+		for (int i = 0, max = attributes.length; i < max; i++) {
+			if (CharOperation.equals(attributes[i].getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) {
+				return true;
+			}
+		}
+		return false;
+	}
 	
 	private void writeNewLine(StringBuffer buffer, String lineSeparator, int tabNumber) {
 		buffer.append(lineSeparator);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ElementInfoConverter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ElementInfoConverter.java
deleted file mode 100644
index 4578f63..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ElementInfoConverter.java
+++ /dev/null
@@ -1,482 +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 Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.core.util;
-
-/**
- * Converter from element info to parsed compilation unit.
- *
- */
-
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.Argument;
-import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.eclipse.jdt.internal.compiler.env.*;
-import org.eclipse.jdt.internal.compiler.env.ISourceField;
-import org.eclipse.jdt.internal.compiler.env.ISourceImport;
-import org.eclipse.jdt.internal.compiler.env.ISourceMethod;
-import org.eclipse.jdt.internal.compiler.env.ISourceType;
-
-import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
-import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
-import org.eclipse.jdt.internal.core.*;
-import org.eclipse.jdt.internal.core.JavaElement;
-import org.eclipse.jdt.internal.core.SourceFieldElementInfo;
-import org.eclipse.jdt.internal.core.SourceMethodElementInfo;
-
-public class ElementInfoConverter implements CompilerModifiers {
-
-	/*
-	 * Convert a set of source type infos into a parsed compilation unit declaration
-	 * The argument types are then all grouped in the same unit. The argument types must 
-	 * at least contain one type.
-	 * Can optionally add local and anonymous types
-	 */
-	public static CompilationUnitDeclaration buildCompilationUnit(
-		SourceTypeElementInfo[] sourceTypes,
-		boolean needLocalTypes,
-		ProblemReporter problemReporter,
-		CompilationResult compilationResult) {
-
-		return 
-			new ElementInfoConverter(needLocalTypes, problemReporter).convert(
-				sourceTypes, 
-				compilationResult);
-	}
-	
-	private boolean needLocalTypes; // local and anoymous types
-	private ProblemReporter problemReporter;
-	private CompilationUnitDeclaration unit;
-	
-	private ElementInfoConverter(boolean needLocalTypes, ProblemReporter problemReporter) {
-		this.needLocalTypes = needLocalTypes;
-		this.problemReporter = problemReporter;
-	}
-	
-	/*
-	 * Convert an initializerinfo into a parsed initializer declaration
-	 */
-	private Initializer convert(InitializerElementInfo initializerInfo, CompilationResult compilationResult) {
-
-		Block block = new Block(0);
-		Initializer initializer = new Initializer(block, IConstants.AccDefault);
-
-		int start = initializerInfo.getDeclarationSourceStart();
-		int end = initializerInfo.getDeclarationSourceEnd();
-
-		initializer.name = initializerInfo.getName();
-		initializer.sourceStart = initializer.declarationSourceStart = start;
-		initializer.sourceEnd = initializer.declarationSourceEnd = end;
-		initializer.modifiers = initializerInfo.getModifiers();
-
-		/* convert local and anonymous types */
-		IJavaElement[] children = initializerInfo.getChildren();
-		int typesLength = children.length;
-		if (typesLength > 0) {
-			Statement[] statements = new Statement[typesLength];
-			for (int i = 0; i < typesLength; i++) {
-				JavaElement type = (JavaElement)children[i];
-				try {
-					TypeDeclaration localType = convert((SourceTypeElementInfo)type.getElementInfo(), compilationResult);
-					if ((localType.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
-						QualifiedAllocationExpression expression = new QualifiedAllocationExpression(localType);
-						expression.type = localType.superclass;
-						localType.superclass = null;
-						localType.superInterfaces = null;
-						localType.allocation = expression;
-						statements[i] = expression;
-					} else {
-						statements[i] = localType;
-					}
-				} catch (JavaModelException e) {
-					// ignore
-				}
-			}
-			block.statements = statements;
-		}
-		
-		return initializer;
-	}
-
-	/*
-	 * Convert a source field info into a parsed field declaration
-	 */
-	private FieldDeclaration convert(SourceFieldElementInfo sourceField, CompilationResult compilationResult) {
-
-		FieldDeclaration field = new FieldDeclaration();
-
-		int start = sourceField.getNameSourceStart();
-		int end = sourceField.getNameSourceEnd();
-
-		field.name = sourceField.getName();
-		field.sourceStart = start;
-		field.sourceEnd = end;
-		field.type = createTypeReference(sourceField.getTypeName(), start, end);
-		field.declarationSourceStart = sourceField.getDeclarationSourceStart();
-		field.declarationSourceEnd = sourceField.getDeclarationSourceEnd();
-		field.modifiers = sourceField.getModifiers();
-
-		/* convert local and anonymous types */
-		if (this.needLocalTypes) {
-			IJavaElement[] children = sourceField.getChildren();
-			int typesLength = children.length;
-			if (typesLength > 0) {
-				ArrayInitializer initializer = new ArrayInitializer();
-				field.initialization = initializer;
-				Expression[] expressions = new Expression[typesLength];
-				initializer.expressions = expressions;
-				for (int i = 0; i < typesLength; i++) {
-					IJavaElement localType = children[i];
-					try {
-						TypeDeclaration anonymousLocalTypeDeclaration = convert((SourceTypeElementInfo)((JavaElement)localType).getElementInfo(),compilationResult);
-						QualifiedAllocationExpression expression = new QualifiedAllocationExpression(anonymousLocalTypeDeclaration);
-						expression.type = anonymousLocalTypeDeclaration.superclass;
-						anonymousLocalTypeDeclaration.superclass = null;
-						anonymousLocalTypeDeclaration.superInterfaces = null;
-						anonymousLocalTypeDeclaration.allocation = expression;
-						expressions[i] = expression;
-					} catch (JavaModelException e) {
-						// ignore
-					}
-				}
-			}
-		}
-		
-		return field;
-	}
-
-	/*
-	 * Convert a source method info into a parsed method/constructor declaration 
-	 */
-	private AbstractMethodDeclaration convert(SourceMethodElementInfo sourceMethod, CompilationResult compilationResult) {
-
-		AbstractMethodDeclaration method;
-
-		/* only source positions available */
-		int start = sourceMethod.getNameSourceStart();
-		int end = sourceMethod.getNameSourceEnd();
-
-		if (sourceMethod.isConstructor()) {
-			ConstructorDeclaration decl = new ConstructorDeclaration(compilationResult);
-			decl.isDefaultConstructor = false;
-			method = decl;
-		} else {
-			MethodDeclaration decl = new MethodDeclaration(compilationResult);
-			/* convert return type */
-			decl.returnType =
-				createTypeReference(sourceMethod.getReturnTypeName(), start, end);
-			method = decl;
-		}
-		method.selector = sourceMethod.getSelector();
-		method.modifiers = sourceMethod.getModifiers();
-		method.sourceStart = start;
-		method.sourceEnd = end;
-		method.declarationSourceStart = sourceMethod.getDeclarationSourceStart();
-		method.declarationSourceEnd = sourceMethod.getDeclarationSourceEnd();
-
-		/* convert arguments */
-		char[][] argumentTypeNames = sourceMethod.getArgumentTypeNames();
-		char[][] argumentNames = sourceMethod.getArgumentNames();
-		int argumentCount = argumentTypeNames == null ? 0 : argumentTypeNames.length;
-		long position = (long) start << 32 + end;
-		method.arguments = new Argument[argumentCount];
-		for (int i = 0; i < argumentCount; i++) {
-			method.arguments[i] =
-				new Argument(
-					argumentNames[i],
-					position,
-					createTypeReference(argumentTypeNames[i], start, end),
-					AccDefault);
-			// do not care whether was final or not
-		}
-
-		/* convert thrown exceptions */
-		char[][] exceptionTypeNames = sourceMethod.getExceptionTypeNames();
-		int exceptionCount = exceptionTypeNames == null ? 0 : exceptionTypeNames.length;
-		method.thrownExceptions = new TypeReference[exceptionCount];
-		for (int i = 0; i < exceptionCount; i++) {
-			method.thrownExceptions[i] =
-				createTypeReference(exceptionTypeNames[i], start, end);
-		}
-		
-		/* convert local and anonymous types */
-		if (this.needLocalTypes) {
-			IJavaElement[] children = sourceMethod.getChildren();
-			int typesLength = children.length;
-			if (typesLength != 0) {
-				Statement[] statements = new Statement[typesLength];
-				for (int i = 0; i < typesLength; i++) {
-					JavaElement type = (JavaElement)children[i];
-					try {
-						TypeDeclaration localType = convert((SourceTypeElementInfo)type.getElementInfo(), compilationResult);
-						if ((localType.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
-							QualifiedAllocationExpression expression = new QualifiedAllocationExpression(localType);
-							expression.type = localType.superclass;
-							localType.superclass = null;
-							localType.superInterfaces = null;
-							localType.allocation = expression;
-							statements[i] = expression;
-						} else {
-							statements[i] = localType;
-						}
-					} catch (JavaModelException e) {
-						// ignore
-					}
-				}
-				method.statements = statements;
-			}
-		}
-		
-		return method;
-	}
-
-	/*
-	 * Convert a source type info into a parsed type declaration
-	 */
-	private TypeDeclaration convert(SourceTypeElementInfo sourceType, CompilationResult compilationResult) {
-		
-		/* create type declaration - can be member type, local type or anonymous type */
-		TypeDeclaration type = new TypeDeclaration(compilationResult);
-		if (sourceType.getEnclosingType() == null) {
-			IType typeHandle = sourceType.getHandle();
-			try {
-				if (typeHandle.isAnonymous()) {
-					type.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
-					type.bits |= ASTNode.AnonymousAndLocalMask;
-				} else {
-					if (typeHandle.isLocal()) {
-						type.bits |= ASTNode.IsLocalTypeMASK;
-					}
-				}
-			} catch (JavaModelException e) {
-				// could not figure, assume toplevel
-			}
-		}  else {
-			type.bits |= ASTNode.IsMemberTypeMASK;
-		}
-		if ((type.bits & ASTNode.IsAnonymousTypeMASK) == 0) {
-			type.name = sourceType.getName();
-		}
-		int start, end; // only positions available
-		type.sourceStart = start = sourceType.getNameSourceStart();
-		type.sourceEnd = end = sourceType.getNameSourceEnd();
-		type.modifiers = sourceType.getModifiers();
-		type.declarationSourceStart = sourceType.getDeclarationSourceStart();
-		type.declarationSourceEnd = sourceType.getDeclarationSourceEnd();
-		type.bodyEnd = type.declarationSourceEnd;
-
-		/* set superclass and superinterfaces */
-		if (sourceType.getSuperclassName() != null)
-			type.superclass =
-				createTypeReference(sourceType.getSuperclassName(), start, end);
-		char[][] interfaceNames = sourceType.getInterfaceNames();
-		int interfaceCount = interfaceNames == null ? 0 : interfaceNames.length;
-		type.superInterfaces = new TypeReference[interfaceCount];
-		for (int i = 0; i < interfaceCount; i++) {
-			type.superInterfaces[i] = createTypeReference(interfaceNames[i], start, end);
-		}
-		
-		/* convert member types */
-		ISourceType[] sourceMemberTypes = sourceType.getMemberTypes();
-		int sourceMemberTypeCount =
-			sourceMemberTypes == null ? 0 : sourceMemberTypes.length;
-		type.memberTypes = new TypeDeclaration[sourceMemberTypeCount];
-		for (int i = 0; i < sourceMemberTypeCount; i++) {
-			type.memberTypes[i] = convert((SourceTypeElementInfo)sourceMemberTypes[i], compilationResult);
-		}
-		
-		/* convert fields and initializers */
-		ISourceField[] sourceFields = sourceType.getFields();
-		int sourceFieldCount = sourceFields == null ? 0 : sourceFields.length;
-		InitializerElementInfo[] initializers = null;
-		int initializerCount = 0;
-		if (this.needLocalTypes) {
-			initializers = sourceType.getInitializers();
-			initializerCount = initializers.length;
-			type.fields = new FieldDeclaration[initializerCount + sourceFieldCount];
-			for (int i = 0; i < initializerCount; i++) {
-				type.fields[i] = convert(initializers[i], compilationResult);
-			}
-		} else {
-			type.fields = new FieldDeclaration[sourceFieldCount];
-		}
-		int length = initializerCount + sourceFieldCount;
-		int index = 0;
-		for (int i = initializerCount; i < length; i++) {
-			type.fields[i] = convert((SourceFieldElementInfo)sourceFields[index++], compilationResult);
-		}
-
-		/* convert methods - need to add default constructor if necessary */
-		ISourceMethod[] sourceMethods = sourceType.getMethods();
-		int sourceMethodCount = sourceMethods == null ? 0 : sourceMethods.length;
-
-		/* source type has a constructor ?           */
-		/* by default, we assume that one is needed. */
-		int neededCount = 0;
-		if (!type.isInterface()) {
-			neededCount = 1;
-			for (int i = 0; i < sourceMethodCount; i++) {
-				if (sourceMethods[i].isConstructor()) {
-					neededCount = 0;
-					// Does not need the extra constructor since one constructor already exists.
-					break;
-				}
-			}
-		}
-		type.methods = new AbstractMethodDeclaration[sourceMethodCount + neededCount];
-		if (neededCount != 0) { // add default constructor in first position
-			type.methods[0] = type.createsInternalConstructor(false, false);
-		}
-		boolean isInterface = type.isInterface();
-		for (int i = 0; i < sourceMethodCount; i++) {
-			AbstractMethodDeclaration method =convert((SourceMethodElementInfo)sourceMethods[i], compilationResult);
-			if (isInterface || method.isAbstract()) { // fix-up flag 
-				method.modifiers |= AccSemicolonBody;
-			}
-			type.methods[neededCount + i] = method;
-		}
-
-		return type;
-	}
-
-	/*
-	 * Convert a set of source element types into a parsed compilation unit declaration
-	 * The argument types are then all grouped in the same unit. The argument types must 
-	 * at least contain one type.
-	 */
-	private CompilationUnitDeclaration convert(SourceTypeElementInfo[] sourceTypes, CompilationResult compilationResult) {
-		
-		SourceTypeElementInfo sourceType = sourceTypes[0];
-		if (sourceType.getName() == null)
-			return null; // do a basic test that the sourceType is valid
-
-		this.unit = new CompilationUnitDeclaration(this.problemReporter, compilationResult, 0);
-		// not filled at this point
-
-		/* only positions available */
-		int start = sourceType.getNameSourceStart();
-		int end = sourceType.getNameSourceEnd();
-
-		/* convert package and imports */
-		if (sourceType.getPackageName() != null
-			&& sourceType.getPackageName().length > 0)
-			// if its null then it is defined in the default package
-			this.unit.currentPackage =
-				createImportReference(sourceType.getPackageName(), start, end, false, AccDefault);
-		ISourceImport[]  sourceImports = sourceType.getImports();
-		int importCount = sourceImports == null ? 0 : sourceImports.length;
-		this.unit.imports = new ImportReference[importCount];
-		for (int i = 0; i < importCount; i++) {
-			ISourceImport sourceImport = sourceImports[i];
-			this.unit.imports[i] = createImportReference(
-				sourceImport.getName(), 
-				sourceImport.getDeclarationSourceStart(),
-				sourceImport.getDeclarationSourceEnd(),
-				sourceImport.onDemand(),
-				sourceImport.getModifiers());
-		}
-		/* convert type(s) */
-		int typeCount = sourceTypes.length;
-		this.unit.types = new TypeDeclaration[typeCount];
-		for (int i = 0; i < typeCount; i++) {
-			this.unit.types[i] = convert(sourceTypes[i], compilationResult);
-		}
-		return this.unit;
-	}
-
-	/*
-	 * Build an import reference from an import name, e.g. java.lang.*
-	 */
-	private ImportReference createImportReference(
-		char[] importName,
-		int start,
-		int end, 
-		boolean onDemand,
-		int modifiers) {
-	
-		char[][] qImportName = CharOperation.splitOn('.', importName);
-		long[] positions = new long[qImportName.length];
-		long position = (long) start << 32 + end;
-		for (int i = 0; i < qImportName.length; i++) {
-			positions[i] = position; // dummy positions
-		}
-		return new ImportReference(
-			qImportName,
-			positions,
-			onDemand,
-			modifiers);
-	}
-
-	/*
-	 * Build a type reference from a readable name, e.g. java.lang.Object[][]
-	 */
-	private TypeReference createTypeReference(
-		char[] typeSignature,
-		int start,
-		int end) {
-
-		/* count identifiers and dimensions */
-		int max = typeSignature.length;
-		int dimStart = max;
-		int dim = 0;
-		int identCount = 1;
-		for (int i = 0; i < max; i++) {
-			switch (typeSignature[i]) {
-				case '[' :
-					if (dim == 0)
-						dimStart = i;
-					dim++;
-					break;
-				case '.' :
-					identCount++;
-					break;
-			}
-		}
-		/* rebuild identifiers and dimensions */
-		if (identCount == 1) { // simple type reference
-			if (dim == 0) {
-				return new SingleTypeReference(typeSignature, (((long) start )<< 32) + end);
-			} else {
-				char[] identifier = new char[dimStart];
-				System.arraycopy(typeSignature, 0, identifier, 0, dimStart);
-				return new ArrayTypeReference(identifier, dim, (((long) start) << 32) + end);
-			}
-		} else { // qualified type reference
-			long[] positions = new long[identCount];
-			long pos = (((long) start) << 32) + end;
-			for (int i = 0; i < identCount; i++) {
-				positions[i] = pos;
-			}
-			char[][] identifiers =
-				CharOperation.splitOn('.', typeSignature, 0, dimStart);
-			if (dim == 0) {
-				return new QualifiedTypeReference(identifiers, positions);
-			} else {
-				return new ArrayQualifiedTypeReference(identifiers, dim, positions);
-			}
-		}
-	}
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/EnclosingMethodAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/EnclosingMethodAttribute.java
new file mode 100644
index 0000000..5f701bd
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/EnclosingMethodAttribute.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package 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.IEnclosingMethodAttribute;
+
+/**
+ * Default implementation of EnclosingMethodAttribute.
+ * 
+ * @since 3.0
+ */
+public class EnclosingMethodAttribute extends ClassFileAttribute implements IEnclosingMethodAttribute {
+	
+	private int enclosingClassIndex;
+	private char[] enclosingClassName;
+	private int methodDescriptorIndex;
+	private char[] methodDescriptor;
+	private int methodNameIndex;
+	private char[] methodName;
+	private int methodNameAndTypeIndex;
+	
+	EnclosingMethodAttribute(byte[] classFileBytes, IConstantPool constantPool, int offset) throws ClassFormatException {
+		super(classFileBytes, constantPool, offset);
+		int index = u2At(classFileBytes, 6, offset);
+		this.enclosingClassIndex = index;
+		IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(index);
+		if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Class) {
+			throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
+		}
+		this.enclosingClassName = constantPoolEntry.getClassInfoName();
+		this.methodNameAndTypeIndex = u2At(classFileBytes, 8, offset);
+		if (this.methodNameAndTypeIndex != 0) {
+			constantPoolEntry = constantPool.decodeEntry(this.methodNameAndTypeIndex);
+			if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_NameAndType) {
+				throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
+			}
+			this.methodDescriptorIndex = constantPoolEntry.getNameAndTypeInfoDescriptorIndex();
+			this.methodNameIndex = constantPoolEntry.getNameAndTypeInfoNameIndex();
+			constantPoolEntry = constantPool.decodeEntry(this.methodDescriptorIndex);
+			if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Utf8) {
+				throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
+			}
+			this.methodDescriptor = constantPoolEntry.getUtf8Value();
+			constantPoolEntry = constantPool.decodeEntry(this.methodNameIndex);
+			if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Utf8) {
+				throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
+			}
+			this.methodName = constantPoolEntry.getUtf8Value();
+		}
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IEnclosingMethodAttribute#getEnclosingClass()
+	 */
+	public char[] getEnclosingClass() {
+		return this.enclosingClassName;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IEnclosingMethodAttribute#getMethodDeclaringClassDescriptorIndex()
+	 */
+	public int getEnclosingClassIndex() {
+		return this.enclosingClassIndex;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IEnclosingMethodAttribute#getMethodDescriptor()
+	 */
+	public char[] getMethodDescriptor() {
+		return this.methodDescriptor;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IEnclosingMethodAttribute#getMethodDescriptorIndex()
+	 */
+	public int getMethodDescriptorIndex() {
+		return this.methodDescriptorIndex;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IEnclosingMethodAttribute#getMethodName()
+	 */
+	public char[] getMethodName() {
+		return this.methodName;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IEnclosingMethodAttribute#getMethodNameIndex()
+	 */
+	public int getMethodNameIndex() {
+		return this.methodNameIndex;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IEnclosingMethodAttribute#getMethodNameAndTypeIndex()
+	 */
+	public int getMethodNameAndTypeIndex() {
+		return this.methodNameAndTypeIndex;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExceptionAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExceptionAttribute.java
index e9b178f..451e398 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExceptionAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExceptionAttribute.java
@@ -12,7 +12,6 @@
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.util.ClassFormatException;
-import org.eclipse.jdt.core.util.IAttributeNamesConstants;
 import org.eclipse.jdt.core.util.IConstantPool;
 import org.eclipse.jdt.core.util.IConstantPoolConstant;
 import org.eclipse.jdt.core.util.IConstantPoolEntry;
@@ -72,12 +71,4 @@
 	public int getExceptionsNumber() {
 		return this.exceptionsNumber;
 	}
-
-	/**
-	 * @see org.eclipse.jdt.core.util.IClassFileAttribute#getAttributeName()
-	 */
-	public char[] getAttributeName() {
-		return IAttributeNamesConstants.EXCEPTIONS;
-	}
-
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/FieldInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/FieldInfo.java
index 56aed05..7a38b69 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/FieldInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/FieldInfo.java
@@ -18,22 +18,23 @@
 import org.eclipse.jdt.core.util.IConstantPoolEntry;
 import org.eclipse.jdt.core.util.IConstantValueAttribute;
 import org.eclipse.jdt.core.util.IFieldInfo;
+import org.eclipse.jdt.core.util.IModifierConstants;
 
 /**
  * Default implementation of IFieldInfo.
  */
 public class FieldInfo extends ClassFileStruct implements IFieldInfo {
+	private int accessFlags;
+	private int attributeBytes;
+	private IClassFileAttribute[] attributes;
+	private int attributesCount;
+	private IConstantValueAttribute constantValueAttribute;
+	private char[] descriptor;
+	private int descriptorIndex;
 	private boolean isDeprecated;
 	private boolean isSynthetic;
-	private int accessFlags;
 	private char[] name;
-	private char[] descriptor;
 	private int nameIndex;
-	private int descriptorIndex;
-	private int attributesCount;
-	private int attributeBytes;
-	private IConstantValueAttribute constantValueAttribute;
-	private IClassFileAttribute[] attributes;
 	
 	/**
 	 * @param classFileBytes byte[]
@@ -42,22 +43,25 @@
 	 */
 	public FieldInfo(byte classFileBytes[], IConstantPool constantPool, int offset)
 		throws ClassFormatException {
-		this.accessFlags = u2At(classFileBytes, 0, offset);
-
+		final int flags = u2At(classFileBytes, 0, offset);
+		this.accessFlags = flags;
+		if ((flags & IModifierConstants.ACC_SYNTHETIC) != 0) {
+			this.isSynthetic = true;
+		}
 		this.nameIndex = u2At(classFileBytes, 2, offset);
 		IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(this.nameIndex);
 		if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Utf8) {
 			throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
 		}
 		this.name = constantPoolEntry.getUtf8Value();
-
+	
 		this.descriptorIndex = u2At(classFileBytes, 4, offset);
 		constantPoolEntry = constantPool.decodeEntry(this.descriptorIndex);
 		if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Utf8) {
 			throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
 		}
 		this.descriptor = constantPoolEntry.getUtf8Value();
-
+	
 		this.attributesCount = u2At(classFileBytes, 6, offset);
 		this.attributes = ClassFileAttribute.NO_ATTRIBUTES;
 		int readOffset = 8;
@@ -80,6 +84,12 @@
 			} else if (equals(attributeName, IAttributeNamesConstants.CONSTANT_VALUE)) {
 				this.constantValueAttribute = new ConstantValueAttribute(classFileBytes, constantPool, offset + readOffset);
 				this.attributes[attributesIndex++] = this.constantValueAttribute;
+			} else if (equals(attributeName, IAttributeNamesConstants.SIGNATURE)) {
+				this.attributes[attributesIndex++] = new SignatureAttribute(classFileBytes, constantPool, offset + readOffset);
+			} else if (equals(attributeName, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS)) {
+				this.attributes[attributesIndex++] = new RuntimeVisibleAnnotationsAttribute(classFileBytes, constantPool, offset + readOffset);
+			} else if (equals(attributeName, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS)) {
+				this.attributes[attributesIndex++] = new RuntimeInvisibleAnnotationsAttribute(classFileBytes, constantPool, offset + readOffset);
 			} else {
 				this.attributes[attributesIndex++] = new ClassFileAttribute(classFileBytes, constantPool, offset + readOffset);
 			}
@@ -94,6 +104,19 @@
 	public int getAccessFlags() {
 		return this.accessFlags;
 	}
+	/**
+	 * @see IFieldInfo#getAttributeCount()
+	 */
+	public int getAttributeCount() {
+		return this.attributesCount;
+	}
+
+	/**
+	 * @see IFieldInfo#getAttributes()
+	 */
+	public IClassFileAttribute[] getAttributes() {
+		return this.attributes;
+	}
 
 	/**
 	 * @see IFieldInfo#getConstantValueAttribute()
@@ -110,6 +133,13 @@
 	}
 
 	/**
+	 * @see IFieldInfo#getDescriptorIndex()
+	 */
+	public int getDescriptorIndex() {
+		return this.descriptorIndex;
+	}
+
+	/**
 	 * @see IFieldInfo#getName()
 	 */
 	public char[] getName() {
@@ -117,6 +147,12 @@
 	}
 
 	/**
+	 * @see IFieldInfo#getNameIndex()
+	 */
+	public int getNameIndex() {
+		return this.nameIndex;
+	}
+	/**
 	 * @see IFieldInfo#hasConstantValueAttribute()
 	 */
 	public boolean hasConstantValueAttribute() {
@@ -140,32 +176,4 @@
 	int sizeInBytes() {
 		return this.attributeBytes;
 	}
-	/**
-	 * @see IFieldInfo#getAttributeCount()
-	 */
-	public int getAttributeCount() {
-		return this.attributesCount;
-	}
-
-	/**
-	 * @see IFieldInfo#getDescriptorIndex()
-	 */
-	public int getDescriptorIndex() {
-		return this.descriptorIndex;
-	}
-
-	/**
-	 * @see IFieldInfo#getNameIndex()
-	 */
-	public int getNameIndex() {
-		return this.nameIndex;
-	}
-
-	/**
-	 * @see IFieldInfo#getAttributes()
-	 */
-	public IClassFileAttribute[] getAttributes() {
-		return this.attributes;
-	}
-
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java
index fac7046..813b9dc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java
@@ -12,7 +12,6 @@
 
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Map;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
@@ -20,7 +19,6 @@
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.Path;
-import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IClassFile;
 import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.ICompilationUnit;
@@ -34,23 +32,14 @@
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.ast.*;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ASTNode;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.Initializer;
-import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
-import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
 import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
 import org.eclipse.jdt.internal.compiler.lookup.Scope;
 import org.eclipse.jdt.internal.core.*;
-import org.eclipse.jdt.internal.core.JavaElement;
 import org.eclipse.jdt.internal.core.JavaModel;
 import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.JavaProject;
@@ -72,7 +61,7 @@
 	/**
 	 * Cache package handles to optimize memory.
 	 */
-	private Map packageHandles;
+	private HashtableOfArrayToObject packageHandles;
 
 	private JavaModel javaModel;
 
@@ -102,44 +91,59 @@
 					return null; // match is outside classpath
 				this.lastPkgFragmentRootPath= jarPath;
 				this.lastPkgFragmentRoot= root;
-				this.packageHandles= new HashMap(5);
+				this.packageHandles= new HashtableOfArrayToObject(5);
 			}
 			// create handle
 			String classFilePath= resourcePath.substring(separatorIndex + 1);
-			int lastSlash= classFilePath.lastIndexOf('/');
-			String packageName= lastSlash > -1 ? classFilePath.substring(0, lastSlash).replace('/', '.') : IPackageFragment.DEFAULT_PACKAGE_NAME;
-			IPackageFragment pkgFragment= (IPackageFragment) this.packageHandles.get(packageName);
-			if (pkgFragment == null) {
-				pkgFragment= this.lastPkgFragmentRoot.getPackageFragment(packageName);
-				this.packageHandles.put(packageName, pkgFragment);
+			String[] simpleNames = new Path(classFilePath).segments();
+			String[] pkgName;
+			int length = simpleNames.length-1;
+			if (length > 0) {
+				pkgName = new String[length];
+				System.arraycopy(simpleNames, 0, pkgName, 0, length);
+			} else {
+				pkgName = CharOperation.NO_STRINGS;
 			}
-			IClassFile classFile= pkgFragment.getClassFile(classFilePath.substring(lastSlash + 1));
+			IPackageFragment pkgFragment= (IPackageFragment) this.packageHandles.get(pkgName);
+			if (pkgFragment == null) {
+				pkgFragment= ((PackageFragmentRoot) this.lastPkgFragmentRoot).getPackageFragment(pkgName);
+				this.packageHandles.put(pkgName, pkgFragment);
+			}
+			IClassFile classFile= pkgFragment.getClassFile(simpleNames[length]);
 			return (Openable) classFile;
 		} else {
 			// path to a file in a directory
 			// Optimization: cache package fragment root handle and package handles
-			int length = -1;
+			int rootPathLength = -1;
 			if (this.lastPkgFragmentRootPath == null 
 				|| !(resourcePath.startsWith(this.lastPkgFragmentRootPath) 
-					&& (length = this.lastPkgFragmentRootPath.length()) > 0
-					&& resourcePath.charAt(length) == '/')) {
+					&& (rootPathLength = this.lastPkgFragmentRootPath.length()) > 0
+					&& resourcePath.charAt(rootPathLength) == '/')) {
 				IPackageFragmentRoot root= this.getPkgFragmentRoot(resourcePath);
 				if (root == null)
 					return null; // match is outside classpath
-				this.lastPkgFragmentRoot= root;
-				this.lastPkgFragmentRootPath= this.lastPkgFragmentRoot.getPath().toString();
-				this.packageHandles= new HashMap(5);
+				this.lastPkgFragmentRoot = root;
+				this.lastPkgFragmentRootPath = this.lastPkgFragmentRoot.getPath().toString();
+				this.packageHandles = new HashtableOfArrayToObject(5);
 			}
 			// create handle
-			int lastSlash= resourcePath.lastIndexOf(IPath.SEPARATOR);
-			String packageName= lastSlash > (length= this.lastPkgFragmentRootPath.length()) ? resourcePath.substring(length + 1, lastSlash).replace(IPath.SEPARATOR, '.') : IPackageFragment.DEFAULT_PACKAGE_NAME;
-			IPackageFragment pkgFragment= (IPackageFragment) this.packageHandles.get(packageName);
-			if (pkgFragment == null) {
-				pkgFragment= this.lastPkgFragmentRoot.getPackageFragment(packageName);
-				this.packageHandles.put(packageName, pkgFragment);
+			resourcePath = resourcePath.substring(this.lastPkgFragmentRootPath.length() + 1);
+			String[] simpleNames = new Path(resourcePath).segments();
+			String[] pkgName;
+			int length = simpleNames.length-1;
+			if (length > 0) {
+				pkgName = new String[length];
+				System.arraycopy(simpleNames, 0, pkgName, 0, length);
+			} else {
+				pkgName = CharOperation.NO_STRINGS;
 			}
-			String simpleName= resourcePath.substring(lastSlash + 1);
-			if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(simpleName)) {
+			IPackageFragment pkgFragment= (IPackageFragment) this.packageHandles.get(pkgName);
+			if (pkgFragment == null) {
+				pkgFragment= ((PackageFragmentRoot) this.lastPkgFragmentRoot).getPackageFragment(pkgName);
+				this.packageHandles.put(pkgName, pkgFragment);
+			}
+			String simpleName= simpleNames[length];
+			if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(simpleName)) {
 				ICompilationUnit unit= pkgFragment.getCompilationUnit(simpleName);
 				return (Openable) unit;
 			} else {
@@ -149,242 +153,6 @@
 		}
 	}
 	
-	/*
-	 * Returns an element handle corresponding to the given ASTNode in the given parsed unit.
-	 * Returns null if the given ASTNode could not be found.
-	 */
-	public IJavaElement createElement(final ASTNode toBeFound, CompilationUnitDeclaration parsedUnit, Openable openable) {
-		class EndVisit extends RuntimeException {
-			// marker to stop traversing ast
-		}
-		class Visitor extends ASTVisitor {
-		    ASTNode[] nodeStack = new ASTNode[10];
-		    int nodeIndex = -1;
-			
-		    public void push(ASTNode node) {
-		    	if (++this.nodeIndex >= this.nodeStack.length) 
-		            System.arraycopy(this.nodeStack, 0, this.nodeStack = new ASTNode[this.nodeStack.length*2], 0, this.nodeIndex-1);
-	            this.nodeStack[this.nodeIndex] = node;
-		    }
-		    
-		    public void pop(ASTNode node) {
-		    	while (this.nodeIndex >= 0 && this.nodeStack[this.nodeIndex--] != node){/*empty*/}
-		    }
-		    
-			public boolean visit(Argument node, BlockScope scope) {
-			    push(node);
-				if (node == toBeFound) throw new EndVisit();
-				return true;
-			}
-			public void endVisit(Argument node, BlockScope scope) {
-			    pop(node);
-            }
-
-			public boolean visit(ConstructorDeclaration node, ClassScope scope) {
-			    push(node);
-				if (node == toBeFound) throw new EndVisit();
-				return true;
-			}
-			public void endVisit(ConstructorDeclaration node, ClassScope scope) {
-				pop(node);
-			}
-
-			public boolean visit(FieldDeclaration node, MethodScope scope) {
-			    push(node);
-				if (node == toBeFound) throw new EndVisit();
-				return true;
-			}
-			public void endVisit(FieldDeclaration node, MethodScope scope) {
-			    pop(node);
-			}
-
-			public boolean visit(Initializer node, MethodScope scope) {
-			    push(node);
-				if (node == toBeFound) throw new EndVisit();
-				return true;
-			}
-			// don't pop initializers (used to count how many occurrences are in the type)
-
-			public boolean visit(LocalDeclaration node, BlockScope scope) {
-			    push(node);
-				if (node == toBeFound) throw new EndVisit();
-				return true;
-			}
-			public void endVisit(LocalDeclaration node, BlockScope scope) {
-			    pop(node);
-            }
-
-			public boolean visit(TypeDeclaration node, BlockScope scope) {
-			    push(node);
-				if (node == toBeFound) throw new EndVisit();
-				return true;
-			}
-			public void endVisit(TypeDeclaration node, BlockScope scope) {
-				if ((node.bits & ASTNode.IsMemberTypeMASK) != 0) {
-				    pop(node);
-				}
-				// don't pop local/anonymous types (used to count how many occurrences are in the method)
-			}
-
-			public boolean visit(TypeDeclaration node, ClassScope scope) {
-			    push(node);
-				if (node == toBeFound) throw new EndVisit();
-				return true;
-			}
-			public void endVisit(TypeDeclaration node, ClassScope scope) {
-				if ((node.bits & ASTNode.IsMemberTypeMASK) != 0) {
-				    pop(node);
-				}
-				// don't pop local/anonymous types (used to count how many occurrences are in the initializer)
-			}
-
-			public boolean visit(MethodDeclaration node, ClassScope scope) {
-			    push(node);
-				if (node == toBeFound) throw new EndVisit();
-				return true;
-			}
-			public void endVisit(MethodDeclaration node, ClassScope scope) {
-				pop(node);
-			}
-
-			public boolean visit(TypeDeclaration node, CompilationUnitScope scope) {
-			    push(node);
-				if (node == toBeFound) throw new EndVisit();
-				return true;
-			}
-			public void endVisit(TypeDeclaration node, CompilationUnitScope scope) {
-				pop(node);
-			}
-
-		}
-		Visitor visitor = new Visitor();
-		try {
-			parsedUnit.traverse(visitor, parsedUnit.scope);
-		} catch (EndVisit e) {
-		    ASTNode[] nodeStack = visitor.nodeStack;
-		    int end = visitor.nodeIndex;
-		    int start = 0;
-		    
-		    // find the inner most type declaration if binary type
-		    ASTNode typeDecl = null;
-		    if (openable instanceof ClassFile) {
-				for (int i = end; i >= 0; i--) {
-				    if (nodeStack[i] instanceof TypeDeclaration) {
-				        typeDecl = nodeStack[i];
-				        start = i;
-				        break;
-				    }
-				}
-		    }
-			
-			// find the openable corresponding to this type declaration
-			if (typeDecl != null) {
-			    openable = getOpenable(typeDecl, openable);
-			}
-			
-			return createElement(nodeStack, start, end, openable);
-		}
-		return null;
-	}
-	private IJavaElement createElement(ASTNode[] nodeStack, int start, int end, IJavaElement parent) {
-		if (start > end) return parent;
-        ASTNode node = nodeStack[start];
-        IJavaElement element = parent;
-		switch(parent.getElementType()) {
-	        case IJavaElement.COMPILATION_UNIT:
-	            String typeName = new String(((TypeDeclaration)node).name);
-	        	element = ((ICompilationUnit)parent).getType(typeName);
-	        	break;
-	        case IJavaElement.CLASS_FILE:
-	            try {
-                    element = ((IClassFile)parent).getType();
-                } catch (JavaModelException e) {
-					// class file doesn't exist: ignore
-                }
-                break;
-            case IJavaElement.TYPE:
-                IType type = (IType)parent;
-                if (node instanceof ConstructorDeclaration) {
-	 				element = type.getMethod(
-						parent.getElementName(), 
-						Util.typeParameterSignatures((ConstructorDeclaration)node));
-				} else if (node instanceof MethodDeclaration) {
-				    MethodDeclaration method = (MethodDeclaration)node;
-					element = type.getMethod(
-						new String(method.selector), 
-						Util.typeParameterSignatures(method));
-				} else if (node instanceof Initializer) {
-				    int occurrenceCount = 1;
-				    while (start < end) {
-				        if (nodeStack[start+1] instanceof Initializer) {
-				            start++;
-				        	occurrenceCount++;
-				    	} else {
-				            break;
-				    	}
-				    }
-				    element = type.getInitializer(occurrenceCount);
-                } else if (node instanceof FieldDeclaration) {
-                    String fieldName = new String(((FieldDeclaration)node).name);
-                    element = type.getField(fieldName);
-                } else if (node instanceof TypeDeclaration) {
-					typeName = new String(((TypeDeclaration)node).name);
-                    element = type.getType(typeName);
-                }
-                break;
-			case IJavaElement.FIELD:
-			    IField field = (IField)parent;
-			    if (field.isBinary()) {
-			        return null;
-			    } else {
-					// child of a field can only be anonymous type
-					element = field.getType("", 1); //$NON-NLS-1$
-			    }
-				break;
-			case IJavaElement.METHOD:
-			case IJavaElement.INITIALIZER:
-				IMember member = (IMember)parent;
-				if (node instanceof TypeDeclaration) {
-				    if (member.isBinary()) {
-				        return null;
-				    } else {
-					    int typeIndex = start;
-					    while (typeIndex <= end) {
-					        ASTNode typeDecl = nodeStack[typeIndex+1];
-					        if (typeDecl instanceof TypeDeclaration && (typeDecl.bits & ASTNode.AnonymousAndLocalMask) != 0) {
-					            typeIndex++;
-					    	} else {
-					            break;
-					    	}
-					    }
-					    char[] name = ((TypeDeclaration)nodeStack[typeIndex]).name;
-					    int occurrenceCount = 1;
-						for (int i = start; i < typeIndex; i++) {
-						    if (CharOperation.equals(name, ((TypeDeclaration)nodeStack[i]).name)) {
-						        occurrenceCount++;
-						    }
-						}
-						start = typeIndex;
-						typeName = (node.bits & ASTNode.IsAnonymousTypeMASK) != 0 ? "" : new String(name); //$NON-NLS-1$
-						element = member.getType(typeName, occurrenceCount);
-				    }
-				} else if (node instanceof LocalDeclaration) {
-				    if (start == end) {
-					    LocalDeclaration local = (LocalDeclaration)node;
-						element = new LocalVariable(
-								(JavaElement)parent, 
-								new String(local.name), 
-								local.declarationSourceStart,
-								local.declarationSourceEnd,
-								local.sourceStart,
-								local.sourceEnd,
-								Util.typeSignature(local.type));
-				    } // else the next node is an anonymous (initializer of the local variable)
-				}
-				break;
- 	    }
-	   return createElement(nodeStack, start+1, end, element);
-	}
 	/**
 	 * Returns a handle denoting the class member identified by its scope.
 	 */
@@ -421,7 +189,7 @@
 							newElement = member.getType(new String(scope.enclosingSourceType().sourceName), 1);
 							// increment occurrence count if collision is detected
 							if (newElement != null) {
-								while (!existingElements.add(newElement)) ((JavaElement)newElement).occurrenceCount++;
+								while (!existingElements.add(newElement)) ((SourceRefElement)newElement).occurrenceCount++;
 							}
 					    }
 						break;						
@@ -440,13 +208,17 @@
 					for (int i = 0, length = type.fields.length; i < length; i++) {
 						FieldDeclaration field = type.fields[i];
 						if (field.declarationSourceStart < elementPosition && field.declarationSourceEnd > elementPosition) {
-							if (field.isField()) {
-								newElement = parentType.getField(new String(field.name));
-							} else {
-								newElement = parentType.getInitializer(occurenceCount);
+							switch (field.getKind()) {
+								case AbstractVariableDeclaration.FIELD :
+								case AbstractVariableDeclaration.ENUM_CONSTANT :
+									newElement = parentType.getField(new String(field.name));
+									break;
+								case AbstractVariableDeclaration.INITIALIZER :
+									newElement = parentType.getInitializer(occurenceCount);
+									break;
 							}
 							break;
-						} else if (!field.isField()) {
+						} else if (field.getKind() == AbstractVariableDeclaration.INITIALIZER) {
 							occurenceCount++;
 						}
 					}
@@ -552,41 +324,6 @@
 		}
 		return null;
 	}
-
-	/*
-	 * Returns the openable that contains the given AST node.
-	 */
-	private Openable getOpenable(ASTNode toBeFound, Openable openable) {
-	    if (openable instanceof ClassFile) {
-	        try {
-	            int sourceStart = toBeFound.sourceStart;
-	            int sourceEnd = toBeFound.sourceEnd;
-	            ClassFile classFile = (ClassFile)openable;
-                ISourceRange sourceRange = classFile.getType().getSourceRange();
-                int offset = sourceRange.getOffset();
-                if (offset == sourceStart && offset + sourceRange.getLength() != sourceEnd) {
-                    return openable;
-                } else {
-                    String prefix = classFile.getTopLevelTypeName() + '$';
-                    IPackageFragment pkg = (IPackageFragment)classFile.getParent();
-                    IClassFile[] children = pkg.getClassFiles();
-                    for (int i = 0, length = children.length; i < length; i++) {
-                        IClassFile child = children[i];
-                        if (child.getElementName().startsWith(prefix)) {
-			                sourceRange = child.getType().getSourceRange();
-			                offset = sourceRange.getOffset();
-                        	if (offset == sourceStart && offset + sourceRange.getLength() != sourceEnd) {
-                        	    return (Openable)child;
-                        	}
-                        }
-                    }
-                }
-            } catch (JavaModelException e) {
-                // class file doesn't exist: ignore
-            }
-	    }
-	    return openable;
-	}
 	
 	/**
 	 * Returns the package fragment root that contains the given resource path.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HashtableOfArrayToObject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HashtableOfArrayToObject.java
new file mode 100644
index 0000000..fa4b732
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HashtableOfArrayToObject.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+/**
+ * Hashtable of {Object[] --> Object }
+ */
+public final class HashtableOfArrayToObject implements Cloneable {
+	
+	// to avoid using Enumerations, walk the individual tables skipping nulls
+	public Object[][] keyTable;
+	public Object[] valueTable;
+
+	public int elementSize; // number of elements in the table
+	int threshold;
+
+	public HashtableOfArrayToObject() {
+		this(13);
+	}
+
+	public HashtableOfArrayToObject(int size) {
+
+		this.elementSize = 0;
+		this.threshold = size; // size represents the expected number of elements
+		int extraRoom = (int) (size * 1.75f);
+		if (this.threshold == extraRoom)
+			extraRoom++;
+		this.keyTable = new Object[extraRoom][];
+		this.valueTable = new Object[extraRoom];
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		HashtableOfArrayToObject result = (HashtableOfArrayToObject) super.clone();
+		result.elementSize = this.elementSize;
+		result.threshold = this.threshold;
+
+		int length = this.keyTable.length;
+		result.keyTable = new Object[length][];
+		System.arraycopy(this.keyTable, 0, result.keyTable, 0, length);
+
+		length = this.valueTable.length;
+		result.valueTable = new Object[length];
+		System.arraycopy(this.valueTable, 0, result.valueTable, 0, length);
+		return result;
+	}
+
+	public boolean containsKey(Object[] key) {
+
+		int index = hashCode(key) % this.valueTable.length;
+		int keyLength = key.length;
+		Object[] currentKey;
+		while ((currentKey = this.keyTable[index]) != null) {
+			if (currentKey.length == keyLength && Util.equalArraysOrNull(currentKey, key))
+				return true;
+			index = (index + 1) % this.keyTable.length;
+		}
+		return false;
+	}
+
+	public Object get(Object[] key) {
+
+		int index = hashCode(key) % this.valueTable.length;
+		int keyLength = key.length;
+		Object[] currentKey;
+		while ((currentKey = this.keyTable[index]) != null) {
+			if (currentKey.length == keyLength && Util.equalArraysOrNull(currentKey, key))
+				return this.valueTable[index];
+			index = (index + 1) % keyTable.length;
+		}
+		return null;
+	}
+
+	public Object[] getKey(Object[] key, int keyLength) {
+
+		int index = hashCode(key, keyLength) % this.valueTable.length;
+		Object[] currentKey;
+		while ((currentKey = this.keyTable[index]) != null) {
+			if (currentKey.length == keyLength && Util.equalArrays(currentKey, key, keyLength))
+				return currentKey;
+			index = (index + 1) % this.keyTable.length;
+		}
+		return null;
+	}
+
+	private int hashCode(Object[] element) {
+		return hashCode(element, element.length);
+	}
+	
+	private int hashCode(Object[] element, int length) {
+		int hash = 0;
+		for (int i = 0; i < length; i++)
+			hash = Util.combineHashCodes(hash, element[i].hashCode());
+		return hash & 0x7FFFFFFF;
+	}
+	
+	public Object put(Object[] key, Object value) {
+
+		int index = hashCode(key) % this.valueTable.length;
+		int keyLength = key.length;
+		Object[] currentKey;
+		while ((currentKey = this.keyTable[index]) != null) {
+			if (currentKey.length == keyLength && Util.equalArraysOrNull(currentKey, key))
+				return this.valueTable[index] = value;
+			index = (index + 1) % keyTable.length;
+		}
+		this.keyTable[index] = key;
+		this.valueTable[index] = value;
+
+		// assumes the threshold is never equal to the size of the table
+		if (++this.elementSize > threshold)
+			rehash();
+		return value;
+	}
+
+	public Object removeKey(Object[] key) {
+
+		int index = hashCode(key) % this.valueTable.length;
+		int keyLength = key.length;
+		Object[] currentKey;
+		while ((currentKey = this.keyTable[index]) != null) {
+			if (currentKey.length == keyLength && Util.equalArraysOrNull(currentKey, key)) {
+				Object value = this.valueTable[index];
+				this.elementSize--;
+				this.keyTable[index] = null;
+				this.valueTable[index] = null;
+				rehash();
+				return value;
+			}
+			index = (index + 1) % this.keyTable.length;
+		}
+		return null;
+	}
+
+	private void rehash() {
+
+		HashtableOfArrayToObject newHashtable = new HashtableOfArrayToObject(elementSize * 2);		// double the number of expected elements
+		Object[] currentKey;
+		for (int i = this.keyTable.length; --i >= 0;)
+			if ((currentKey = this.keyTable[i]) != null)
+				newHashtable.put(currentKey, this.valueTable[i]);
+
+		this.keyTable = newHashtable.keyTable;
+		this.valueTable = newHashtable.valueTable;
+		this.threshold = newHashtable.threshold;
+	}
+
+	public int size() {
+		return elementSize;
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		Object[] element;
+		for (int i = 0, length = this.keyTable.length; i < length; i++)
+			if ((element = this.keyTable[i]) != null) {
+				buffer.append('{');
+				for (int j = 0, length2 = element.length; j < length2; j++) {
+					buffer.append(element[j]);
+					if (j != length2-1) 
+						buffer.append(", "); //$NON-NLS-1$
+				}
+				buffer.append("} -> ");  //$NON-NLS-1$
+				buffer.append(this.valueTable[i]);
+				if (i != length-1)
+					buffer.append('\n');
+			}
+		return buffer.toString();
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/InnerClassesAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/InnerClassesAttribute.java
index 3ce5827..1b891e9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/InnerClassesAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/InnerClassesAttribute.java
@@ -37,8 +37,7 @@
 		throws ClassFormatException {
 		super(classFileBytes, constantPool, offset);
 		this.numberOfClasses = u2At(classFileBytes, 6, offset);
-		int length = this.numberOfClasses;
-		this.entries = NO_ENTRIES;
+		final int length = this.numberOfClasses;
 		if (length != 0) {
 			int readOffset = 8;
 			this.entries = new IInnerClassesAttributeEntry[length];
@@ -46,6 +45,8 @@
 				this.entries[i] = new InnerClassesAttributeEntry(classFileBytes, constantPool, offset + readOffset);
 				readOffset += 8;
 			}		
+		} else {
+			this.entries = NO_ENTRIES;
 		}
 	}
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LineNumberAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LineNumberAttribute.java
index 3b6820e..19a94f0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LineNumberAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LineNumberAttribute.java
@@ -11,7 +11,6 @@
 package org.eclipse.jdt.internal.core.util;
 
 import org.eclipse.jdt.core.util.ClassFormatException;
-import org.eclipse.jdt.core.util.IAttributeNamesConstants;
 import org.eclipse.jdt.core.util.IConstantPool;
 import org.eclipse.jdt.core.util.ILineNumberAttribute;
 
@@ -40,26 +39,20 @@
 		throws ClassFormatException {
 		super(classFileBytes, constantPool, offset);
 		
-		this.lineNumberTableLength = u2At(classFileBytes, 6, offset);
-		this.lineNumberTable = NO_ENTRIES;
-		if (this.lineNumberTableLength != 0) {
-			this.lineNumberTable = new int[this.lineNumberTableLength][2];
-		}
-		int readOffset = 8;
-		for (int i = 0, max = this.lineNumberTableLength; i < max; i++) {
-			this.lineNumberTable[i][0] = u2At(classFileBytes, readOffset, offset);
-			this.lineNumberTable[i][1] = u2At(classFileBytes, readOffset + 2, offset);
-			readOffset += 4;
+		final int length = u2At(classFileBytes, 6, offset);
+		this.lineNumberTableLength = length;
+		if (length != 0) {
+			this.lineNumberTable = new int[length][2];
+			int readOffset = 8;
+			for (int i = 0; i < length; i++) {
+				this.lineNumberTable[i][0] = u2At(classFileBytes, readOffset, offset);
+				this.lineNumberTable[i][1] = u2At(classFileBytes, readOffset + 2, offset);
+				readOffset += 4;
+			}
+		} else {
+			this.lineNumberTable = NO_ENTRIES;
 		}
 	}
-
-	/**
-	 * @see org.eclipse.jdt.core.util.IClassFileAttribute#getAttributeName()
-	 */
-	public char[] getAttributeName() {
-		return IAttributeNamesConstants.LINE_NUMBER;
-	}
-
 	/**
 	 * @see ILineNumberAttribute#getLineNumberTable()
 	 */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableAttribute.java
index 8ca2c27..d82413c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableAttribute.java
@@ -11,7 +11,6 @@
 package org.eclipse.jdt.internal.core.util;
 
 import org.eclipse.jdt.core.util.ClassFormatException;
-import org.eclipse.jdt.core.util.IAttributeNamesConstants;
 import org.eclipse.jdt.core.util.IConstantPool;
 import org.eclipse.jdt.core.util.ILocalVariableAttribute;
 import org.eclipse.jdt.core.util.ILocalVariableTableEntry;
@@ -40,26 +39,19 @@
 		int offset)
 		throws ClassFormatException {
 		super(classFileBytes, constantPool, offset);
-		this.localVariableTableLength = u2At(classFileBytes, 6, offset);
-		int readOffset = 8;
-		int length = this.localVariableTableLength;
-		this.localVariableTable = NO_ENTRIES;
+		final int length = u2At(classFileBytes, 6, offset);
+		this.localVariableTableLength = length;
 		if (length != 0) {
-			this.localVariableTable = new LocalVariableTableEntry[length];
-		}
-		for (int i = 0; i < length; i++) {
-			this.localVariableTable[i] = new LocalVariableTableEntry(classFileBytes, constantPool, offset + readOffset);
-			readOffset += 10;
+			int readOffset = 8;
+			this.localVariableTable = new ILocalVariableTableEntry[length];
+			for (int i = 0; i < length; i++) {
+				this.localVariableTable[i] = new LocalVariableTableEntry(classFileBytes, constantPool, offset + readOffset);
+				readOffset += 10;
+			}
+		} else {
+			this.localVariableTable = NO_ENTRIES;
 		}
 	}
-
-	/**
-	 * @see org.eclipse.jdt.core.util.IClassFileAttribute#getAttributeName()
-	 */
-	public char[] getAttributeName() {
-		return IAttributeNamesConstants.LOCAL_VARIABLE;
-	}
-
 	/**
 	 * @see ILocalVariableAttribute#getLocalVariableTable()
 	 */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTypeAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTypeAttribute.java
new file mode 100644
index 0000000..e776134
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTypeAttribute.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package 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.ILocalVariableTypeTableAttribute;
+import org.eclipse.jdt.core.util.ILocalVariableTypeTableEntry;
+
+/**
+ * Default implementation of ILocalVariableTypeAttribute.
+ */
+public class LocalVariableTypeAttribute
+	extends ClassFileAttribute
+	implements ILocalVariableTypeTableAttribute {
+
+	private static final ILocalVariableTypeTableEntry[] NO_ENTRIES = new ILocalVariableTypeTableEntry[0];
+	private int localVariableTypeTableLength;
+	private ILocalVariableTypeTableEntry[] localVariableTypeTableEntries;
+	
+	/**
+	 * Constructor for LocalVariableTypeAttribute.
+	 * @param classFileBytes
+	 * @param constantPool
+	 * @param offset
+	 * @throws ClassFormatException
+	 */
+	public LocalVariableTypeAttribute(
+		byte[] classFileBytes,
+		IConstantPool constantPool,
+		int offset)
+		throws ClassFormatException {
+		super(classFileBytes, constantPool, offset);
+		final int length = u2At(classFileBytes, 6, offset);
+		this.localVariableTypeTableLength = length;
+		if (length != 0) {
+			int readOffset = 8;
+			this.localVariableTypeTableEntries = new ILocalVariableTypeTableEntry[length];
+			for (int i = 0; i < length; i++) {
+				this.localVariableTypeTableEntries[i] = new LocalVariableTypeTableEntry(classFileBytes, constantPool, offset + readOffset);
+				readOffset += 10;
+			}
+		} else {
+			this.localVariableTypeTableEntries = NO_ENTRIES;
+		}
+	}
+	/**
+	 * @see ILocalVariableTypeTableAttribute#getLocalVariableTypeTable()
+	 */
+	public ILocalVariableTypeTableEntry[] getLocalVariableTypeTable() {
+		return this.localVariableTypeTableEntries;
+	}
+
+	/**
+	 * @see ILocalVariableTypeTableAttribute#getLocalVariableTypeTableLength()
+	 */
+	public int getLocalVariableTypeTableLength() {
+		return this.localVariableTypeTableLength;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTypeTableEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTypeTableEntry.java
new file mode 100644
index 0000000..a2390c3
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTypeTableEntry.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package 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.ILocalVariableTypeTableEntry;
+
+/**
+ * Default implementation of ILocalVariableTypeTableEntry
+ */
+public class LocalVariableTypeTableEntry extends ClassFileStruct implements ILocalVariableTypeTableEntry {
+
+	private int startPC;
+	private int length;
+	private int nameIndex;
+	private int signatureIndex;
+	private char[] name;
+	private char[] signature;
+	private int index;
+	
+	/**
+	 * Constructor for LocalVariableTypeTableEntry.
+	 * 
+	 * @param classFileBytes
+	 * @param constantPool
+	 * @param offset
+	 * @throws ClassFormatException
+	 */
+	public LocalVariableTypeTableEntry(
+		byte[] classFileBytes,
+		IConstantPool constantPool,
+		int offset) throws ClassFormatException {
+			this.startPC = u2At(classFileBytes, 0, offset);
+			this.length = u2At(classFileBytes, 2, offset);
+			this.nameIndex = u2At(classFileBytes, 4, offset);
+			this.signatureIndex = u2At(classFileBytes, 6, offset);
+			this.index = u2At(classFileBytes, 8, offset);
+			IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(this.nameIndex);
+			if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Utf8) {
+				throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
+			}
+			this.name = constantPoolEntry.getUtf8Value();
+			constantPoolEntry = constantPool.decodeEntry(this.signatureIndex);
+			if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Utf8) {
+				throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
+			}
+			this.signature = constantPoolEntry.getUtf8Value();
+		}
+		
+	/**
+	 * @see ILocalVariableTypeTableEntry#getStartPC()
+	 */
+	public int getStartPC() {
+		return this.startPC;
+	}
+
+	/**
+	 * @see ILocalVariableTypeTableEntry#getLength()
+	 */
+	public int getLength() {
+		return this.length;
+	}
+
+	/**
+	 * @see ILocalVariableTypeTableEntry#getNameIndex()
+	 */
+	public int getNameIndex() {
+		return this.nameIndex;
+	}
+
+	/**
+	 * @see ILocalVariableTypeTableEntry#getSignatureIndex()
+	 */
+	public int getSignatureIndex() {
+		return this.signatureIndex;
+	}
+
+	/**
+	 * @see ILocalVariableTypeTableEntry#getIndex()
+	 */
+	public int getIndex() {
+		return this.index;
+	}
+
+	/**
+	 * @see ILocalVariableTypeTableEntry#getName()
+	 */
+	public char[] getName() {
+		return this.name;
+	}
+
+	/**
+	 * @see ILocalVariableTypeTableEntry#getSignature()
+	 */
+	public char[] getSignature() {
+		return this.signature;
+	}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java
index d053a83..bac7c0c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java
@@ -27,6 +27,7 @@
 	private static final String PACKAGEDECLARATION = Character.toString(JavaElement.JEM_PACKAGEDECLARATION);
 	private static final String IMPORTDECLARATION = Character.toString(JavaElement.JEM_IMPORTDECLARATION);
 	private static final String LOCALVARIABLE = Character.toString(JavaElement.JEM_LOCALVARIABLE);
+	private static final String TYPE_PARAMETER = Character.toString(JavaElement.JEM_TYPE_PARAMETER);
 
 	private final char[] memento;
 	private final int length;
@@ -76,6 +77,8 @@
 				return IMPORTDECLARATION;
 			case JavaElement.JEM_LOCALVARIABLE:
 				return LOCALVARIABLE;
+			case JavaElement.JEM_TYPE_PARAMETER:
+				return TYPE_PARAMETER;
 		}
 		loop: while (this.index < this.length) {
 			switch (this.memento[this.index]) {
@@ -97,6 +100,7 @@
 				case JavaElement.JEM_PACKAGEDECLARATION:
 				case JavaElement.JEM_IMPORTDECLARATION:
 				case JavaElement.JEM_LOCALVARIABLE:
+				case JavaElement.JEM_TYPE_PARAMETER:
 					break loop;
 			}
 			this.index++;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MethodInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MethodInfo.java
index 84186c0..283f7ab 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MethodInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MethodInfo.java
@@ -26,18 +26,18 @@
  * Default implementation of IMethodInfo.
  */
 public class MethodInfo extends ClassFileStruct implements IMethodInfo {
+	private int accessFlags;
+	private int attributeBytes;
+	private IClassFileAttribute[] attributes;
+	private int attributesCount;
+	private ICodeAttribute codeAttribute;
+	private char[] descriptor;
+	private int descriptorIndex;
+	private IExceptionAttribute exceptionAttribute;
 	private boolean isDeprecated;
 	private boolean isSynthetic;
-	private int accessFlags;
 	private char[] name;
-	private char[] descriptor;
 	private int nameIndex;
-	private int descriptorIndex;
-	private int attributesCount;
-	private int attributeBytes;
-	private ICodeAttribute codeAttribute;
-	private IExceptionAttribute exceptionAttribute;
-	private IClassFileAttribute[] attributes;
 	
 	/**
 	 * @param classFileBytes byte[]
@@ -49,7 +49,11 @@
 		throws ClassFormatException {
 			
 		boolean no_code_attribute = (decodingFlags & IClassFileReader.METHOD_BODIES) == 0;
-		this.accessFlags = u2At(classFileBytes, 0, offset);
+		final int flags = u2At(classFileBytes, 0, offset);
+		this.accessFlags = flags;
+		if ((flags & IModifierConstants.ACC_SYNTHETIC) != 0) {
+			this.isSynthetic = true;
+		}
 		
 		this.nameIndex = u2At(classFileBytes, 2, offset);
 		IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(this.nameIndex);
@@ -98,6 +102,18 @@
 			} else if (equals(attributeName, IAttributeNamesConstants.EXCEPTIONS)) {
 				this.exceptionAttribute = new ExceptionAttribute(classFileBytes, constantPool, offset + readOffset);
 				this.attributes[attributesIndex++] = this.exceptionAttribute;
+			} else if (equals(attributeName, IAttributeNamesConstants.SIGNATURE)) {
+				this.attributes[attributesIndex++] = new SignatureAttribute(classFileBytes, constantPool, offset + readOffset);
+			} else if (equals(attributeName, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS)) {
+				this.attributes[attributesIndex++] = new RuntimeVisibleAnnotationsAttribute(classFileBytes, constantPool, offset + readOffset);
+			} else if (equals(attributeName, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS)) {
+				this.attributes[attributesIndex++] = new RuntimeInvisibleAnnotationsAttribute(classFileBytes, constantPool, offset + readOffset);
+			} else if (equals(attributeName, IAttributeNamesConstants.RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS)) {
+				this.attributes[attributesIndex++] = new RuntimeVisibleParameterAnnotationsAttribute(classFileBytes, constantPool, offset + readOffset);
+			} else if (equals(attributeName, IAttributeNamesConstants.RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS)) {
+				this.attributes[attributesIndex++] = new RuntimeInvisibleParameterAnnotationsAttribute(classFileBytes, constantPool, offset + readOffset);
+			} else if (equals(attributeName, IAttributeNamesConstants.ANNOTATION_DEFAULT)) {
+				this.attributes[attributesIndex++] = new AnnotationDefaultAttribute(classFileBytes, constantPool, offset + readOffset);
 			} else {
 				this.attributes[attributesIndex++] = new ClassFileAttribute(classFileBytes, constantPool, offset + readOffset);
 			}
@@ -113,6 +129,19 @@
 	}
 
 	/**
+	 * @see IMethodInfo#getAttributeCount()
+	 */
+	public int getAttributeCount() {
+		return this.attributesCount;
+	}
+	/**
+	 * @see IMethodInfo#getAttributes()
+	 */
+	public IClassFileAttribute[] getAttributes() {
+		return this.attributes;
+	}
+
+	/**
 	 * @see IMethodInfo#getCodeAttribute()
 	 */
 	public ICodeAttribute getCodeAttribute() {
@@ -127,6 +156,20 @@
 	}
 
 	/**
+	 * @see IMethodInfo#getDescriptorIndex()
+	 */
+	public int getDescriptorIndex() {
+		return this.descriptorIndex;
+	}
+
+	/**
+	 * @see IMethodInfo#getExceptionAttribute()
+	 */
+	public IExceptionAttribute getExceptionAttribute() {
+		return this.exceptionAttribute;
+	}
+
+	/**
 	 * @see IMethodInfo#getName()
 	 */
 	public char[] getName() {
@@ -134,6 +177,17 @@
 	}
 
 	/**
+	 * @see IMethodInfo#getNameIndex()
+	 */
+	public int getNameIndex() {
+		return this.nameIndex;
+	}
+
+	private boolean isAbstract() {
+		return (this.accessFlags & IModifierConstants.ACC_ABSTRACT) != 0;
+	}
+
+	/**
 	 * @see IMethodInfo#isClinit()
 	 */
 	public boolean isClinit() {
@@ -153,6 +207,10 @@
 	public boolean isDeprecated() {
 		return this.isDeprecated;
 	}
+	
+	private boolean isNative() {
+		return (this.accessFlags & IModifierConstants.ACC_NATIVE) != 0;
+	}
 
 	/**
 	 * @see IMethodInfo#isSynthetic()
@@ -161,49 +219,7 @@
 		return this.isSynthetic;
 	}
 
-	/**
-	 * @see IMethodInfo#getExceptionAttribute()
-	 */
-	public IExceptionAttribute getExceptionAttribute() {
-		return this.exceptionAttribute;
-	}
-
-	/**
-	 * @see IMethodInfo#getAttributeCount()
-	 */
-	public int getAttributeCount() {
-		return this.attributesCount;
-	}
-
-	/**
-	 * @see IMethodInfo#getDescriptorIndex()
-	 */
-	public int getDescriptorIndex() {
-		return this.descriptorIndex;
-	}
-
-	/**
-	 * @see IMethodInfo#getNameIndex()
-	 */
-	public int getNameIndex() {
-		return this.nameIndex;
-	}
-
 	int sizeInBytes() {
 		return this.attributeBytes;
 	}
-	/**
-	 * @see IMethodInfo#getAttributes()
-	 */
-	public IClassFileAttribute[] getAttributes() {
-		return this.attributes;
-	}
-
-	private boolean isAbstract() {
-		return (this.accessFlags & IModifierConstants.ACC_ABSTRACT) != 0;
-	}
-	
-	private boolean isNative() {
-		return (this.accessFlags & IModifierConstants.ACC_NATIVE) != 0;
-	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ParameterAnnotation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ParameterAnnotation.java
new file mode 100644
index 0000000..c79ac6f
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ParameterAnnotation.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 Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IAnnotation;
+import org.eclipse.jdt.core.util.IConstantPool;
+import org.eclipse.jdt.core.util.IParameterAnnotation;
+
+/**
+ * Default implementation of IParameterAnnotation
+ */
+public class ParameterAnnotation extends ClassFileStruct implements IParameterAnnotation {
+
+	private static final IAnnotation[] NO_ENTRIES = new IAnnotation[0];
+	
+	private int annotationsNumber;
+	private IAnnotation[] annotations;
+	private int readOffset;
+	
+	/**
+	 * Constructor for Annotation.
+	 * 
+	 * @param classFileBytes
+	 * @param constantPool
+	 * @param offset
+	 * @throws ClassFormatException
+	 */
+	public ParameterAnnotation(
+			byte[] classFileBytes,
+			IConstantPool constantPool,
+			int offset) throws ClassFormatException {
+		
+		final int length = u2At(classFileBytes, 0, offset);
+		this.readOffset = 2;
+		this.annotationsNumber = length;
+		if (length != 0) {
+			this.annotations = new IAnnotation[length];
+			for (int i = 0; i < length; i++) {
+				Annotation annotation = new Annotation(classFileBytes, constantPool, offset + readOffset);
+				this.annotations[i++] = annotation;
+				this.readOffset += annotation.sizeInBytes();
+			}
+		} else {
+			this.annotations = NO_ENTRIES;
+		}
+	}
+	
+	int sizeInBytes() {
+		return this.readOffset;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IParameterAnnotation#getAnnotations()
+	 */
+	public IAnnotation[] getAnnotations() {
+		return this.annotations;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IParameterAnnotation#getAnnotationsNumber()
+	 */
+	public int getAnnotationsNumber() {
+		return this.annotationsNumber;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
index d90b1ca..389bce5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
@@ -16,9 +16,11 @@
 import org.eclipse.jdt.core.compiler.IScanner;
 import org.eclipse.jdt.core.compiler.ITerminalSymbols;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.parser.NLSLine;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
 
 public class PublicScanner implements IScanner, ITerminalSymbols {
 
@@ -30,13 +32,15 @@
 	 - sourceStart gives the position into the stream
 	 - currentPosition-1 gives the sourceEnd position into the stream 
 	*/
-
+	protected long sourceLevel;
 	// 1.4 feature 
-	private boolean assertMode = false;
 	public boolean useAssertAsAnIndentifier = false;
 	//flag indicating if processed source contains occurrences of keyword assert 
 	public boolean containsAssertKeyword = false; 
 	
+	// 1.5 feature
+	public boolean useEnumAsAnIndentifier = false;
+	
 	public boolean recordLineSeparator = false;
 	public char currentCharacter;
 	public int startPosition;
@@ -97,6 +101,7 @@
 	public static final String UNTERMINATED_STRING = "Unterminated_String"; //$NON-NLS-1$
 	public static final String UNTERMINATED_COMMENT = "Unterminated_Comment"; //$NON-NLS-1$
 	public static final String INVALID_CHAR_IN_STRING = "Invalid_Char_In_String"; //$NON-NLS-1$
+	public static final String INVALID_DIGIT = "Invalid_Digit"; //$NON-NLS-1$	
 
 	//----------------optimized identifier managment------------------
 	static final char[] charArray_a = new char[] {'a'}, 
@@ -133,7 +138,7 @@
 	public /*static*/ final char[][][][] charArray_length = 
 		new char[OptimizedLength][TableSize][InternalTableSize][]; 
 	// support for detecting non-externalized string literals
-	NLSLine currentLine= null;
+	public NLSLine currentLine= null;
 	public static final String TAG_PREFIX= "//$NON-NLS-"; //$NON-NLS-1$
 	public static final int TAG_PREFIX_LENGTH= TAG_PREFIX.length();
 	public static final String TAG_POSTFIX= "$"; //$NON-NLS-1$
@@ -142,6 +147,9 @@
 	public boolean checkNonExternalizedStringLiterals = false;
 	public boolean wasNonExternalizedStringLiteral = false;
 	
+	// generic support
+	public boolean returnOnlyGreater = false;
+	
 	/*static*/ {
 		for (int i = 0; i < 6; i++) {
 			for (int j = 0; j < TableSize; j++) {
@@ -179,7 +187,7 @@
 	this.tokenizeComments = tokenizeComments;
 	this.tokenizeWhiteSpace = tokenizeWhiteSpace;
 	this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
-	this.assertMode = sourceLevel >= ClassFileConstants.JDK1_4;
+	this.sourceLevel = sourceLevel;
 	this.taskTags = taskTags;
 	this.taskPriorities = taskPriorities;
 	this.isTaskCaseSensitive = isTaskCaseSensitive;
@@ -192,7 +200,7 @@
 	return this.source.length == this.currentPosition;
 }
 
-private void checkNonExternalizedString() {
+protected void checkNonExternalizedString() {
 	if (this.currentLine == null) 
 		return;
 	parseTags(this.currentLine);
@@ -662,7 +670,7 @@
 		return -1;
 	}
 }
-public final boolean getNextCharAsDigit() {
+public final boolean getNextCharAsDigit() throws InvalidInputException {
 	//BOOLEAN
 	//handle the case of unicode.
 	//when a unicode appears then we must use a buffer that holds char internal values
@@ -698,7 +706,7 @@
 			}
 
 			this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
-			if (!Character.isDigit(this.currentCharacter)) {
+			if (!isDigit(this.currentCharacter)) {
 				this.currentPosition = temp;
 				return false;
 			}
@@ -713,7 +721,7 @@
 			return true;
 		} //-------------end unicode traitement--------------
 		else {
-			if (!Character.isDigit(this.currentCharacter)) {
+			if (!isDigit(this.currentCharacter)) {
 				this.currentPosition = temp;
 				return false;
 			}
@@ -921,6 +929,13 @@
 			// ---------Identify the next token-------------
 
 			switch (this.currentCharacter) {
+				case '@' :
+/*					if (this.sourceLevel >= ClassFileConstants.JDK1_5) {
+						return TokenNameAT;
+					} else {
+						return TokenNameERROR;
+					}*/
+					return TokenNameAT;
 				case '(' :
 					return TokenNameLPAREN;
 				case ')' :
@@ -938,9 +953,37 @@
 				case ',' :
 					return TokenNameCOMMA;
 				case '.' :
-					if (getNextCharAsDigit())
+					if (getNextCharAsDigit()) {
 						return scanNumber(true);
-					return TokenNameDOT;
+					}
+/*					if (this.sourceLevel >= ClassFileConstants.JDK1_5) {
+						int temp = this.currentPosition;
+						if (getNextChar('.')) {
+							if (getNextChar('.')) {
+								return TokenNameELLIPSIS;
+							} else {
+								this.currentPosition = temp;
+								return TokenNameDOT;
+							}
+						} else {
+							this.currentPosition = temp;
+							return TokenNameDOT;
+						}
+					} else {
+						return TokenNameDOT;
+					}*/
+					int temp = this.currentPosition;
+					if (getNextChar('.')) {
+						if (getNextChar('.')) {
+							return TokenNameELLIPSIS;
+						} else {
+							this.currentPosition = temp;
+							return TokenNameDOT;
+						}
+					} else {
+						this.currentPosition = temp;
+						return TokenNameDOT;
+					}
 				case '+' :
 					{
 						int test;
@@ -988,6 +1031,9 @@
 				case '>' :
 					{
 						int test;
+						if (this.returnOnlyGreater) {
+							return TokenNameGREATER;
+						}
 						if ((test = getNextChar('=', '>')) == 0)
 							return TokenNameGREATER_EQUAL;
 						if (test > 0) {
@@ -1363,7 +1409,9 @@
 								if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
 									checkNonExternalizedString();
 									if (this.recordLineSeparator) {
-										if (!isUnicode) {
+										if (isUnicode) {
+											pushUnicodeLineSeparator();
+										} else {
 											pushLineSeparator();
 										}
 									} else {
@@ -1393,7 +1441,9 @@
 									if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
 										checkNonExternalizedString();
 										if (this.recordLineSeparator) {
-											if (!isUnicode) {
+											if (isUnicode) {
+												pushUnicodeLineSeparator();
+											} else {
 												pushLineSeparator();
 											}
 										} else {
@@ -1446,8 +1496,9 @@
 				default :
 					if (Character.isJavaIdentifierStart(this.currentCharacter))
 						return scanIdentifierOrKeyword();
-					if (Character.isDigit(this.currentCharacter))
+					if (isDigit(this.currentCharacter)) {
 						return scanNumber(false);
+					}						
 					return TokenNameERROR;
 			}
 		}
@@ -1509,7 +1560,26 @@
 public char[] getSource(){
 	return this.source;
 }
-
+protected boolean isDigit(char c) throws InvalidInputException {
+	if (Character.isDigit(c)) {
+		switch(c) {
+			case '0' :
+			case '1' :
+			case '2' :
+			case '3' :
+			case '4' :
+			case '5' :
+			case '6' :
+			case '7' :
+			case '8' :
+			case '9' :
+				return true;
+		}
+		throw new InvalidInputException(Scanner.INVALID_DIGIT);
+	} else {
+		return false;
+	}
+}
 /* Tokenize a method body, assuming that curly brackets are properly balanced.
  */
 public final void jumpOverMethodBody() {
@@ -1837,7 +1907,7 @@
 						scanIdentifierOrKeyword();
 						break;
 					}
-					if (Character.isDigit(this.currentCharacter)) {
+					if (isDigit(this.currentCharacter)) {
 						try {
 							scanNumber(false);
 						} catch (InvalidInputException ex) {
@@ -2141,7 +2211,7 @@
 	newEntry6 = max;
 	return r;	
 }
-private void parseTags(NLSLine line) {
+protected void parseTags(NLSLine line) {
 	String s = new String(getCurrentTokenSource());
 	int pos = s.indexOf(TAG_PREFIX);
 	int lineLength = line.size();
@@ -2351,11 +2421,11 @@
 			int number = Character.getNumericValue(this.currentCharacter);
 			if (number >= 0 && number <= 7) {
 				boolean zeroToThreeNot = number > 3;
-				if (Character.isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
+				if (isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
 					int digit = Character.getNumericValue(this.currentCharacter);
 					if (digit >= 0 && digit <= 7) {
 						number = (number * 8) + digit;
-						if (Character.isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
+						if (isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
 							if (zeroToThreeNot) {// has read \NotZeroToThree OctalDigit Digit --> ignore last character
 								this.currentPosition--;
 							} else {
@@ -2390,6 +2460,7 @@
 	//keywors with the same length AND the same first char, then do another
 	//dispatch on the second char 
 	this.useAssertAsAnIndentifier = false;
+	this.useEnumAsAnIndentifier = false;
 	while (getNextCharAsJavaIdentifierPart()){/*empty*/}
 
 	int index, length;
@@ -2436,7 +2507,7 @@
 						&& (data[++index] == 'e')
 						&& (data[++index] == 'r')
 						&& (data[++index] == 't')) {
-							if (this.assertMode) {
+							if (this.sourceLevel >= ClassFileConstants.JDK1_4) {
 								this.containsAssertKeyword = true;
 								return TokenNameassert;
 							} else {
@@ -2561,8 +2632,18 @@
 				case 4 :
 					if ((data[++index] == 'l') && (data[++index] == 's') && (data[++index] == 'e'))
 						return TokenNameelse;
-					else
-						return TokenNameIdentifier;
+					else if ((data[index] == 'n')
+						&& (data[++index] == 'u')
+						&& (data[++index] == 'm')) {
+							if (this.sourceLevel >= ClassFileConstants.JDK1_5) {
+								return TokenNameenum;
+							} else {
+								this.useEnumAsAnIndentifier = true;
+								return TokenNameIdentifier;								
+							}
+						} else {
+							return TokenNameIdentifier;
+						}
 				case 7 :
 					if ((data[++index] == 'x')
 						&& (data[++index] == 't')
@@ -2962,25 +3043,114 @@
 	boolean floating = dotPrefix;
 	if ((!dotPrefix) && (this.currentCharacter == '0')) {
 		if (getNextChar('x', 'X') >= 0) { //----------hexa-----------------
-			//force the first char of the hexa number do exist...
-			// consume next character
-			this.unicodeAsBackSlash = false;
-			if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
-				&& (this.source[this.currentPosition] == 'u')) {
-				getNextUnicodeChar();
-			} else {
-				if (this.withoutUnicodePtr != 0) {
-					unicodeStoreAt(++this.withoutUnicodePtr);
-				}
-			}
-			if (Character.digit(this.currentCharacter, 16) == -1)
-				throw new InvalidInputException(INVALID_HEXA);
-			//---end forcing--
+			int start = this.currentPosition;
 			while (getNextCharAsDigit(16)){/*empty*/}
-			if (getNextChar('l', 'L') >= 0)
+			int end = this.currentPosition;
+			if (getNextChar('l', 'L') >= 0) {
+				if (end == start) {
+					throw new InvalidInputException(INVALID_HEXA);
+				}
 				return TokenNameLongLiteral;
-			else
+			} else if (getNextChar('.')) {
+				if (this.sourceLevel < ClassFileConstants.JDK1_5) {
+					// if we are in source level < 1.5, we report an integer literal
+					this.currentPosition = end;
+					return TokenNameIntegerLiteral;
+				}
+				// hexadeciman floating point literal
+				// read decimal part
+				boolean hasNoDigitsBeforeDot = end == start;
+				start = this.currentPosition;
+				while (getNextCharAsDigit(16)){/*empty*/}
+				end = this.currentPosition;
+				if (hasNoDigitsBeforeDot && end == start) {
+					throw new InvalidInputException(INVALID_HEXA);
+				}
+				
+				if (getNextChar('p', 'P') >= 0) { // consume next character
+					this.unicodeAsBackSlash = false;
+					if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+						&& (this.source[this.currentPosition] == 'u')) {
+						getNextUnicodeChar();
+					} else {
+						if (this.withoutUnicodePtr != 0) {
+							unicodeStoreAt(++this.withoutUnicodePtr);
+						}
+					}
+
+					if ((this.currentCharacter == '-')
+						|| (this.currentCharacter == '+')) { // consume next character
+						this.unicodeAsBackSlash = false;
+						if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+							&& (this.source[this.currentPosition] == 'u')) {
+							getNextUnicodeChar();
+						} else {
+							if (this.withoutUnicodePtr != 0) {
+								unicodeStoreAt(++this.withoutUnicodePtr);
+							}
+						}
+					}
+					if (!isDigit(this.currentCharacter)) {
+						throw new InvalidInputException(INVALID_HEXA);
+					}
+					while (getNextCharAsDigit()){/*empty*/}
+					if (getNextChar('f', 'F') >= 0) {
+						return TokenNameFloatingPointLiteral;
+					}
+					if (getNextChar('d', 'D') >= 0) {
+						return TokenNameDoubleLiteral;
+					}
+					if (getNextChar('l', 'L') >= 0) {
+						throw new InvalidInputException(INVALID_HEXA);
+					}					
+					return TokenNameDoubleLiteral;
+				} else {
+					throw new InvalidInputException(INVALID_HEXA);
+				}
+			} else if (getNextChar('p', 'P') >= 0) { // consume next character
+				if (this.sourceLevel < ClassFileConstants.JDK1_5) {
+					// if we are in source level < 1.5 we report an integer literal
+					this.currentPosition = end;
+					return TokenNameIntegerLiteral;
+				}
+				this.unicodeAsBackSlash = false;
+				if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+					&& (this.source[this.currentPosition] == 'u')) {
+					getNextUnicodeChar();
+				} else {
+					if (this.withoutUnicodePtr != 0) {
+						unicodeStoreAt(++this.withoutUnicodePtr);
+					}
+				}
+
+				if ((this.currentCharacter == '-')
+					|| (this.currentCharacter == '+')) { // consume next character
+					this.unicodeAsBackSlash = false;
+					if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+						&& (this.source[this.currentPosition] == 'u')) {
+						getNextUnicodeChar();
+					} else {
+						if (this.withoutUnicodePtr != 0) {
+							unicodeStoreAt(++this.withoutUnicodePtr);
+						}
+					}
+				}
+				if (!isDigit(this.currentCharacter))
+					throw new InvalidInputException(INVALID_FLOAT);
+				while (getNextCharAsDigit()){/*empty*/}
+				if (getNextChar('f', 'F') >= 0)
+					return TokenNameFloatingPointLiteral;
+				if (getNextChar('d', 'D') >= 0)
+					return TokenNameDoubleLiteral;
+				if (getNextChar('l', 'L') >= 0) {
+					throw new InvalidInputException(INVALID_HEXA);
+				}
+				return TokenNameDoubleLiteral;
+			} else {
+				if (end == start)
+					throw new InvalidInputException(INVALID_HEXA);
 				return TokenNameIntegerLiteral;
+			}
 		}
 
 		//there is x or X in the number
@@ -3028,7 +3198,7 @@
 							}
 						}
 					}
-					if (!Character.isDigit(this.currentCharacter))
+					if (!isDigit(this.currentCharacter))
 						throw new InvalidInputException(INVALID_FLOAT);
 					while (getNextCharAsDigit()){/*empty*/}
 				}
@@ -3080,7 +3250,7 @@
 				}
 			}
 		}
-		if (!Character.isDigit(this.currentCharacter))
+		if (!isDigit(this.currentCharacter))
 			throw new InvalidInputException(INVALID_FLOAT);
 		while (getNextCharAsDigit()){/*empty*/}
 	}
@@ -3138,6 +3308,21 @@
 	this.eofPosition = sourceLength;
 	this.initialPosition = this.currentPosition = 0;
 	this.containsAssertKeyword = false;
+	this.linePtr = -1;	
+}
+
+/*
+ * Should be used if a parse (usually a diet parse) has already been performed on the unit, 
+ * so as to get the already computed line end positions.
+ */
+public final void setSource(CompilationResult compilationResult) {
+	char[] contents = compilationResult.compilationUnit.getContents();
+	setSource(contents);
+	int[] lineSeparatorPositions = compilationResult.lineSeparatorPositions;
+	if (lineSeparatorPositions != null) {
+		this.lineEnds = lineSeparatorPositions;
+		this.linePtr = lineSeparatorPositions.length - 1;
+	}
 }
 
 public String toString() {
@@ -3177,7 +3362,7 @@
 		+ "<-- Ends here\n===============================\n" //$NON-NLS-1$
 		+ new String(end); 
 }
-public final String toStringAction(int act) {
+public String toStringAction(int act) {
 	switch (act) {
 		case TokenNameIdentifier :
 			return "Identifier(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeInvisibleAnnotationsAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeInvisibleAnnotationsAttribute.java
new file mode 100644
index 0000000..3644b28
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeInvisibleAnnotationsAttribute.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IAnnotation;
+import org.eclipse.jdt.core.util.IConstantPool;
+import org.eclipse.jdt.core.util.IRuntimeInvisibleAnnotationsAttribute;
+
+/**
+ * Default implementation of IRuntimeInvisibleAnnotations
+ */
+public class RuntimeInvisibleAnnotationsAttribute
+	extends ClassFileAttribute
+	implements IRuntimeInvisibleAnnotationsAttribute {
+
+	private static final IAnnotation[] NO_ENTRIES = new IAnnotation[0];
+	private int annotationsNumber;
+	private IAnnotation[] annotations;
+	
+	/**
+	 * Constructor for RuntimeInvisibleAnnotations.
+	 * @param classFileBytes
+	 * @param constantPool
+	 * @param offset
+	 * @throws ClassFormatException
+	 */
+	public RuntimeInvisibleAnnotationsAttribute(
+			byte[] classFileBytes,
+			IConstantPool constantPool,
+			int offset)
+			throws ClassFormatException {
+		super(classFileBytes, constantPool, offset);
+		final int length = u2At(classFileBytes, 6, offset);
+		this.annotationsNumber = length;
+		if (length != 0) {
+			int readOffset = 8;
+			this.annotations = new IAnnotation[length];
+			for (int i = 0; i < length; i++) {
+				Annotation annotation = new Annotation(classFileBytes, constantPool, offset + readOffset);
+				this.annotations[i] = annotation;
+				readOffset += annotation.sizeInBytes();
+			}
+		} else {
+			this.annotations = NO_ENTRIES;
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IRuntimeInvisibleAnnotations#getAnnotations()
+	 */
+	public IAnnotation[] getAnnotations() {
+		return this.annotations;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IRuntimeInvisibleAnnotations#getAnnotationsNumber()
+	 */
+	public int getAnnotationsNumber() {
+		return this.annotationsNumber;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeInvisibleParameterAnnotationsAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeInvisibleParameterAnnotationsAttribute.java
new file mode 100644
index 0000000..def1d59
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeInvisibleParameterAnnotationsAttribute.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package 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.IParameterAnnotation;
+import org.eclipse.jdt.core.util.IRuntimeInvisibleParameterAnnotationsAttribute;
+
+/**
+ * Default implementation of IRuntimeInvisibleParameterAnnotations
+ */
+public class RuntimeInvisibleParameterAnnotationsAttribute
+	extends ClassFileAttribute
+	implements IRuntimeInvisibleParameterAnnotationsAttribute {
+
+	private static final IParameterAnnotation[] NO_ENTRIES = new IParameterAnnotation[0];
+	private IParameterAnnotation[] parameterAnnotations;
+	private int parametersNumber;
+	
+	/**
+	 * Constructor for RuntimeVisibleParameterAnnotations.
+	 * @param classFileBytes
+	 * @param constantPool
+	 * @param offset
+	 * @throws ClassFormatException
+	 */
+	public RuntimeInvisibleParameterAnnotationsAttribute(
+		byte[] classFileBytes,
+		IConstantPool constantPool,
+		int offset)
+		throws ClassFormatException {
+		super(classFileBytes, constantPool, offset);
+		final int length = u1At(classFileBytes, 6, offset);
+		this.parametersNumber = length;
+		if (length != 0) {
+			int readOffset = 7;
+			this.parameterAnnotations = new IParameterAnnotation[length];
+			for (int i = 0; i < length; i++) {
+				ParameterAnnotation parameterAnnotation = new ParameterAnnotation(classFileBytes, constantPool, offset + readOffset);
+				this.parameterAnnotations[i] = parameterAnnotation;
+				readOffset += parameterAnnotation.sizeInBytes();
+			}
+		} else {
+			this.parameterAnnotations = NO_ENTRIES;
+		}
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IRuntimeInvisibleParameterAnnotations#getAnnotations()
+	 */
+	public IParameterAnnotation[] getParameterAnnotations() {
+		return this.parameterAnnotations;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IRuntimeInvisibleParameterAnnotations#getParametersNumber()
+	 */
+	public int getParametersNumber() {
+		return this.parametersNumber;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeVisibleAnnotationsAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeVisibleAnnotationsAttribute.java
new file mode 100644
index 0000000..a56d40d
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeVisibleAnnotationsAttribute.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IAnnotation;
+import org.eclipse.jdt.core.util.IConstantPool;
+import org.eclipse.jdt.core.util.IRuntimeVisibleAnnotationsAttribute;
+
+/**
+ * Default implementation of IRuntimeVisibleAnnotations
+ */
+public class RuntimeVisibleAnnotationsAttribute
+	extends ClassFileAttribute
+	implements IRuntimeVisibleAnnotationsAttribute {
+
+	private static final IAnnotation[] NO_ENTRIES = new IAnnotation[0];
+	private int annotationsNumber;
+	private IAnnotation[] annotations;
+	
+	/**
+	 * Constructor for RuntimeVisibleAnnotations.
+	 * @param classFileBytes
+	 * @param constantPool
+	 * @param offset
+	 * @throws ClassFormatException
+	 */
+	public RuntimeVisibleAnnotationsAttribute(
+		byte[] classFileBytes,
+		IConstantPool constantPool,
+		int offset)
+		throws ClassFormatException {
+		super(classFileBytes, constantPool, offset);
+		final int length = u2At(classFileBytes, 6, offset);
+		this.annotationsNumber = length;
+		if (length != 0) {
+			int readOffset = 8;
+			this.annotations = new IAnnotation[length];
+			for (int i = 0; i < length; i++) {
+				Annotation annotation = new Annotation(classFileBytes, constantPool, offset + readOffset);
+				this.annotations[i] = annotation;
+				readOffset += annotation.sizeInBytes();
+			}
+		} else {
+			this.annotations = NO_ENTRIES;
+		}
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IRuntimeVisibleAnnotations#getAnnotations()
+	 */
+	public IAnnotation[] getAnnotations() {
+		return this.annotations;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IRuntimeVisibleAnnotations#getAnnotationsNumber()
+	 */
+	public int getAnnotationsNumber() {
+		return this.annotationsNumber;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeVisibleParameterAnnotationsAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeVisibleParameterAnnotationsAttribute.java
new file mode 100644
index 0000000..ec17be2
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeVisibleParameterAnnotationsAttribute.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package 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.IParameterAnnotation;
+import org.eclipse.jdt.core.util.IRuntimeVisibleParameterAnnotationsAttribute;
+
+/**
+ * Default implementation of IRuntimeVisibleAnnotations
+ */
+public class RuntimeVisibleParameterAnnotationsAttribute
+	extends ClassFileAttribute
+	implements IRuntimeVisibleParameterAnnotationsAttribute {
+
+	private static final IParameterAnnotation[] NO_ENTRIES = new IParameterAnnotation[0];
+	private int parametersNumber;
+	private IParameterAnnotation[] parameterAnnotations;
+	
+	/**
+	 * Constructor for RuntimeVisibleParameterAnnotations.
+	 * @param classFileBytes
+	 * @param constantPool
+	 * @param offset
+	 * @throws ClassFormatException
+	 */
+	public RuntimeVisibleParameterAnnotationsAttribute(
+		byte[] classFileBytes,
+		IConstantPool constantPool,
+		int offset)
+		throws ClassFormatException {
+		super(classFileBytes, constantPool, offset);
+		final int length = u1At(classFileBytes, 6, offset);
+		this.parametersNumber = length;
+		if (length != 0) {
+			int readOffset = 7;
+			this.parameterAnnotations = new IParameterAnnotation[length];
+			for (int i = 0; i < length; i++) {
+				ParameterAnnotation parameterAnnotation = new ParameterAnnotation(classFileBytes, constantPool, offset + readOffset);
+				this.parameterAnnotations[i] = parameterAnnotation;
+				readOffset += parameterAnnotation.sizeInBytes();
+			}
+		} else {
+			this.parameterAnnotations = NO_ENTRIES;
+		}
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IRuntimeVisibleParameterAnnotations#getAnnotations()
+	 */
+	public IParameterAnnotation[] getParameterAnnotations() {
+		return this.parameterAnnotations;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.IRuntimeVisibleParameterAnnotations#getParametersNumber()
+	 */
+	public int getParametersNumber() {
+		return this.parametersNumber;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SignatureAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SignatureAttribute.java
new file mode 100644
index 0000000..b04b091
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SignatureAttribute.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package 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.ISignatureAttribute;
+
+/**
+ * @since 3.0
+ */
+public class SignatureAttribute extends ClassFileAttribute implements ISignatureAttribute {
+	
+	private int signatureIndex;
+	private char[] signature;
+	
+	SignatureAttribute(byte[] classFileBytes, IConstantPool constantPool, int offset) throws ClassFormatException {
+		super(classFileBytes, constantPool, offset);
+		final int index = u2At(classFileBytes, 6, offset);
+		this.signatureIndex = index;
+		IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(index);
+		if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Utf8) {
+			throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
+		}
+		this.signature = constantPoolEntry.getUtf8Value();
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.ISignatureAttribute#getSignatureIndex()
+	 */
+	public int getSignatureIndex() {
+		return this.signatureIndex;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.util.ISignatureAttribute#getSignature()
+	 */
+	public char[] getSignature() {
+		return this.signature;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SourceFileAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SourceFileAttribute.java
index 43d151c..1aa89da 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SourceFileAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SourceFileAttribute.java
@@ -11,7 +11,6 @@
 package org.eclipse.jdt.internal.core.util;
 
 import org.eclipse.jdt.core.util.ClassFormatException;
-import org.eclipse.jdt.core.util.IAttributeNamesConstants;
 import org.eclipse.jdt.core.util.IConstantPool;
 import org.eclipse.jdt.core.util.IConstantPoolConstant;
 import org.eclipse.jdt.core.util.IConstantPoolEntry;
@@ -47,14 +46,6 @@
 		}
 		this.sourceFileName = constantPoolEntry.getUtf8Value();
 	}
-
-	/**
-	 * @see org.eclipse.jdt.core.util.IClassFileAttribute#getAttributeName()
-	 */
-	public char[] getAttributeName() {
-		return IAttributeNamesConstants.SOURCE;
-	}
-
 	/**
 	 * @see ISourceAttribute#getSourceFileIndex()
 	 */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java
index 58f6713..dee5905 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java
@@ -15,6 +15,7 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
+import org.eclipse.core.resources.*;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IResource;
@@ -31,6 +32,7 @@
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.Assert;
 import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.PackageFragmentRoot;
@@ -67,8 +69,9 @@
 	private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
 	private static final String EMPTY_ARGUMENT = "   "; //$NON-NLS-1$
 	
-	public static final String[] fgEmptyStringArray = new String[0];
 	private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
+	
+	public static char[][] JAVA_LIKE_EXTENSIONS = {SuffixConstants.SUFFIX_java, SuffixConstants.SUFFIX_JAVA};
 
 	static {
 		relocalize();
@@ -79,6 +82,55 @@
 	}
 	
 	/**
+	 * Returns a new array adding the second array at the end of first array.
+	 * It answers null if the first and second are null.
+	 * If the first array is null or if it is empty, then a new array is created with second.
+	 * If the second array is null, then the first array is returned.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    first = null
+	 *    second = "a"
+	 *    => result = {"a"}
+	 * </pre>
+	 * <li><pre>
+	 *    first = {"a"}
+	 *    second = null
+	 *    => result = {"a"}
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = {"a"}
+	 *    second = {"b"}
+	 *    => result = {"a", "b"}
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param first the first array to concatenate
+	 * @param second the array to add at the end of the first array
+	 * @return a new array adding the second array at the end of first array, or null if the two arrays are null.
+	 */
+	public static final String[] arrayConcat(String[] first, String second) {
+		if (second == null)
+			return first;
+		if (first == null)
+			return new String[] {second};
+
+		int length = first.length;
+		if (first.length == 0) {
+			return new String[] {second};
+		}
+		
+		String[] result = new String[length + 1];
+		System.arraycopy(first, 0, result, 0, length);
+		result[length] = second;
+		return result;
+	}
+
+	/**
 	 * Lookup the message with the given ID in this catalog 
 	 */
 	public static String bind(String id) {
@@ -105,7 +157,7 @@
 	 * Lookup the message with the given ID in this catalog and bind its
 	 * substitution locations with the given string values.
 	 */
-	public static String bind(String id, String[] bindings) {
+	public static String bind(String id, String[] arguments) {
 		if (id == null)
 			return "No message available"; //$NON-NLS-1$
 		String message = null;
@@ -120,7 +172,7 @@
 		char[] messageWithNoDoubleQuotes =
 			CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
 	
-		if (bindings == null) return new String(messageWithNoDoubleQuotes);
+		if (arguments == null) return new String(messageWithNoDoubleQuotes);
 	
 		int length = messageWithNoDoubleQuotes.length;
 		int start = 0;
@@ -128,14 +180,18 @@
 		StringBuffer output = null;
 		while (true) {
 			if ((end = CharOperation.indexOf('{', messageWithNoDoubleQuotes, start)) > -1) {
-				if (output == null) output = new StringBuffer(length+bindings.length*20);
+				if (output == null) output = new StringBuffer(length+arguments.length*20);
 				output.append(messageWithNoDoubleQuotes, start, end - start);
 				if ((start = CharOperation.indexOf('}', messageWithNoDoubleQuotes, end + 1)) > -1) {
 					int index = -1;
 					String argId = new String(messageWithNoDoubleQuotes, end + 1, start - end - 1);
 					try {
 						index = Integer.parseInt(argId);
-						output.append(bindings[index]);
+						if (arguments[index] == null) {
+							output.append('{').append(argId).append('}'); // leave parameter in since no better arg '{0}'
+						} else {
+							output.append(arguments[index]);
+						}
 					} catch (NumberFormatException nfe) { // could be nested message ID {compiler.name}
 						boolean done = false;
 						if (!id.equals(argId)) {
@@ -305,6 +361,90 @@
 	}
 
 	/**
+	 * Returns the concatenation of the given array parts using the given separator between each part.
+	 * <br>
+	 * <br>
+	 * For example:<br>
+	 * <ol>
+	 * <li><pre>
+	 *    array = {"a", "b"}
+	 *    separator = '.'
+	 *    => result = "a.b"
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = {}
+	 *    separator = '.'
+	 *    => result = ""
+	 * </pre></li>
+	 * </ol>
+	 * 
+	 * @param array the given array
+	 * @param separator the given separator
+	 * @return the concatenation of the given array parts using the given separator between each part
+	 */
+	public static final String concatWith(String[] array, char separator) {
+		StringBuffer buffer = new StringBuffer();
+		for (int i = 0, length = array.length; i < length; i++) {
+			buffer.append(array[i]);
+			if (i < length - 1)
+				buffer.append(separator);
+		}
+		return buffer.toString();
+	}
+	
+	/**
+	 * Returns the concatenation of the given array parts using the given separator between each
+	 * part and appending the given name at the end.
+	 * <br>
+	 * <br>
+	 * For example:<br>
+	 * <ol>
+	 * <li><pre>
+	 *    name = "c"
+	 *    array = { "a", "b" }
+	 *    separator = '.'
+	 *    => result = "a.b.c"
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    name = null
+	 *    array = { "a", "b" }
+	 *    separator = '.'
+	 *    => result = "a.b"
+	 * </pre></li>
+	 * <li><pre>
+	 *    name = " c"
+	 *    array = null
+	 *    separator = '.'
+	 *    => result = "c"
+	 * </pre></li>
+	 * </ol>
+	 * 
+	 * @param array the given array
+	 * @param name the given name
+	 * @param separator the given separator
+	 * @return the concatenation of the given array parts using the given separator between each
+	 * part and appending the given name at the end
+	 */
+	public static final String concatWith(
+		String[] array,
+		String name,
+		char separator) {
+		
+		if (array == null || array.length == 0) return name;
+		if (name == null || name.length() == 0) return concatWith(array, separator);
+		StringBuffer buffer = new StringBuffer();
+		for (int i = 0, length = array.length; i < length; i++) {
+			buffer.append(array[i]);
+			buffer.append(separator);
+		}
+		buffer.append(name);
+		return buffer.toString();
+		
+	}
+	
+	/**
 	 * Concatenate three strings.
 	 * @see #concat(String, String)
 	 */
@@ -328,6 +468,14 @@
 	public static String convertTypeSignature(char[] sig) {
 		return new String(sig).replace('/', '.');
 	}
+	
+	/*
+	 * Returns the default java extension (".java").
+	 * To be used when the extension is not known.
+	 */
+	public static String defaultJavaExtension() {
+		return SuffixConstants.SUFFIX_STRING_java;
+	}
 
 	/**
 	 * Apply the given edit on the given string and return the updated string.
@@ -379,6 +527,24 @@
 
 	/**
 	 * Compares two arrays using equals() on the elements.
+	 * Neither can be null. Only the first len elements are compared.
+	 * Return false if either array is shorter than len.
+	 */
+	public static boolean equalArrays(Object[] a, Object[] b, int len) {
+		if (a == b)	return true;
+		if (a.length < len || b.length < len) return false;
+		for (int i = 0; i < len; ++i) {
+			if (a[i] == null) {
+				if (b[i] != null) return false;
+			} else {
+				if (!a[i].equals(b[i])) return false;
+			}
+		}
+		return true;
+	}
+
+	/**
+	 * Compares two arrays using equals() on the elements.
 	 * Either or both arrays may be null.
 	 * Returns true if both are null.
 	 * Returns false if only one is null.
@@ -491,6 +657,32 @@
 		return a.equals(b);
 	}
 	
+	/*
+	 * Returns whether the given file name equals to the given string ignoring the java like extension
+	 * of the file name.
+	 * Returns false if it is not a java like file name.
+	 */
+	public static boolean equalsIgnoreJavaLikeExtension(String fileName, String string) {
+		int fileNameLength = fileName.length();
+		int stringLength = string.length();
+		if (fileNameLength < stringLength) return false;
+		for (int i = 0; i < stringLength; i ++) {
+			if (fileName.charAt(i) != string.charAt(i)) {
+				return false;
+			}
+		}
+		suffixes: for (int i = 0, length = JAVA_LIKE_EXTENSIONS.length; i < length; i++) {
+			char[] suffix = JAVA_LIKE_EXTENSIONS[i];
+			if (stringLength + suffix.length != fileNameLength) continue;
+			for (int j = stringLength; j < fileNameLength; j++) {
+				if (fileName.charAt(j) != suffix[j-stringLength]) 
+					continue suffixes;
+			}
+			return true;
+		}
+		return false;
+	}
+	
 	/**
 	 * Given a qualified name, extract the last component.
 	 * If the input is not qualified, the same string is answered.
@@ -859,7 +1051,6 @@
 	 */
 	public static String[] getTrimmedSimpleNames(String name) {
 		String[] result = Signature.getSimpleNames(name);
-		if (result == null) return null;
 		for (int i = 0, length = result.length; i < length; i++) {
 			result[i] = result[i].trim();
 		}
@@ -886,6 +1077,26 @@
 	}
 	
 	/*
+	 * 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. 
+	 */
+	public static int indexOfJavaLikeExtension(String fileName) {
+		int fileNameLength = fileName.length();
+		extensions: for (int i = 0, length = JAVA_LIKE_EXTENSIONS.length; i < length; i++) {
+			char[] extension = JAVA_LIKE_EXTENSIONS[i];
+			int extensionLength = extension.length;
+			int extensionStart = fileNameLength - extensionLength;
+			if (extensionStart < 0) continue;
+			for (int j = 0; j < extensionLength; j++) {
+				if (fileName.charAt(extensionStart + j) != extension[j])
+					continue extensions;
+			}
+			return extensionStart;
+		}
+		return -1;
+	}
+	
+	/*
 	 * Returns the index of the first argument paths which is equal to the path to check
 	 */
 	public static int indexOfMatchingPath(IPath checkedPath, IPath[] paths, int pathCount) {
@@ -946,42 +1157,9 @@
 	 */
 	public final static boolean isExcluded(IPath resourcePath, char[][] inclusionPatterns, char[][] exclusionPatterns, boolean isFolderPath) {
 		if (inclusionPatterns == null && exclusionPatterns == null) return false;
-		char[] path = resourcePath.toString().toCharArray();
-
-		inclusionCheck: if (inclusionPatterns != null) {
-			for (int i = 0, length = inclusionPatterns.length; i < length; i++) {
-				char[] pattern = inclusionPatterns[i];
-				char[] folderPattern = pattern;
-				if (isFolderPath) {
-					int lastSlash = CharOperation.lastIndexOf('/', pattern);
-					if (lastSlash != -1 && lastSlash != pattern.length-1){ // trailing slash -> adds '**' for free (see http://ant.apache.org/manual/dirtasks.html)
-						int star = CharOperation.indexOf('*', pattern, lastSlash);
-						if ((star == -1
-								|| star >= pattern.length-1 
-								|| pattern[star+1] != '*')) {
-							folderPattern = CharOperation.subarray(pattern, 0, lastSlash);
-						}
-					}
-				}
-				if (CharOperation.pathMatch(folderPattern, path, true, '/')) {
-					break inclusionCheck;
-				}
-			}
-			return true; // never included
-		}
-		if (isFolderPath) {
-			path = CharOperation.concat(path, new char[] {'*'}, '/');
-		}
-		exclusionCheck: if (exclusionPatterns != null) {
-			for (int i = 0, length = exclusionPatterns.length; i < length; i++) {
-				if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/')) {
-					return true;
-				}
-			}
-		}
-		return false;
+		return org.eclipse.jdt.internal.compiler.util.Util.isExcluded(resourcePath.toString().toCharArray(), inclusionPatterns, exclusionPatterns, isFolderPath);
 	}	
-	
+
 	/*
 	 * Returns whether the given resource matches one of the exclusion patterns.
 	 * NOTE: should not be asked directly using pkg root pathes
@@ -1067,6 +1245,17 @@
 		int len = sig.length();
 		return checkTypeSignature(sig, 0, len, allowVoid) == len;
 	}
+	
+	/*
+	 * Returns the simple name of a local type from the given binary type name.
+	 * The last '$' is at lastDollar. The ;last character of the type name is at end-1.
+	 */
+	public static String localTypeName(String binaryTypeName, int lastDollar, int end) {
+		int nameStart = lastDollar+1;
+		while (nameStart < end && Character.isDigit(binaryTypeName.charAt(nameStart)))
+			nameStart++;
+		return binaryTypeName.substring(nameStart, end);
+	}
 
 	/*
 	 * Add a log entry
@@ -1486,6 +1675,69 @@
 			throw e;
 		}
 	}
+	/**
+	 * 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.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    divider = 'b'
+	 *    string = "abbaba"
+	 *    start = 2
+	 *    end = 5
+	 *    result => { "", "a", "" }
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param divider the given divider
+	 * @param string the given string
+	 * @param start the given starting index
+	 * @param end the given ending index
+	 * @return a new array which is the split of the given string using the given divider
+	 * @throws ArrayIndexOutOfBoundsException if start is lower than 0 or end is greater than the array length
+	 */
+	public static final String[] splitOn(
+		char divider,
+		String string,
+		int start,
+		int end) {
+		int length = string == null ? 0 : string.length();
+		if (length == 0 || start > end)
+			return CharOperation.NO_STRINGS;
+
+		int wordCount = 1;
+		for (int i = start; i < end; i++)
+			if (string.charAt(i) == divider)
+				wordCount++;
+		String[] split = new String[wordCount];
+		int last = start, currentWord = 0;
+		for (int i = start; i < end; i++) {
+			if (string.charAt(i) == divider) {
+				split[currentWord++] = string.substring(last, i);
+				last = i + 1;
+			}
+		}
+		split[currentWord] = string.substring(last, end);
+		return split;
+	}
+	public static boolean isReadOnly(IResource resource) {
+		ResourceAttributes resourceAttributes = resource.getResourceAttributes();
+		if (resourceAttributes == null) return false; // not supported on this platform for this resource
+		return resourceAttributes.isReadOnly();
+	}
+	public static void setReadOnly(IResource resource, boolean readOnly) {
+		ResourceAttributes resourceAttributes = resource.getResourceAttributes();
+		if (resourceAttributes == null) return; // not supported on this platform for this resource
+		resourceAttributes.setReadOnly(readOnly);
+		try {
+			resource.setResourceAttributes(resourceAttributes);
+		} catch (CoreException e) {
+			// ignore
+		}
+	}
 	public static void sort(char[][] list) {
 		if (list.length > 1)
 			quickSort(list, 0, list.length - 1);
@@ -1572,6 +1824,22 @@
 		if (strings.length > 1)
 			quickSortReverse(strings, 0, strings.length - 1);
 	}
+	
+	/*
+	 * Returns whether the given compound name starts with the given prefix.
+	 * Returns true if the n first elements of the prefix are equals and the last element of the 
+	 * prefix is a prefix of the corresponding element in the compound name.
+	 */
+	public static boolean startsWithIgnoreCase(String[] compoundName, String[] prefix) {
+		int prefixLength = prefix.length;
+		int nameLength = compoundName.length;
+		if (prefixLength > nameLength) return false;
+		for (int i = 0; i < prefixLength - 1; i++) {
+			if (!compoundName[i].equalsIgnoreCase(prefix[i]))
+				return false;
+		}
+		return compoundName[prefixLength-1].toLowerCase().startsWith(prefix[prefixLength-1].toLowerCase());
+	}
 
 	/**
 	 * Converts a String[] to char[][].
@@ -1580,22 +1848,12 @@
 		int len = a.length;
 		char[][] result = new char[len][];
 		for (int i = 0; i < len; ++i) {
-			result[i] = toChars(a[i]);
+			result[i] = a[i].toCharArray();
 		}
 		return result;
 	}
 
 	/**
-	 * Converts a String to char[].
-	 */
-	public static char[] toChars(String s) {
-		int len = s.length();
-		char[] chars = new char[len];
-		s.getChars(0, len, chars, 0);
-		return chars;
-	}
-
-	/**
 	 * Converts a String to char[][], where segments are separate by '.'.
 	 */
 	public static char[][] toCompoundChars(String s) {
@@ -1618,7 +1876,7 @@
 		}
 		return segs;
 	}
-
+	
 	/**
 	 * Converts a char[] to String.
 	 */
@@ -1675,13 +1933,9 @@
 	 * e.g. "QString;", "[int", "[[Qjava.util.Vector;"
 	 */
 	public static String typeSignature(TypeReference type) {
-		char[][] compoundName = type.getTypeName();
+		char[][] compoundName = type.getParameterizedTypeName();
 		char[] typeName =CharOperation.concatWith(compoundName, '.');
 		String signature = Signature.createTypeSignature(typeName, false/*don't resolve*/);
-		int dimensions = type.dimensions();
-		if (dimensions > 0) {
-			signature =  Signature.createArraySignature(signature, dimensions);
-		}
 		return signature;
 	}
 
@@ -1764,5 +2018,35 @@
 			}
 		}
 		return utflen + 2; // the number of bytes written to the stream
+	}
+
+	/**
+	 * Returns true if the given name ends with one of the known java like extension.
+	 * (implementation is not creating extra strings)
+	 */
+	public final static boolean isJavaLikeFileName(String name) {
+		if (name == null) return false;
+		return indexOfJavaLikeExtension(name) != -1;
+	}
+
+	/**
+	 * Returns true if the given name ends with one of the known java like extension.
+	 * (implementation is not creating extra strings)
+	 */
+	public final static boolean isJavaLikeFileName(char[] fileName) {
+		if (fileName == null) return false;
+		int fileNameLength = fileName.length;
+		extensions: for (int i = 0, length = JAVA_LIKE_EXTENSIONS.length; i < length; i++) {
+			char[] extension = JAVA_LIKE_EXTENSIONS[i];
+			int extensionLength = extension.length;
+			int extensionStart = fileNameLength - extensionLength;
+			if (extensionStart < 0) continue;
+			for (int j = 0; j < extensionLength; j++) {
+				if (fileName[extensionStart + j] != extension[j])
+					continue extensions;
+			}
+			return true;
+		}
+		return false;
 	}	
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties
index 8670c8f..1de606f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties
@@ -20,6 +20,7 @@
 
 ### java element
 element.doesNotExist = {0} does not exist
+element.notOnClasspath = {0} is not on its project's build path
 element.invalidClassFileName = Class file name must end with .class
 element.reconciling = Reconciling...
 element.attachingSource = Attaching source...
@@ -173,6 +174,10 @@
 cache.invalidLoadFactor = Incorrect load factor
 savedState.jobName = Processing Java changes since last activation
 
+### access restrictions
+restrictedAccess.project = The type {0} is not imported from required project {1}  
+restrictedAccess.library = The type {0} is not imported from required library {1}
+
 ### java conventions
 convention.unit.nullName = Compilation unit name must not be null
 convention.unit.notJavaName = Compilation unit name must end with .java
@@ -192,6 +197,10 @@
 convention.package.nameWithBlanks = A package name must not start or end with a blank
 convention.package.consecutiveDotsName = A package name must not contain two consecutive dots
 convention.package.uppercaseName = By convention, package names usually start with a lowercase letter
+convention.compiler.invalidCompilerOption = ''{0}'' is not valid value for ''{1}'' compiler option.
+convention.compiler.incompatibleTargetForSource = Target level ''{0}'' is incompatible with source level ''{1}''. A target level ''{1}'' or better is required
+convention.compiler.incompatibleComplianceForSource = Compliance level ''{0}'' is incompatible with source level ''{1}''. A compliance level ''{1}'' or better is required
+convention.compiler.incompatibleComplianceForTarget = Compliance level ''{0}'' is incompatible with target level ''{1}''. A compliance level ''{1}'' or better is required
 
 ### DOM
 dom.cannotDetail = Unable to generate detailed source indexes
@@ -220,6 +229,8 @@
 ### Eclipse Java Core Search messages.
 
 engine.searching = Searching...
+engine.searching.indexing = {0}: lookup indexes...
+engine.searching.matching = {0}: locate matches...
 exception.wrongFormat = Wrong format
 process.name = Java indexing
 manager.filesToIndex = {0} files to index
@@ -252,7 +263,7 @@
 disassembler.genericattributename = Name: 
 disassembler.genericattributelength =\ Length: 
 disassembler.signatureattributeheader = Signature:\ 
-disassembler.identation = \  
+disassembler.indentation = \  
 disassembler.constantpoolindex =\ #
 disassembler.classmemberseparator = .
 disassembler.space = \ 
@@ -260,6 +271,33 @@
 disassembler.openinnerclassentry = [
 disassembler.closeinnerclassentry = ]
 disassembler.deprecated =\ (deprecated)
+disassembler.constantpoolheader = Constant pool:
+disassembler.constantpool.class = constant #{0} class: #{1} {2}
+disassembler.constantpool.double = constant #{0} double: {1}
+disassembler.constantpool.float = constant #{0} float: {1}
+disassembler.constantpool.integer = constant #{0} integer: {1}
+disassembler.constantpool.long = constant #{0} long: {1}
+disassembler.constantpool.string = constant #{0} string: #{1} {2}
+disassembler.constantpool.fieldref = constant #{0} field_ref: #{1}.#{2} {3}.{4}
+disassembler.constantpool.interfacemethodref = constant #{0} interface_method_ref: #{1}.#{2} {3}.{4}
+disassembler.constantpool.methodref = constant #{0} method_ref: #{1}.#{2} {3}.{4}
+disassembler.constantpool.name_and_type = constant #{0} name_and_type: #{1}.#{2} {3} {4}
+disassembler.constantpool.utf8 = constant #{0} utf8: {1}
+disassembler.annotationdefaultheader = Annotation Default:\ 
+disassembler.annotationdefaultvalue= {0} (constant type)
+disassembler.annotationenumvalue = {2}.{3}(enum type #{0}.#{1})
+disassembler.annotationclassvalue = {1} (#{0} class type)
+disassembler.annotationannotationvalue = annotation value = 
+disassembler.annotationarrayvaluestart = [
+disassembler.annotationarrayvalueend = ]
+disassembler.annotationentrystart = #{0} @{1}(
+disassembler.annotationentryend = )
+disassembler.annotationcomponent = #{0} {1}=
+disassembler.runtimevisibleannotationsattributeheader= RuntimeVisibleAnnotations:\ 
+disassembler.runtimeinvisibleannotationsattributeheader= RuntimeInvisibleAnnotations:\ 
+disassembler.runtimevisibleparameterannotationsattributeheader= RuntimeVisibleParameterAnnotations:\ 
+disassembler.runtimeinvisibleparameterannotationsattributeheader= RuntimeInvisibleParameterAnnotations:\ 
+disassembler.parameterannotationentrystart=Number of annotations for parameter {0}: {1}
 
 ### classfileformat decoding
 classfileformat.versiondetails =\ (version {0} : {1}.{2}, {3})
diff --git a/org.eclipse.jdt.core/notes/R30_buildnotes_jdt-core.html b/org.eclipse.jdt.core/notes/R30_buildnotes_jdt-core.html
new file mode 100644
index 0000000..b71803e
--- /dev/null
+++ b/org.eclipse.jdt.core/notes/R30_buildnotes_jdt-core.html
@@ -0,0 +1,4492 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <meta name="GENERATOR" content="Mozilla/4.75 [en] (Windows NT 5.0; U) [Netscape]">
+   <title>JDT/Core Release Notes</title>
+
+</head>
+<body>
+
+<body text="#000000" bgcolor="#FFFFFF">
+&nbsp;
+
+<table border=0 cellspacing=5 cellpadding=2 width="100%" >
+  <tr> 
+    <td align=left width="72%">
+      <font face="Verdana, Arial, Helvetica" size="+3"><b>jdt core - build notes 3.0 stream</b></font>
+      <br><font face="Arial, Helvetica, sans-serif" size="-2" color="#8080ff">java development tooling core</font></td>
+  </tr>
+	<tr><td>&nbsp;</td></tr>
+  <tr>
+  	<td>
+	  <font face="Arial, Helvetica, sans-serif" size="-1">
+	  Here are the build notes for the Eclipse JDT/Core plug-in project 
+	  <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/jdt-core-home/main.html"><b>org.eclipse.jdt.core</b></a>, 
+	  describing <a href="http://bugs.eclipse.org/bugs" target=new>bug</a> resolution and substantial changes in the <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core"><b>HEAD</b></a> branch. 
+	  This present document covers all changes since Release 2.1 (also see a summary of <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.jdt.core/notes/API_changes.html">API changes</a>).
+	  Older changes which occurred up to Release 2.1 can be found in 
+	  <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.jdt.core/notes/R21_buildnotes_jdt-core.html">build notes R2.1</a>.
+	  </font>
+	</td>
+  </tr>
+</table>
+
+<a name="v_449"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0RC4 Build - 24th June 2004 - 3.0 RELEASE CANDIDATE 4
+<br>Project org.eclipse.jdt.core v_449
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_449">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Fixed schema copyrights.</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44068">44068</a>
+[DOC] Need more project configuration tutorials
+
+<a name="v_448"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0RC4 Build - 24th June 2004
+<br>Project org.eclipse.jdt.core v_448
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_448">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Fixed mixed line delimiters.</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+
+<a name="v_447"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0RC4 Build - 23rd June 2004
+<br>Project org.eclipse.jdt.core v_447
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_447">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Copyright update to 2004.</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+
+<a name="v_446"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0RC4 Build - 22nd June 2004
+<br>Project org.eclipse.jdt.core v_446
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_446">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=67769">67769</a>
+Internal StackOverflowError occurred during project build
+
+<a name="v_445"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0RC3 Build - 18th June 2004 - 3.0 RELEASE CANDIDATE 3
+<br>Project org.eclipse.jdt.core v_445
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_445">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=66898">66898</a>
+refactor-rename: encoding is not preserved
+
+<a name="v_444"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0RC3 Build - 18th June 2004
+<br>Project org.eclipse.jdt.core v_444
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_444">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=67297">67297</a>
+Renaming included package folder throws JME 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=67786">67786</a>
+OutOfMemoryError searching for reference to Object 
+
+<a name="v_443"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0RC3 Build - 18th June 2004
+<br>Project org.eclipse.jdt.core v_443
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_443">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=67717">67717</a>
+NPE disassembling .class file
+
+<a name="v_442"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0RC3 Build - 17th June 2004
+<br>Project org.eclipse.jdt.core v_442
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_442">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=67600">67600</a>
+String Index out of bounds when searching for all types 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=67599">67599</a>
+NPE when cancelling search 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66271">66271</a>
+No need to resolve type names when selecting declaration
+
+<a name="v_441"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0RC3 Build - 16th June 2004
+<br>Project org.eclipse.jdt.core v_441
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_441">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=67324">67324</a>
+Package Explorer doesn't update included package after moving contents of source folder 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41434">41434</a>
+[msic] Slow Down using classes with many methods
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64646">64646</a>
+[Navigator] Navigator popup causes Eclipse to hang. 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65186">65186</a>
+Can't attach source from project directory [build path] 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65831">65831</a>
+search for all types slow/memory intensive [search] 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66675">66675</a>
+Extra period in the doc in 200406110010
+
+<a name="v_440"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0RC2 Build - 10th June 2004 - 3.0 RELEASE CANDIDATE 2
+<br>Project org.eclipse.jdt.core v_440
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_440">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=66551">66551</a>
+Error in org.eclipse.swt project on class PrinterData
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66573">66573</a>
+Shouldn't bind to local constructs
+
+<a name="v_439"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0RC2 Build - 10th June 2004
+<br>Project org.eclipse.jdt.core v_439
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_439">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=66216">66216</a>
+Sort Members is broken.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66437">66437</a>
+Canceling search leads to broken workspace 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65266">65266</a>
+JarPackageFragmentInfo has unnecessary field 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66098">66098</a>
+MatchLocatorParser does not need advanced syntax diagnosis
+
+<a name="v_438"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0RC2 Build - 9th June 2004
+<br>Project org.eclipse.jdt.core v_438
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_438">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=66026">66026</a>
+Large amount of garbage created by DefaultCommentMapper
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64646">64646</a>
+[Navigator] Navigator popup causes Eclipse to hang. 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65288">65288</a>
+Javadoc: tag gets mangled when javadoc closing on same line without whitespace
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65253">65253</a>
+[Javadoc] @@tag is wrongly parsed as @tag
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65180">65180</a>
+Spurious "Javadoc: xxx cannot be resolved or is not a field" error with inner classes
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65174">65174</a>
+Spurious "Javadoc: Missing reference" error
+
+<a name="v_437"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0RC2 Build - 8th June 2004
+<br>Project org.eclipse.jdt.core v_437
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_437">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=66142">66142</a>
+SearchParticipant#scheduleDocumentIndexing() fails silently if index doesn't exist 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65795">65795</a>
+source inclusion mechanism breaks type lookups 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=66099">66099</a>
+Persisted container/variable values are leaked throughout a session
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65250">65250</a>
+Problem selection does not choose first n errors
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65259">65259</a>
+CodeSelect should only find one match for dup methods
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65737">65737</a>
+Strange completion by code assist 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65871">65871</a>
+Missing SUPER_INTERFACE_TYPES_PROPERTY in EnumDeclaration 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53072">53072</a>
+[DOC] Search for fully qualified constructor name reports nothing 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65116">65116</a>
+IProjectDescription.getBuildSpec copies commands 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65234">65234</a>
+Inclusion filter not working 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64657">64657</a>
+better documentation for IType#resolveType behavior 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65693">65693</a>
+Package Explorer shows .class files instead of .java 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64750">64750</a>
+NPE in Java AST Creation - editing some random file 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65562">65562</a>
+Java AST creation failure
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65531">65531</a>
+out of the box formatter settings need to be improved
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65677">65677</a>
+Creating hierarchy failed. See log for details. 0 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=65090">65090</a>
+ASTParser with kind == K_STATEMENTS doesn't work unless source range specified
+	  	
+<a name="v_436"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0RC1 Build - 28th May 2004 - 3.0 RELEASE CANDIDATE 1
+<br>Project org.eclipse.jdt.core v_436
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_436">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=63534">63534</a>
+ConcurrentModificationException after "catching up" 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62131">62131</a>
+CodeStream should do bounds checks
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64470">64470</a>
+&lt;packages prefixes=..../&gt; should be removed
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64299">64299</a>
+NullPointerException when OverrideIndicatorLabelDecorator is decorating
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63550">63550</a>
+NPE "Java AST Creation"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64421">64421</a>
+ArrayIndexOutOfBoundsException in PackageReferenceLocator.matchReportReference()
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62453">62453</a>
+Large File: Java builder not reacting on cancel
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64377">64377</a>
+CRASH: An internal error occurred during: "Java AST creation"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64378">64378</a>
+Wording of error message
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64332">64332</a>
+Javadoc errors in non-API doc comments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64329">64329</a>
+Missing Javadoc tags declaration in API methods
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=64170">64170</a>
+Classpath reentrance protection is not thread-safe 
+
+<a name="v_435"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0RC1 Build - 27th May 2004
+<br>Project org.eclipse.jdt.core v_435
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_435">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>API polish on search matches (org.eclipse.jdt.core.search.SearchMatch hierarchy):
+<ul>
+<li>added setters for all match properties (not just length &amp; offset)</li>
+<li>add insideDocComment argument to PackageReferenceMatch constructor (for 
+being consistent with other reference matches)</li>
+</ul>
+See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62697">62697</a> for more details.
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62854">62854</a>
+refactoring does not trigger reconcile 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62697">62697</a>
+Need to know if a package reference match is in Javadoc or in Code
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63756">63756</a>
+multiple builds early
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63077">63077</a>
+IllegalArgumentException in Openable.codeSelect 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62861">62861</a>
+ArrayIndexOutOfBoundsException in SearchableEnvironment 
+
+
+<a name="v_434"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0RC1 Build - 26th May 2004
+<br>Project org.eclipse.jdt.core v_434
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_434">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=56870">56870</a>
+copied file not shown in package explorer / java browser [ccp] 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63748">63748</a>
+Type Hierarchy: null pointer when pressing F4 on ListCellRenderer 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38839">38839</a>
+org.eclipse.jdt.internal.compiler.parser.Scanner throws thousands of Exceptions
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62869">62869</a>
+[navigation] 'Go to Next Annotation' doesn't find next error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63871">63871</a>
+Using M9, -warn: option crashes the batch compiler
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63434">63434</a>
+NPE during checkout/build 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62737">62737</a>
+Code formatter doesn't work on some files
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62639">62639</a>
+[1.5] Cheetah and extending Vector
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62769">62769</a>
+Javadoc errors in 200405180816
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62952">62952</a>
+Ant adapter behavior is a little strange
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62704">62704</a>
+Using 05180816, //toto is a task if //toto is a task tag.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51660">51660</a>
+[DOM/AST] AST.parse* should handle all legal doc tags
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51606">51606</a>
+Javadoc - {@inheritDoc} should be inefficient when not in first text element
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62713">62713</a>
+should not be able to nest output folders [build path]
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63245">63245</a>
+findPackageFragment won't return default package 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62698">62698</a>
+NPE while searching for declaration of binary package 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61017">61017</a>
+Refactoring - test case that results in uncompilable source 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=63044">63044</a>
+Reference to a constructor inside a javadoc should point to a type binding and not a constructor binding
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62812">62812</a>
+Some malformed javadoc tags are not reported as malformed
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62810">62810</a>
+Deadlock when closing editors and save 
+
+
+<a name="v_433"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M9 Build - 21st May 2004 - 3.0 MILESTONE-9 / 3.0 RELEASE CANDIDATE 0
+<br>Project org.eclipse.jdt.core v_433
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_433">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>Put back test org.eclipse.jdt.core.tests.model.JavaElementDeltaTests.testBuildProjectUsedAsLib()
+after bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62927">62927</a> was fixed.
+</ul>
+
+<a name="v_432"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M9 Build - 20th May 2004
+<br>Project org.eclipse.jdt.core v_432
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_432">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>Excluded test org.eclipse.jdt.core.tests.model.JavaElementDeltaTests.testBuildProjectUsedAsLib()
+</ul>
+
+<a name="v_431"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M9 Build - 20th May 2004
+<br>Project org.eclipse.jdt.core v_431
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_431">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=62881">62881</a>
+JDT/Core could be contributing a content type for JAR manifests
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58580">58580</a>
+VariableBinding.getVariableId() returns wrong IDs for nested types
+
+<a name="v_430"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M9 Build - 18th May 2004
+<br>Project org.eclipse.jdt.core v_430
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_430">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=62608">62608</a>
+Include pattern ending with slash should include all subtree 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59933">59933</a>
+applying exclusion filter to opened java file makes it appear twice [build path]
+
+
+<a name="v_429"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M9 Build - 18th May 2004
+<br>Project org.eclipse.jdt.core v_429
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_429">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=39499">39499</a>
+keyword completion does not work in anonymous inner classes 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59282">59282</a>
+Unable to include an external folder with class files to project classpath 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52422">52422</a>
+F3 can't find method def'n inside inner (anonymous) class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62463">62463</a>
+Wrong length for ExpressionStatement after conversion
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61831">61831</a>
+Full build happens on every start of Eclipse 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62201">62201</a>
+NPE in MethodScope
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61872">61872</a>
+library looses content when setting source attachment
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54962">54962</a>
+plain reference to package not found in (@see) javadoc
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54424">54424</a>
+AST has structural problems with incomplete javadoc tags
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51951">51951</a>
+codeComplete finds no completion in method of local class inside static method 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50686">50686</a>
+NPE in MethodScope.createMethod 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61952">61952</a>
+Bad deprecation -- IJavaSearchConstants#CASE_SENSITIVE 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=62068">62068</a>
+Index manager should use client's index location 
+
+<a name="v_428"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M9 Build - 13th May 2004
+<br>Project org.eclipse.jdt.core v_428
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_428">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Due to an implementation cleanup, the optional diagnosis for unnecessary empty statement or empty control-flow
+statement, will be reverted to ignore by default. If you did set it differently in the past, you will have to manually
+set it back. We now conform to the spec for this option (until JDT/UI converted, the old option ID was 
+incorrectly used: "org.eclipse.jdt.core.compiler.problem.superfluousSemicolon"):
+<pre>
+* COMPILER / Reporting Empty Statements and Unnecessary Semicolons
+*    When enabled, the compiler will issue an error or a warning if an empty statement or a
+*    unnecessary semicolon is encountered.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.emptyStatement"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>	 
+</li>
+<li>Improved error location when type indirectly referenced from required .class files.</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61959">61959</a>
+dangerous practice of catching Throwable
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61882">61882</a>
+Inconsistency between build errors and reconcile errors
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35356">35356</a>
+Convert local variable to field refactoring proposes weird name 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53555">53555</a>
+SourceType#get*QualifiedName() methods return unusable/invalid names for local types 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48752">48752</a>
+Completion: relevance could be improved for non static field
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61877">61877</a>
+ClassCastException in DefaultBindingResolver
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59769">59769</a>
+Javadoc of SearchMatch#getElement(): is *enclosing* element 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58440">58440</a>
+type hierarchy incomplete when implementing fully qualified interface 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61719">61719</a>
+Incorrect fine grain delta after method copy-rename 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61075">61075</a>
+[Compiler] implementation uses numerous ArrayIndexOutOfBoundsException
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=19898">19898</a>
+StackOverflowError in BinaryExpression
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61706">61706</a>
+Improve error message when unbound reference from binaries
+
+<a name="v_427"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M9 Build - 11th May 2004
+<br>Project org.eclipse.jdt.core v_427
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_427">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>A system job now reports progress when the indexer is running.</li>
+<li>The org.eclipse.jdt.core.jdom package has been deprecated. The JDOM was made obsolete by 
+      the addition in 2.0 of the more powerful, fine-grained DOM/AST API found in the 
+      org.eclipse.jdt.core.dom package.</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60689">60689</a>
+AST on reconcile: AST without Javadoc comments created
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60365">60365</a>
+hierarchy view shows some interfaces as classes [type hierarchy] 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53290">53290</a>
+[Javadoc] Compiler should complain when tag name is not correct
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53279">53279</a>
+[Javadoc] Compiler should complain when inline tag is not terminated
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51600">51600</a>
+Javadoc: tags with errors are not stored in DOM AST Javadoc hierarchy
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59751">59751</a>
+No Feedback/information from indexing 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42402">42402</a>
+OuterClass.this does not appear in code assist of the InnerClass
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61390">61390</a>
+Indexing thread grabbing resource lock 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61408">61408</a>
+Incorrect parsing
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58859">58859</a>
+[encoding] Editor does not detect BOM on .txt files
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61148">61148</a>
+deprecate JDOM API 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61270">61270</a>
+Wrong delta when copying a package that overrides another package 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61181">61181</a>
+Task tag starting with double-/ (//) causes compile error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61040">61040</a>
+Should add protect for reentrance to #getResolvedClasspath 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61214">61214</a>
+The classpath computation inside the Java builder should get rid of duplicates entries
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60867">60867</a>
+LocalVariableReferenceMatch should offer isReadAccess(), etc. 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59638">59638</a>
+ConcurrentModificationException in JavaModelManager.saving 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61052">61052</a>
+Flatten cp container initialization 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60848">60848</a>
+[reconciling] Unclosed Comment in Java Texteditor
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60822">60822</a>
+Reacting to Project > Clean... 
+	  	
+<a name="v_426"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M9 Build - 4th May 2004
+<br>Project org.eclipse.jdt.core v_426
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_426">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added new flag IJavaElementDelta.F_PRIMARY_RESOURCE that is set when the resource of a primary working copy 
+     changes (or when it is added or removed).</li>
+<li>Removed dependency on org.eclipse.runtime.compatibility.</li>
+<li>Tuned the diagnosis for unnecessary else statements to tolerate else-if constructs.</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60687">60687</a>
+NPE in JavaCore.getEncoding
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60581">60581</a>
+"Java AST creation" error.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48502">48502</a>
+Exception during "Java AST creation"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59750">59750</a>
+DCR: Code Assist: Hook to add getter and setters
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47227">47227</a>
+Syntax error diagnosis shouldn't expose internal goal tokens
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60595">60595</a>
+AST: AST from reconcile does not have 'ORIGINAL' bit set
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59500">59500</a>
+Java Model Notification needs notification that a java class was physically saved 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60459">60459</a>
+AST: 'malformed' flag overwrites other flags
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60367">60367</a>
+dynamic project references not maintained
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60257">60257</a>
+SearchPattern API: R_CASE_SENSITIVE vs. boolean isCaseSensitive 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58565">58565</a>
+code formatter doesn't format blocks with a return statement correctly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58724">58724</a>
+Java code formatter should add space between imports and class definition
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60418">60418</a>
+remove warnings from core runtime deprecations 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57749">57749</a>
+Search in working copies doesn't find all matches 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60235">60235</a>
+WorkingCopyOwner needs clarification on
+
+
+<a name="v_425"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M9 Build - 28th April 2004
+<br>Project org.eclipse.jdt.core v_425
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_425">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added API to register/deregister a pre-processing resource change listener:
+<pre>
+/**
+ * Adds the given listener for POST_CHANGE resource change events to the Java core. 
+ * The listener is guarantied to be notified of the POST_CHANGE resource change event before
+ * the Java core starts processing the resource change event itself.
+ * 
+ * Has no effect if an identical listener is already registered.
+ * 
+ * @param listener the listener
+ * @see #removePreResourceChangeListener(IResourceChangeListener)
+ * @since 3.0
+ */
+public static void addPreProcessingResourceChangedListener(IResourceChangeListener listener);
+	
+/**
+ * Removes the given pre-processing resource changed listener.
+ *
+ * Has no affect if an identical listener is not registered.
+ *
+ * @param listener the listener
+ * @since 3.0
+ */
+public static void removePreProcessingResourceChangedListener(IResourceChangeListener listener);
+</pre>
+</li>
+<li>When diagnostic for unnecessary semicolon is enabled, the compiler will also flag empty
+control-flow statement: e.g. if (bool);.  Note that the naming of the option is going soon
+to be revised to better reflect this evolution.
+Empty control-flow statement problem ID is: <tt>IProblem.EmptyControlFlowStatement</tt>.
+</li>
+<li>Added compiler style option to report situation where a statement is unnecessarily nested
+in else clause, e.g.: 
+<pre>
+ if (bool) 
+   return;
+ else
+   System.out.println();   // no need to be inside else
+</pre>    
+Associated problem ID is: <tt>IProblem.UnnecessaryElse</tt>.
+<pre>
+* COMPILER / Reporting Unnecessary Else
+*    When enabled, the compiler will issue an error or a warning when a statement is unnecessarily
+*    nested within an else clause (in situation where then clause is not completing normally).
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.unnecessaryElse"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42493">42493</a>
+Error message when evaluating: Expressionopt?
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32061">32061</a>
+No code assist in instance variable inner class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49904">49904</a>
+[DCR] Quick Assist : unneeded else
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60081">60081</a>
+[Compiler] java.lang.VerifyError: Illegal target of jump or branch
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52805">52805</a>
+[DCR] Compiler should warn when using if (test);
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58652">58652</a>
+ImageBuilderInternalException during auto build
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60108">60108</a>
+SearchMatch should implement toString() 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=60078">60078</a>
+NPE in ASTConverter
+
+<a name="v_424"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M9 Build - 27th April 2004
+<br>Project org.eclipse.jdt.core v_424
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_424">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=54108">54108</a>
+Weird piece of source code in SourceTypeConverter.java
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51500">51500</a>
+[DOM AST] Quick fix "Add unimplemented methods" fails on static variable initialized using anonymous constructor
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59843">59843</a>
+Eclipse 3.0M8 generates ambiguous keys from ITypeBindings for nested classes with the same name
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59937">59937</a>
+Should not process saved state delta during startup 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58069">58069</a>
+Compilation ERROR: Missing code implementation in the compiler
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51911">51911</a>
+@see method w/out ()
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49025">49025</a>
+Util.bind(String, String[]) can be optimized a little bit
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59743">59743</a>
+[Compiler] Incorrect diagnosis of ambiguous method when inheriting
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57871">57871</a>
+Override Indicator: blocks editor from opening when error occurs in java compiler
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59421">59421</a>
+Bad error message from Eclipse Java Compiler when file is missing
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58946">58946</a>
+Standalone compiler help text is incorrect on Unix
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59084">59084</a>
+[content type] ensure content types/file associations are contributed by the right plugins
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59716">59716</a>
+Using 200404201300, one more blank line is inserted in front of import declarations when no package is defined
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59575">59575</a>
+invalid formatting
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51213">51213</a>
+Unable to resolve conflict between type and package name in binaries
+
+<a name="v_423"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M9 Build - 22nd April 2004
+<br>Project org.eclipse.jdt.core v_423
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_423">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=59363">59363</a>
+Should surface cancellation exceptions 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51075">51075</a>
+Compiler warning "is hiding a field" given for static inner class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38658">38658</a>
+Search for existing type fails
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59291">59291</a>
+Deadlock between AllTypes cache and setClasspathContainer
+
+
+<a name="v_422"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M9 Build - 20th April 2004
+<br>Project org.eclipse.jdt.core v_422
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_422">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added API for User Library Container support in JavaCore:
+<pre>
+
+/**
+ * Name of the User Library Container id.
+ */
+public static final String USER_LIBRARY_CONTAINER_ID= "org.eclipse.jdt.USER_LIBRARY"; //$NON-NLS-1$
+
+/**
+ * Returns the names of all defined user libraries. The corresponding classpath container path
+ * is the name appended to the USER_LIBRARY_CONTAINER_ID.  
+ * @return Return an array containing the names of all known user defined.
+ */
+public static String[] getUserLibraryNames();
+</pre>
+</li>
+<li>Added API to get classpath container comparison ID in ClasspathContainerInitializer:
+<pre>
+/**
+ * Returns an object which identifies a container for comparison purpose. This allows
+ * to eliminate redundant containers when accumulating classpath entries (e.g. 
+ * runtime classpath computation). When requesting a container comparison ID, one
+ * should ensure using its corresponding container initializer. Indeed, a random container
+ * initializer cannot be held responsible for determining comparison IDs for arbitrary 
+ * containers.
+ * <p>
+ * @param containerPath the path of the container which is being checked
+ * @param project the project for which the container is to being checked
+ * @return returns an Object identifying the container for comparison
+ * @since 3.0
+ */
+public Object getComparisonID(IPath containerPath, IJavaProject project);
+</pre>
+By default, containers are identical if they have same container path first segment
+but this may be refined by other container initializer implementations.
+<br>
+For example, the User Library classpath container initializer added for User Library Container API
+implementation (UserLibraryClasspathContainerInitializer) refines the comparison ID to the entire container path.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52747">52747</a>
+formatter - please special case empty array init
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=59000">59000</a>
+Code formatter struggles with end-of-line comments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52679">52679</a>
+Code formatter formats braces in case and default statements, but no settings exist
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52940">52940</a>
+Formatter: Separate control of new lines in control statements by statement type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47815">47815</a>
+Refactoring doesn't work with some project names [refactoring] 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37657">37657</a>
+[plan item] Improve code formatter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50989">50989</a>
+Non-externalized strings wrap lines incorrectly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57689">57689</a>
+ArrayIndexOutOfBoundsException when creating a new class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55004">55004</a>
+[DCR] IVariableBinding should have a method returning the constant value
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=58606">58606</a>
+Inner class in child calling protected method in parent
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55979">55979</a>
+There are still deprecated formatter constants without new way
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57117">57117</a>
+Ant adapter preserves all deprecation when using compiler arg even if deprecation is set to off
+
+<a name="v_421"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M9 Build - 13th April 2004
+<br>Project org.eclipse.jdt.core v_421
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_421">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=57829">57829</a>
+Should optimize assert true case
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57294">57294</a>
+Ignore serialVersionUID hiding another field
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41395">41395</a>
+StackOverflowError when pasting code 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57414">57414</a>
+Summary: GB18030: Can not open Java Search dialog. 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57886">57886</a>
+Concurrency issue while initializing containers and variables 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57858">57858</a>
+[Compiler] Marking a field deprecated still report deprecated usage #46973
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57743">57743</a>
+[Compiler] invalid byte code produced when catching Throwable
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=57235">57235</a>
+DCR: AST Name.getQualifiedName()
+
+<a name="v_420"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M9 Build - 6th April 2004
+<br>Project org.eclipse.jdt.core v_420
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_420">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added inclusion patterns support. See <code>JavaCore.newSourceEntry(IPath,IPath[],IPath[],IPath)</code> 
+	 and <code>IClasspathEntry.getInclusionPatterns()</code> for details.</li>
+<li>Added API on WorkingCopyOwner to set the primary buffer provider (for internal use by the jdt-related plug-ins only).
+<pre>
+/**
+ * Sets the buffer provider of the primary working copy owner. Note that even if the
+ * buffer provider is a working copy owner, only its createBuffer(ICompilationUnit)
+ * method is used by the primary working copy owner. It doesn't replace the internal primary 
+ * working owner.
+ * 
+ * This method is for internal use by the jdt-related plug-ins.
+ * Clients outside of the jdt should not reference this method.
+ * 
+ * @param primaryBufferProvider the primary buffer provider
+ */
+public static void setPrimaryBufferProvider(WorkingCopyOwner primaryBufferProvider);
+</pre></li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54009">54009</a>
+jardesc should be known to Team/File Content
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51867">51867</a>
+An anonymous type is missing in type hierarchy when editor is modified 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54763">54763</a>
+[Compiler] Unnecessary cast not detected
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52347">52347</a>
+NPE in LaunchingPlugin.shutdown 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55992">55992</a>
+AssertionFailed during preference import
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29964">29964</a>
+Add inclusion filter 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55088">55088</a>
+IAE when using ICU.reconcile(GET_AST_TRUE, ...) 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=56462">56462</a>
+[formatter] java profile; array initializer before closing brace
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=56449">56449</a>
+Need to know if a reference match is in Javadoc or in Code 
+
+<a name="v_419"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M9 Build - 30th March 2004
+<br>Project org.eclipse.jdt.core v_419
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_419">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Replaced "name" property of ParameterizedType node (DOM/AST) 
+with "type" property. The old methods and fields (added earlier in 3.0 cycle)
+are deprecated and will be removed shortly.</li>
+<li>Added typeParameters property to ClassInstanceCreation node (DOM/AST).</li>
+<li>Package org.eclipse.jdt.core.internal.dom.rewrite renamed to org.eclipse.jdt.internal.core.dom.rewrite.</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=56316">56316</a>
+JavaProject exists should not populate 
+	  	
+<a name="v_418"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M8 Build - 25th March 2004 - 3.0 MILESTONE-8
+<br>Project org.eclipse.jdt.core v_418
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_418">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=55930">55930</a>
+File encoding should be used on save
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55478">55478</a>
+Unused import not reported in IDE
+	  	
+<a name="v_417"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M8 Build - 24th March 2004
+<br>Project org.eclipse.jdt.core v_417
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_417">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Removed failing tests re: encoding support.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+
+<a name="v_416"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M8 Build - 23rd March 2004
+<br>Project org.eclipse.jdt.core v_416
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_416">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=55504">55504</a>
+@&lt;tasktag&gt; should not be reported
+
+<a name="v_415"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M8 Build - 23rd March 2004
+<br>Project org.eclipse.jdt.core v_415
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_415">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul> 
+<li> Added rewriting support to DOM AST.
+There are two set of API to perform rewriting.
+<ul> 
+<li>An AST-modifying rewrite API<br>
+To use the AST-modifying rewrite the client must create an AST from an existing
+compilation unit (ASTParser#createAST(...)).
+Then the client need to start the record process of the AST changes (CompilationUnit#recordModifications())
+and modify the AST after. When modifications are done, the client can call a method to
+compute a text edit tree containing all the text changes (CompilationUnit#rewrite()).
+
+<pre>
+CompilationUnit
+	public void recordModifications()
+	public TextEdit rewrite(IDocument document, Map options) throws RewriteException
+</pre>
+</li>
+<li>A describing rewrite API<br>
+To use the describing AST rewrite, the client starts with creating an instance of NewASTRewrite. Then the client
+must not modify the AST directly but use NewASTRewrite instead. When modifications are done, the client can call
+a method to compute a text edit tree containing all the text changes (NewASTRewrite#rewrite()).
+<pre>
+NewASTRewrite
+	public final void markAsRemoved(ASTNode node, TextEditGroup editGroup)
+	public final void markAsReplaced(ASTNode node, ASTNode replacingNode, TextEditGroup editGroup)
+	public ListRewriter getListRewrite(ASTNode parent, ChildListPropertyDescriptor childProperty)
+	public TextEdit rewriteAST(IDocument document, Map options) throws RewriteException
+	...
+	
+ListRewriter
+	remove(ASTNode, TextEditGroup)
+	public void replace(ASTNode, ASTNode, TextEditGroup)
+	public void insertAfter(ASTNode, ASTNode, TextEditGroup)
+	public void insertBefore(ASTNode, ASTNode, TextEditGroup)
+	public void insertFirst(ASTNode, TextEditGroup)
+	public void insertLast(ASTNode, TextEditGroup)
+	public void insertAt(ASTNode, int, TextEditGroup)
+	...
+</pre>
+</li>
+</ul>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39068">39068</a>
+Adopt new core API for encoding on a per file basis
+
+<a name="v_414"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M8 Build - 22nd March 2004
+<br>Project org.eclipse.jdt.core v_414
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_414">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=46668">46668</a>
+Changes to class path containers should not change .project 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55421">55421</a>
+Cannot save a .java file in a non-java project anymore 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55223">55223</a>
+Bug in comment mapper: Same comment mapped to 2 statements
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54044">54044</a>
+Ant log does not use system newline character
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55372">55372</a>
+Should not assume that Preferences.defaultPropertyNames() returns default-default properties 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55221">55221</a>
+Bug in comment mapper: Grabs next node's Javadoc
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=55102">55102</a>
+NPE when using ICU.reconcile(GET_AST_TRUE, ...) 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49986">49986</a>
+setRawClasspath(...) should fire a F_CLASSPATH_CHANGED delta 
+
+<a name="v_413"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M8 Build - 15th March 2004
+<br>Project org.eclipse.jdt.core v_413
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_413">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul> 
+<li> Added compiler option JavaCore.COMPILER_TASK_CASE_SENSITIVE to control whether the task detection
+should be case sensitive or not. By default, it is.
+<pre>
+ * COMPILER / Determine whether task tags are case-sensitive
+ *    When enabled, task tags are considered in a case-sensitive way.
+ *     - option id:         "org.eclipse.jdt.core.compiler.taskCaseSensitive"
+ *     - possible values:   { "enabled", "disabled" }
+ *     - default:           "enabled"
+</pre>
+</li>
+<li> Added 2 default task tags: "FIXME" and "XXX".
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54776">54776</a>
+DefaultCommentMapper: different behaviour
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54431">54431</a>
+ASTParser should honor set compiler options in all cases
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54043">54043</a>
+Problems with type hierarchy for binary types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53095">53095</a>
+I20040225: Won't accept breakpoint on NoClassDefFoundError
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=54294">54294</a>
+No default for JavaCore.COMPILER_CODEGEN_INLINE_JSR_BYTECODE
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48435">48435</a>
+Java Search for OR-pattern finds too much in strange project setup
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40921">40921</a>
+Task tags should be case-insensitive
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49266">49266</a>
+FIXME task tag
+
+
+<a name="v_412"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M8 Build - 8th March 2004
+<br>Project org.eclipse.jdt.core v_412
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_412">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Added new global JavaCore.COMPILER_DOC_COMMENT_SUPPORT option for doc comment (Javadoc) support. By default, this option is enabled for backward compatibility.
+<pre>
+ * COMPILER / Javadoc Comment Support
+ *    When this support is disabled, the compiler will ignore all javadoc problems options settings
+ *    and will not report any javadoc problem. It will also not find any reference in javadoc comment and
+ *    DOM AST Javadoc node will be only a flat text instead of having structured tag elements.
+ *     - option id:         "org.eclipse.jdt.core.compiler.doc.comment.support"
+ *     - possible values:   { "enabled", "disabled" }
+ *     - default:           "enabled"
+</pre>
+See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52264">52264</a>.
+</li>
+<li> Added new JavaCore.COMPILER_CODEGEN_INLINE_JSR_BYTECODE option to allow user to inline subroutine code instead of generating JSR instructions. By default, this option is disabled.
+<pre>
+ * COMPILER / Inline JSR Bytecode Instruction
+ *    When enabled, the compiler will no longer generate JSR instructions, but rather inline corresponding
+ *    subroutine code sequences (mostly corresponding to try finally blocks). The generated code will thus
+ *    get bigger, but will load faster on virtual machines since the verification process is then much simpler. 
+ *    This mode is anticipating support for the Java Specification Request 202.
+ *     - option id:         "org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode"
+ *     - possible values:   { "enabled", "disabled" }
+ *     - default:           "disabled"
+ * 
+</pre>
+Corresponding command line compiler option <code>-noJSR</code> has been renamed to:
+<pre>
+    <code>-inlineJSR</code> : inline JSR bytecode
+</pre>
+which means that when specified, the compiler will no longer generate JSR bytecodes, but instead inlining the corresponding subroutine (e.g. finally block).
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53757">53757</a>
+Javadoc tag @transient  ignored
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=530757">53075</a>
+https://bugs.eclipse.org/bugs/show_bug.cgi?id=53075
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53357">53357</a>
+Java AST creation error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52264">52264</a>
+Need a global preference to enable Javadoc support
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51529">51529</a>
+"Organize imports" is confused by references inside Javadoc
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53477">53477</a>
+AnonymousClassDeclaration has wrong range
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53624">53624</a>
+StackOverFlow in Code assist 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50433">50433</a>
+Rationalize signatures of AST.parse* methods 
+
+<a name="v_411"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M8 Build - 3rd March 2004
+<br>Project org.eclipse.jdt.core v_411
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_411">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added new constant <code>IJavaElementDelta.F_CLASSPATH_CHANGED</code> that indicates that
+	  the project's raw classpath has changed.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49986">49986</a>
+setRawClasspath(...) should fire a F_CLASSPATH_CHANGED delta 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53242">53242</a>
+Consitent Out of Memory problems indexing (with multiple Java libraries)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52474">52474</a>
+UI Blocked when opening Java Perspective during CVS check out 
+
+<a name="v_410"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M8 Build - 2nd March 2004
+<br>Project org.eclipse.jdt.core v_410
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_410">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added following APIs to <code>org.eclipse.jdt.core.dom.CompilationUnit</code>:
+<ul>
+<li><code>getCommentList()</code>: Returns a list of the comments encountered while parsing the compilation unit.</li>
+<li><code>getExtendedStartPosition(ASTNode)</code>: Returns the extended start position of the given node.</li>
+<li><code>getExtendedLength(ASTNode)</code>: Returns the extended source length of the given node.</li>
+</li>
+</ul>
+Unlike <code>ASTNode#getStartPosition()</code> and <code>ASTNode#getLength()</code>, the extended source range may include
+comments and whitespace immediately before or after the normal source range for the node.
+<br>
+See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53445">53445</a> for more details on heuristic to find leading and trailing comments.
+</li>
+<li>Added API <code>FieldReferenceMatch.isReadAccess()</code> and <code>isWriteAccess()</code>.
+<li>Added API <code>JavaCore.run(IWorkspaceRunnable action, ISchedulingRule rule, IProgressMonitor monitor)</code> 
+	 to control the scheduling rule during a Java batch operation.
+</li>
+<li>Added API <code>SearchEngine.createJavaSearchScope(IJavaElement[], int)</code> that allows to filter the
+     classpath entries added in the scope: SOURCES, APPLICATION_LIBRARIES, SYSTEM_LIBRARIES and REQUIRED_PROJECTS.
+</li>
+<li> New command line options for batch compiler:
+  <ul>
+  <li> <code>-maxProblems &lt;n&gt;</code> :  max number of problems per compilation unit (100 by default) </li>
+  <li> <code>-noJSR</code> : do not use JSR bytecode </li>
+  </ul>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53445">53445</a>
+[DCR] [DOM Comments] Provide extended ranges including leading/trailing comments for AST nodes
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=53276">53276</a>
+[DOM Comments] Wrong text element length when containing '\' character
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52908">52908</a>
+[DOM Comments] Wrong text element positions when starting/ending with { or }
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48337">48337</a>
+[Search] FieldReferenceMatch should report read/write access 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52691">52691</a>
+Add batch compiler option for maxProblemsPerUnit
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51045">51045</a>
+Offer to call JavaCore.run with scheduling rule 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52273">52273</a>
+Add option on predefined search scope to include/exclude system contain libraries 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49809">49809</a>
+NPE from MethodVerifier 
+
+<a name="v_409"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M8 Build - 24th February 2004
+<br>Project org.eclipse.jdt.core v_409
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_409">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added new API to create a DOM AST while reconciling 
+	 <code>ICompilationUnit.reconcile(boolean, boolean, WorkingCopyOwner, IProgressMonitor)</code>.
+</li>
+<li>Removed compiler support for deprecating jsr bytecode in 1.5 compliant mode (turned off until future release).
+</li>
+<li>The constant DefaultCodeFormatterConstants.FORMATTER_PRESERVE_USER_LINEBREAKS will be removed. It has been deprecated for now and
+has no effect in the UI anymore.
+</li>
+<li>The constant DefaultCodeFormatterConstants.FORMATTER_FILLING_SPACE will be removed. It has been deprecated for now and
+has no effect in the UI anymore.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52916">52916</a>
+Strang error message when using jre1.5.0 libraries
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50586">50586</a>
+[Code Formatter] trim trailing blanks/whitespace
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52851">52851</a>
+Space before else should be removed in some cases
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52283">52283</a>
+do &lt;single-statement&gt; while(&lt;condition&gt;) is ill-formatted
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52479">52479</a>
+Code Format fails on not on-demand imports
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52246">52246</a>
+M7 Source formatter fails silently when assert present in source
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52429">52429</a>
+code formatter seems to ignore settings
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51623">51623</a>
+[formatter] Wrong formatting when "Preserve existing line breaks" switched on
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52305">52305</a>
+Code Formatter strips blank lines in methods and field definitions when I try to tell it not to
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52746">52746</a>
+Formatter - preserve line breaks conflicts with keep blank lines
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52804">52804</a>
+Deprecated formatter constant should indicate new way
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52619">52619</a>
+NPE running Java model tests
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36889">36889</a>
+[DCR] Keep AST created in reconcile for active editor 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52384">52384</a>
+OutOfMemoryError opening hierarchy on Object 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52355">52355</a>
+Not present exception trying to create a class in excluded package
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49809">49809</a>
+NPE from MethodVerifier
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22104">22104</a>
+[infrastructure] NPE from IndexSummary.read(...)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31013">31013</a>
+ [infrastructure] npe in index crash recovery
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31014">31014</a>
+[infrastructure] exception in indexer
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51447">51447</a>
+[infrastructure] NPE running JDT Core tests
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52221">52221</a>
+[Compiler] should reject Local type usage when defined in other switch case block
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52216">52216</a>
+[regression in M7] javadoc: @see &lt;a href&gt; shows a warning
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51990">51990</a>
+'parameter' vs 'argument' in compiler errors/settings
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=52012">52012</a>
+Special 'serialPersistentFields' marked as 'never used locally'
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51353">51353</a>
+The type AbstractStringBuilder is not visible
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49259">49259</a>
+Task tags starting with TODO don't correctly display their priority in Tasks View
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49879">49879</a>
+java.lang.ClassCastException (SourceTypeBinding to a BinaryTypeBinding) in 30M6 within jdt.core.dom.TypeBinding.getKey(TypeBinding.java:411)
+
+<a name="v_408"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M7 Build - 12th February 2004 - 3.0 MILESTONE-7
+<br>Project org.eclipse.jdt.core v_408
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_408">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=51603">51603</a>
+[preferences] Code formatter line wrapping preference inconsistent preview behaviour
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51476">51476</a>
+Javadoc: String or URL @see references are not stored in DOM AST Javadoc structure
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51478">51478</a>
+Javadoc: @deprecated/@inheritDoc tags are not stored in DOM AST Javadoc structure
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51508">51508</a>
+Javadoc: Package references DOM AST nodes binding is null
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51626">51626</a>
+Javadoc - DOM/AST is not correct after a @see tag
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51650">51650</a>
+Incorrected deprecation check
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51770">51770</a>
+Javadoc AST Node: wrong binding on qualified name part
+
+
+<a name="v_407"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M7 Build - 11th February 2004
+<br>Project org.eclipse.jdt.core v_407
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_407">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Fixed most of the API Java doc comments. 
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51659">51659</a>
+New Code Formatter: minor problem with "White spaces/Array Initializers" option
+
+
+<a name="v_406"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M7 Build - 10th February 2004
+<br>Project org.eclipse.jdt.core v_406
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_406">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=51035">51035</a>
+[Formatter] endline comment in case of simple if-then statement
+
+
+<a name="v_405"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M7 Build - 9th February 2004
+<br>Project org.eclipse.jdt.core v_405
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_405">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=51363">51363</a>
+Wrong comment positions inside the Scanner.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51201">51201</a>
+Code formatter missing 'between empty brackets' option in Whitespace Array allocation configuration
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50695">50695</a>
+Javadoc: package reference in @see tags is wrongly warned
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49994">49994</a>
+Strange matches with start=0, end=1 in type reference search
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51300">51300</a>
+VerifyError when using a array reference assigned to null
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51128">51128</a>
+[Code Formatter] Indent statements within blocks and methods
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51241">51241</a>
+IllegalArgumentException while creating a DOM/AST
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51249">51249</a>
+Performance problems in PackageFragment.getPath 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50276">50276</a>
+Function call line wrapping fails on chained calls
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51190">51190</a>
+comment after else block goes to next line
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51226">51226</a>
+Javadoc inside DOM AST does not support starting characters in unicode
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51104">51104</a>
+Comments are not recorded when inside a method body
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50858">50858</a>
+Javadoc IProblem constant not defined
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50898">50898</a>
+Javadoc AST: Missing binding for reference to non-visible type
+
+<a name="v_404"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M7 Build - 3rd February 2004
+<br>Project org.eclipse.jdt.core v_404
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_404">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=50938">50938</a>
+Javadoc AST: Still invalid range for embedded tag
+
+<a name="v_403"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M7 Build - 3rd February 2004
+<br>Project org.eclipse.jdt.core v_403
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_403">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Updated porting guide to introduce search participant story (see <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.jdt.core/notes/porting_guide.html">porting guide</a>)</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=51089">51089</a>
+Java AST creation failure 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50571">50571</a>
+search sender in hierarchy hangs 
+
+<a name="v_402"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M7 Build - 30th January 2004
+<br>Project org.eclipse.jdt.core v_402
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_402">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=50883">50883</a>
+Javadoc AST node: Range problem with embedded tags
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50884">50884</a>
+Compiler crashes without a trace in the log leaving workspace in unhappy state
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50831">50831</a>
+DCR Javadoc AST: Offer well known tag names as constants 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50880">50880</a>
+JavadocAST Nodes: Wrong ranges on link
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50877">50877</a>
+Javadoc AST Nodes: Wrong ranges
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47396">47396</a>
+JAVA AST Creation failure
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50844">50844</a>
+AbortCompilation thrown from Name#resolveBinding() 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50746">50746</a>
+Searching for variable references can cause an internal error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50838">50838</a>
+Javadoc bindings: No bindings in constructor ref parameter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50840">50840</a>
+Javadoc AST: wrong start position on MemberRef
+
+<a name="v_401"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M7 Build - 29th January 2004
+<br>Project org.eclipse.jdt.core v_401
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_401">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=46126">46126</a>
+[DCR] IBinding should have a method to check @since javadoc tag
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50785">50785</a>
+Javadoc bindings: No bindings member refs
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50784">50784</a>
+Javadoc bindings: No binding in {@link } and link disturbs other bindings
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50781">50781</a>
+Javadoc bindings: No bindings for qualified names
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50736">50736</a>
+Out of bounds exception while formatting
+
+<a name="v_400"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M7 Build - 28th January 2004
+<br>Project org.eclipse.jdt.core v_400
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_400">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=50694">50694</a>
+Javadoc: Cannot find DOM AST bindings for types in @see tags
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50692">50692</a>
+Javadoc: Cannot find DOM AST bindings for inline link tags references
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50719">50719</a>
+wrong formatting for java coding conventions
+
+<a name="v_399"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M7 Build - 27th January 2004
+<br>Project org.eclipse.jdt.core v_399
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_399">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Improve DOM/AST support for doc comments.
+<br>Following changes have been made to the DOM/AST API:
+<ul>
+<li>added Javadoc.tags() to represent structure of the doc comments</li>
+<li>deprecated Javadoc.get/setComment</li>
+<li>added 5 new node types that occur only within doc comments: TagElement, TextElement, MemberRef, MethodRef, MethodRefParameter</li>
+<li>tag elements like MemberRef, MethodRef, and Name can carry binding information (must be requested like elsewhere)</li>
+<li>added ASTVisitor(boolean) for controlling whether Javadoc.tags() are visited by default</li>
+<li>added ASTMatcher(boolean) for controlling whether Javadoc.tags() are compared vs. only Javadoc.getComment()</li>
+<li>AST.parse*(...) now returns structured doc comments (for compatibility, Javadoc.getComment() is also set as before)</li>
+</ul>
+See bugs <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50683">50683</a>.
+</li>
+<li>
+Improve DOM/AST support for locating all comments.
+<br>Following changes have been made to the DOM/AST API:
+<ul>
+<li>added CompilationUnit.getCommentTable() to record locations of all comments found in the source</li>
+<li>added 2 new node types, LineComment and BlockComment, to represent end-of-line and traditional comments respectively</li>
+<li>these new nodes are placeholders for comments</li>
+<li>these new node types only occur in the comment table (since they can occur anywhere (lexically), there is no way to properly parent them in the regular AST nodes that reflects their position)</li>
+<li>AST.parse*(...) now returns sets the comment table on the compilation unit to include all comments (including attached and free-floating doc comments)</li>
+</ul>
+See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50697">50697</a>.
+</li>
+<li> Added option to control whether diagnosis for unused thrown exceptions should be enabled when overriding another
+method. By default, it is disabled.
+<pre>
+* COMPILER / Reporting Unused Declared Thrown Exception in Overridind Method
+*    When disabled, the compiler will not include overriding methods in its diagnosis for unused declared
+*    thrown exceptions.
+*    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException".
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding"
+*     - possible values:   { "enabled", "disabled" }
+*     - default:           "disabled"
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50644">50644</a>
+Deprecation check doesn't check that the @deprecated is at the beginning of the line
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27134">27134</a>
+Add a ASTNode for non-Javadoc comments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50683">50683</a>
+Improve DOM/AST support for doc comments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50697">50697</a>
+Improve DOM/AST support for locating all comments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50667">50667</a>
+Deadlock on Refactor -> Extract method
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47430">47430</a>
+the immutable bit is copied from the original resource to the ouput directory
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50601">50601</a>
+Blank lines before package declaration is one fewer than specified
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48292">48292</a>
+[DCR] Need AST.parsePartialClassFile(....)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50320">50320</a>
+Java model operations should use IResourceRuleFactory 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50207">50207</a>
+Compile errors fixed by 'refresh' do not reset problem list or package explorer error states 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49691">49691</a>
+JavaProject looses property listeners on preferences
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50265">50265</a>
+Emulate old formatter with the new formatter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50225">50225</a>
+Calling the default formatter with an empty string returns an invalid Edit 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44876">44876</a>
+"Unnecessary declaration of thrown exception" problems
+
+
+<a name="v_398"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M7 Build - 20th January 2004
+<br>Project org.eclipse.jdt.core v_398
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_398">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Major renaming of constants in the code formatter. See <code>org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants</code>. See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49908">49908</a>.
+The old constants have been deprecated and will be removed before M7. So we encourage you to save your code formatter preferences if
+you modified the default settings. The UI will provide an automatic conversion to the new options.
+</li>
+<li>Added API for alignment options in the code formatter.  See <code>org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants</code>. See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49968">49968</a>.
+</li>
+<li>Changed 3.0 APIs on <code>org.eclipse.jdt.core.dom.AST</code> to take an <code>IProgressMonitor</code>. This progress monitor is checked for the cancelation of the AST creation only.
+</li>
+<li>Added API on <code>org.eclipse.jdt.core.dom.AST</code> to parse an expression or statements or class body declarations without requiring the parsing
+of the whole compilation unit. This is still subject to change before 3.0.
+<pre>
+	/**
+	 * Parses the given source between the bounds specified by the given offset (inclusive)
+	 * and the given length and creates and returns a corresponding abstract syntax tree.
+	 * 
+	 * The root node of the new AST depends on the given kind.
+	 * - <code>org.eclipse.jdt.core.dom.AST.K_CLASS_BODY_DECLARATIONS</code>: The root node is an instance of
+	 * <code>org.eclipse.jdt.core.dom.TypeDeclaration</code>. The type declaration itself doesn't contain any information.
+	 * It is simply used to return all class body declarations inside the bodyDeclaratins() collection.
+	 * - <code>org.eclipse.jdt.core.dom.AST.K_STATEMENTS</code>: The root node is an instance of
+	 * <code>org.eclipse.jdt.core.dom.Block</code>. The block itself doesn't contain any information.
+	 * It is simply used to return all the statements.
+	 * - <code>org.eclipse.jdt.core.dom.AST.K_EXPRESSION</code>: The root node is an instance of a subclass of
+	 * <code>org.eclipse.jdt.core.dom.Expression</code>.
+	 *  
+	 * Each node in the subtree carries source range(s) information relating back
+	 * to positions in the given source (the given source itself
+	 * is not remembered with the AST). 
+	 * The source range usually begins at the first character of the first token 
+	 * corresponding to the node; leading whitespace and comments are <b>not</b>
+	 * included. The source range usually extends through the last character of
+	 * the last token corresponding to the node; trailing whitespace and
+	 * comments are <b>not</b> included. There are a handful of exceptions
+	 * (including compilation units and the various body declarations); the
+	 * specification for these node type spells out the details.
+	 * Source ranges nest properly: the source range for a child is always
+	 * within the source range of its parent, and the source ranges of sibling
+	 * nodes never overlap.
+	 * 
+	 * This method does not compute binding information; all <code>resolveBinding</code>
+	 * methods applied to nodes of the resulting AST return <code>null</code>.
+	 * 
+	 * <code>null</code> is returned:
+	 * 1. If a syntax error is detected while parsing,
+	 * 2. If the given source doesn't correspond to the given kind.
+	 *  
+	 * @param kind the given kind to parse
+	 * @param source the string to be parsed
+	 * @param offset the given offset
+	 * @param length the given length
+	 * @param options the given options. If null, <code>JavaCore.getOptions()</code> is used.
+	 * @param monitor the progress monitor used to check if the AST creation needs to be canceled
+	 * 
+	 * @return ASTNode
+	 * @see ASTNode#getStartPosition()
+	 * @see ASTNode#getLength()
+	 * @see AST#K_CLASS_BODY_DECLARATIONS
+	 * @see AST#K_EXPRESSION
+	 * @see AST#K_STATEMENTS
+	 * @see JavaCore#getOptions()
+	 * @since 3.0
+	 */
+	public static ASTNode parse(int kind, char[] source, int offset, int length, Map options, IProgressMonitor monitor);
+</pre>
+</li>
+<li>Added API on <code>org.eclipse.jdt.core.dom.AST</code> to parse a compilation unit and specify
+the set of options to use. This is still subject to change before 3.0. The previous API was directly
+using <code>JavaCore.getOptions()</code>. This could be problematic in case you want to parse assert
+statements.
+<pre>
+	/**
+	 * Parses the given string as a Java compilation unit and creates and 
+	 * returns a corresponding abstract syntax tree.
+	 * 
+	 * The given options are used to find out the compiler options to use while parsing.
+	 * This could implies the settings for the assertion support. See the <code>JavaCore.getOptions()</code>
+	 * methods for further details.
+	 * 
+	 * 
+	 * The returned compilation unit node is the root node of a new AST.
+	 * Each node in the subtree carries source range(s) information relating back
+	 * to positions in the given source string (the given source string itself
+	 * is not remembered with the AST). 
+	 * The source range usually begins at the first character of the first token 
+	 * corresponding to the node; leading whitespace and comments are <b>not</b>
+	 * included. The source range usually extends through the last character of
+	 * the last token corresponding to the node; trailing whitespace and
+	 * comments are <b>not</b> included. There are a handful of exceptions
+	 * (including compilation units and the various body declarations); the
+	 * specification for these node type spells out the details.
+	 * Source ranges nest properly: the source range for a child is always
+	 * within the source range of its parent, and the source ranges of sibling
+	 * nodes never overlap.
+	 * If a syntax error is detected while parsing, the relevant node(s) of the
+	 * tree will be flagged as <code>MALFORMED</code>.
+	 * 
+	 * 
+	 * This method does not compute binding information; all <code>resolveBinding</code>
+	 * methods applied to nodes of the resulting AST return <code>null</code>.
+	 * 
+	 * 
+	 * @param source the string to be parsed as a Java compilation unit
+	 * @param options options to use while parsing the file. If null, <code>JavaCore.getOptions()</code> is used.
+	 * @param monitor the progress monitor used to check if the AST creation needs to be canceled
+	 * @return CompilationUnit
+	 * @see ASTNode#getFlags()
+	 * @see ASTNode#MALFORMED
+	 * @see ASTNode#getStartPosition()
+	 * @see ASTNode#getLength()
+	 * @see JavaCore#getOptions()
+	 * @since 3.0
+	 */
+	public static CompilationUnit parseCompilationUnit(char[] source, Map options, IProgressMonitor monitor);
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50258">50258</a>
+AST.parseCompilationUnit(... IWorkingCopyOwner..) should allow null 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49937">49937</a>
+JavaDoc of ITypeBinding#isLocal() talks about local interfaces 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49845">49845</a>
+DCR: Allow to cancel the AST creation 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48489">48489</a>
+[DCR] AST support for a single expression (vs. CU)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49327">49327</a>
+formatter can return null TextEdit when parsing valid java
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49908">49908</a>
+Renaming of DefaultCodeFormatterConstants.java
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49968">49968</a>
+[formatter] Alignment API
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49953">49953</a>
+[Code Formatter] Cannot customize the spaces around brackets in array allocation expression
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=50025">50025</a>
+uppercase ZIP and JAR classpath entries ignored
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45060">45060</a>
+Missing external jar prevents build, but jar still in Java model 
+
+<a name="v_397"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M7 Build - 13th January 2004
+<br>Project org.eclipse.jdt.core v_397
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_397">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added API to get the scheduling rule for a Java element:
+<pre>
+	/**
+	 * Returns the scheduling rule associated with this Java element.
+	 * This is a handle-only method.
+	 * 
+	 * @return the scheduling rule associated with this Java element
+	 * @since 3.0
+	 */
+	ISchedulingRule getSchedulingRule();
+</pre>
+</li>
+<li>Code formatter: If you did change the value of the setting controlling the insertion of a white space between empty arguments of a method declaration,
+then you have to change it again. Indeed, a spelling mistake has been fixed in the constant name. See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49530">49530</a>.</li>
+<li>Inline tags are now supported in Javadoc comments:
+<ul><li>{@link} and {@linkplain} tags are now parsed using same rules as for @see tag. See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48385">48385</a>.
+<br>Because references declared in these tags should be now found during search operation,  the index format had to be changed. Indexes will be automatically regenerated upon subsequent search queries (accounting for indexing notification in search progress dialogs).</li>
+<li>{@inheritDoc} tag is now parsed. When this tag is present in a method javadoc comment, all missing tags errors are ignored.
+See bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45782">45782</a>.</li>
+</ul>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49843">49843</a>
+Not reporting error on constructor with no body
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49491">49491</a>
+Add option to toggle warning for Javadoc multiple same name @throws tags
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49260">49260</a>
+Malformed Javadoc Compiler option sensitive to line breaks
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45782">45782</a>
+[DCR] Compiler should take into account {@inheritDoc} tag
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48385">48385</a>
+[DCR] Need Javadoc warning for {@link }
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49760">49760</a>
+Splitting up FORMATTER_INSERT_SPACE_WITHIN_MESSAGE_SEND
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49763">49763</a>
+New formatter: Problem with empty statement in while
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48701">48701</a>
+NPE evaluating watch expression 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49290">49290</a>
+NullpointerException in TypeBinding.getInterfaces(). 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49660">49660</a>
+Code formatter line wrapping indentation ignores whitespace settings
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48293">48293</a>
+[DCR] IJavaElement should implement ISchedulingRule 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48459">48459</a>
+NPE in Type hierarchy 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49653">49653</a>
+Unnecessary white space is added after last semicolon in for statement without increments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49351">49351</a>
+New code formatter: left curly brace placement
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49530">49530</a>
+Spelling mistake in the FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_ARGUMENTS string constant
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49298">49298</a>
+Code formatter does not correctly space closing bracket on method calls
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48395">48395</a>
+Hierarchy on region misses local classes 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47743">47743</a>
+Open type hiearchy problems [type hierarchy] 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49571">49571</a>
+White space options for method and constructor declarations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49577">49577</a>
+Add an option to specify the number of blank lines between two type declarations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49551">49551</a>
+formatter fails on empty statement between package and imports
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39943">39943</a>
+[navigation] outliner auto-changes selection (multi-fields) 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49490">49490</a>
+New Code Formatter; Java Coding Conventions; Blank Lines; Before first declaration
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49561">49561</a>
+Commit should only lock parent's folder 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47699">47699</a>
+Make org.eclipse.core.runtime.compatibility non optional 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41444">41444</a>
+[navigation] error dialog on opening class file 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48350">48350</a>
+IType#resolveType(String) fails on local types 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49120">49120</a>
+search doesn't find references to anonymous inner methods 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49482">49482</a>
+New Code Formatter; if/else without curly braces; guardian clause (2)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49481">49481</a>
+New Code Formatter; if/else without curly braces; guardian clause (1)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49361">49361</a>
+FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_ARRAY_INITIALIZER
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49243">49243</a>
+New code formatter: missing feature
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49429">49429</a>
+error during build
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48404">48404</a>
+formatter: no edit returned
+
+<a name="v_396"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 18th December 2003 - 3.0 MILESTONE-6
+<br>Project org.eclipse.jdt.core v_396
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_396">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49081">49081</a>
+JDT is no more using the tab character by default for indentation 
+
+<a name="v_395"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 17th December 2003
+<br>Project org.eclipse.jdt.core v_395
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_395">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48706">48706</a>
+NPE in move refactoring 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48965">48965</a>
+Javadoc problem preference settings: Use 'include' instead of 'ignore'
+
+<a name="v_394"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 16th December 2003
+<br>Project org.eclipse.jdt.core v_394
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_394">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47209">47209</a>
+Javadoc: Type references are not found in @see tag inside a method reference
+
+<a name="v_393"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 16th December 2003
+<br>Project org.eclipse.jdt.core v_393
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_393">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48818">48818</a>
+NPE in delta processor 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48711">48711</a>
+javadoc-warning if derived exception in @throws clause
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46040">46040</a>
+NPE in Eclipse console 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48725">48725</a>
+Cannot search for local vars in jars. 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48749">48749</a>
+[Compiler] deprecation check in initializer fooled by trailing deprecated field decl
+
+
+<a name="v_392"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 15th December 2003
+<br>Project org.eclipse.jdt.core v_392
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_392">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Added option to avoid reporting a warning when overriding a deprecated method. By default, such
+warnings are no longer reported.
+<pre>
+ * COMPILER / Reporting Deprecation When Overriding Deprecated Method
+ *    When enabled, the compiler will signal the declaration of a method overriding a deprecated one.
+ *    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.deprecation".
+ *     - option id:        "org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod"
+ *     - possible values:   { "enabled", "disabled" }
+ *     - default:           "disabled"
+</pre>	 
+<li>Compiler options to signal problems with javadoc comments have been improved. User can now decide to report
+independently problems on invalid tags (syntax and references), missing tags and missing comments.
+Invalid references, missing tags or missing comments problem can be now ignored below a specific visibility level.
+Finally, user will also have the possibility to ignore missing tags and missing comments on overriding methods
+(assuming that complete Javadoc comments is done in superclass or interface declaration).
+<br>
+Here's the complete list of these options:
+<pre>
+	 * COMPILER / Reporting Invalid Javadoc Comment
+	 *    This is the generic control for the severity of Javadoc problems.
+	 *    When enabled, the compiler will issue an error or a warning for a problem in Javadoc.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadoc"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 *
+	 * COMPILER / Visibility Level For Invalid Javadoc Tags
+	 *    Set the minimum visibility level for Javadoc tag problems. Below this level problems will be ignored.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility"
+	 *     - possible values:   { "public", "protected", "default", "private" }
+	 *     - default:           "private"
+	 * 
+	 * COMPILER / Reporting Invalid Javadoc Tags
+	 *    When enabled, the compiler will signal unbound or unexpected reference tags in Javadoc.
+	 *    A 'throws' tag referencing an undeclared exception would be considered as unexpected.
+	 *    <br>Note that this diagnosis can be enabled based on the visibility of the construct associated with the Javadoc;
+	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility".
+	 *    <br>
+	 *    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.invalidJavadoc".
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadocTags"
+	 *     - possible values:   { "disabled", "enabled" }
+	 *     - default:           "enabled"
+	 * 
+	 * COMPILER / Reporting Missing Javadoc Tags
+	 *    This is the generic control for the severity of Javadoc missing tag problems.
+	 *    When enabled, the compiler will issue an error or a warning when tags are missing in Javadoc comments.
+	 *    <br>Note that this diagnosis can be enabled based on the visibility of the construct associated with the Javadoc;
+	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility".
+	 *    <br>
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocTags"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 * 
+	 * COMPILER / Visibility Level For Missing Javadoc Tags
+	 *    Set the minimum visibility level for Javadoc missing tag problems. Below this level problems will be ignored.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility"
+	 *     - possible values:   { "public", "protected", "default", "private" }
+	 *     - default:           "private"
+	 * 
+	 * COMPILER / Reporting Missing Javadoc Tags on Overriding Methods
+	 *    Specify whether the compiler will verify overriding methods in order to report Javadoc missing tag problems.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding"
+	 *     - possible values:   { "enabled", "disabled" }
+	 *     - default:           "enabled"
+	 * 
+	 * COMPILER / Reporting Missing Javadoc Comments
+	 *    This is the generic control for the severity of missing Javadoc comment problems.
+	 *    When enabled, the compiler will issue an error or a warning when Javadoc comments are missing.
+	 *    <br>Note that this diagnosis can be enabled based on the visibility of the construct associated with the expected Javadoc;
+	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility".
+	 *    <br>
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocComments"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 * 
+	 * COMPILER / Visibility Level For Missing Javadoc Comments
+	 *    Set the minimum visibility level for missing Javadoc problems. Below this level problems will be ignored.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility"
+	 *     - possible values:   { "public", "protected", "default", "private" }
+	 *     - default:           "public"
+	 * 
+	 * COMPILER / Reporting Missing Javadoc Comments on Overriding Methods
+	 *    Specify whether the compiler will verify overriding methods in order to report missing Javadoc comment problems.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding"
+	 *     - possible values:   { "enabled", "disabled" }
+	 *     - default:           "enabled"
+	 * 
+</pre>
+Note that backward compatibility with previous options IDs: <code>"org.eclipse.jdt.core.compiler.problem.missingJavadoc"</code>
+will be supported until 3.0M7 build and removed after.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47214">47214</a>
+Cannot open declaration on a selected method of an anonymous class 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47795">47795</a>
+NPE selecting method in anonymous 2 level deep 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48335">48335</a>
+[Compiler] Need option to not report deprecation in override scenarii
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48523">48523</a>
+@throws reference incorrectly warned as not declared
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47940">47940</a>
+Unable to control level  of JavaDoc errors
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47319">47319</a>
+Compiler warns on missing Javadoc tags for private methods.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46976">46976</a>
+Do not warn about 'Missing Javadoc'  for overriding methods
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46854">46854</a>
+[DCR] Javadoc configuration setting needs more flexibility
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48617">48617</a>
+Error range for unresolved names in qualified references
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48333">48333</a>
+[Compiler] Implicit deprecation isn't propagated to anonymous type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46084">46084</a>
+ArrayIndexOutOfBoundsException in compiler after feeding with non-real java code 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43354">43354</a>
+CodeAssist relevance should privilege package completion over type name 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48422">48422</a>
+Calling isStructureKnown() on ILocalVaraible throws JavaModelExceptions 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48261">48261</a>
+Search does not show results 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47213">47213</a>
+Inefficient recursion while initializing classpath container 
+
+<a name="v_391"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 10th December 2003
+<br>Project org.eclipse.jdt.core v_391
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_391">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>We reverted back the behavior when using the class literal. See bugs <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=37565">37565</a> and
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48086">48086</a>. As long as javac doesn't clarify this case, we keep
+the old behavior.</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48086">48086</a>
+Compiler does not resolve references in static init blocks correctly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48353">48353</a>
+Indexes deleted on shutdown 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42579">42579</a>
+Eclipse allows setting a source folder's parent as output folder, which wipes out source code
+
+<a name="v_390"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 9th December 2003
+<br>Project org.eclipse.jdt.core v_390
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_390">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>The classpath validation rules now allow an excluded directory to be used as an output location. 
+Remember that a source folder can be associated with exclusion rules so as to eliminate portions of the
+source tree. Nested source/library entries were already allowed given proper exclusion rules were specified,
+now we also enable nesting an output folder as well under the same restrictions.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47338">47338</a>
+CCE in CompletionParser
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45589">45589</a>
+Too many Util classes in JDTCore 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39539">39539</a>
+Cannot select excluded directory as output folder for class files
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48070">48070</a>
+[CodeAssist] ArrayIndexOutOfBoundsException in AssistParster
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48167">48167</a>
+Indentation/line wrapping problems with array initializers
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32022">32022</a>
+Indirect static proposal: Wrong compiler positions
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48141">48141</a>
+Formatter: Java Conventions/WS/Expressions/Operators 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45157">45157</a>
+Source Formatter: Clear all Blank lines needs to have the ability to set a number of lines to keep.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44673">44673</a>
+Formatting
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38523">38523</a>
+so add "Insert new line after each parameter if line is too long" checkbox to Preferences > Java > Code Formatter > New Lines
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34897">34897</a>
+Code Formatter feature request
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46937">46937</a>
+[Compiler] Marking a field deprecated still report deprecated usage
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47989">47989</a>
+Exception when searching for IPackageFragment "java.util.zip"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47997">47997</a>
+No empty line after opening brace [formatter]
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48064">48064</a>
+Javadoc: NPE during build process
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44815">44815</a>
+Continuation indent for array initializer should be customizable
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44813">44813</a>
+Option "Insert new line before an open brace" should work also for array initializers
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43212">43212</a>
+catch variable not recognized by code-completion 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46060">46060</a>
+regression - content assist fails to present proposal 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47918">47918</a>
+New code Formatter 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47968">47968</a>
+Cannot find @see references in Class javadoc comment
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47909">47909</a>
+Javadoc: NPE while searching a constructor references in jdt-core
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47986">47986</a>
+Formatting of 'for' initializers
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47976">47976</a>
+Implementation of IField.getConstant() fails for some constants
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47886">47886</a>
+[Compiler] ACC_SUPER bit sets for interfaces
+
+<a name="v_389"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 2nd December 2003
+<br>Project org.eclipse.jdt.core v_389
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_389">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Spec and implementation for <code>ITypeBinding.getBinaryName()</code> was changed to be '.' separated:
+<pre>
+ /**
+ * Returns the binary name of this type binding.
+ * The binary name of a class is defined in the Java Language 
+ * Specification 2nd edition, section 13.1.
+ *
+ * Note that in some cases, the binary name may be unavailable.
+ * This may happen, for example, for a local type declared in 
+ * unreachable code.
+ *
+ * @return the binary name of this type, or null 
+ * if the binary name is unknown
+ * @since 3.0
+ */
+public String getBinaryName();
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47881">47881</a>
+[Compiler] x &amp;&amp; false evaluates to "true"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47802">47802</a>
+New Code Formatter: NEXT_PER_LINE_SPLIT
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47811">47811</a>
+New Code Formatter: doesn't handle several classes per CU
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47801">47801</a>
+New Code Formatter: INSERT_SPACE_AFTER_PREFIX_OPERATOR
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47800">47800</a>
+New Code Formatter: BINARY_EXPRESSION_ALIGNMENT
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47799">47799</a>
+New Code Formatter: PUT_EMPTY_STATEMENT_ON_NEW_LINE
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47776">47776</a>
+java.lang.VerifyError / Illegal target of jump or branch compiling with 3.0 M5
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47341">47341</a>
+Javadoc problem for @see to protected method
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47339">47339</a>
+Javadoc problem while using @see tag
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47132">47132</a>
+Javadoc for method in anonymous type should not be mark as missing
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47215">47215</a>
+Javadoc: type reference in @see tag ignore the following text
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46761">46761</a>
+Search for references: misses match in Javadoc
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46675">46675</a>
+[Compiler] NullPointerException with ? operator
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35220">35220</a>
+CodeAssist - method of anonymous type should not be proposed
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47631">47631</a>
+PerThreadObject (JavaModelManager.deltaState) leaks Threads.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46470">46470</a>
+Wrong completion after a switch
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35232">35232</a>
+CodeAssist - wrong completion for static method in anonymous type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47401">47401</a>
+Wrong code assist proposals in anonymous class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47443">47443</a>
+All projects touched on startup
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44493">44493</a>
+Improve formatting of throws clauses
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44765">44765</a>
+New formatter not properly formatting long method invocation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44653">44653</a>
+// $NON-NLS-1$ comments not kept on same line of the string while formatting
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46699">46699</a>
+IBinding.isSynthetic() returns false for compiler-generated constructor
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47415">47415</a>
+[Search] package references confused with multiple fragments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38679">38679</a>
+Search for class ref shows local class containing a match on an import [search]
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47049">47049</a>
+[Builder] Build output folder not getting flushed because files are not marked as derived
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46613">46613</a>
+AST nodes and string buffers
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47396">47396</a>
+JAVA AST Creation failure
+
+<a name="v_388"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 25th November 2003
+<br>Project org.eclipse.jdt.core v_388
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_388">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47082">47082</a>
+[Compiler] Problem with final variable initialization
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47180">47180</a>
+Merge different type declarations into one class
+
+
+<a name="v_387"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 21st November 2003 - 3.0 MILESTONE-5
+<br>Project org.eclipse.jdt.core v_387
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_387">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44397">44397</a>
+Search doesn't find references to local types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46571">46571</a>
+Searching for all occurrences for method declarated in local types doesn't wor
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46943">46943</a>
+refactoring: encapsulate field of local type: references from enclosing type are not replaced by setter 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47180">47180</a>
+NPE in Delta Processor 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46788">46788</a>
+Export scripts: shouldn't use variable name version
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47160">47160</a>
+ArrayIndexOutOfBoundsException from CodeSnippetParser
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47177">47177</a>
+ClassCastException during hover
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47079">47079</a>
+[Builder] suspicious side-effects during incremental compile
+
+<a name="v_386"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 20th November 2003
+<br>Project org.eclipse.jdt.core v_386
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_386">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Removed APIs that create an <code>ICompilationUnit</code> handle given a <code>WorkingCopyOwner</code>
+	 as these can be replaced with <code>ICompilationUnit.findWorkingCopy(WorkingCopyOwner)</code>:
+	 <ul>
+	 <li><code>IPackageFragment.getCompilationUnit(String, WorkingCopyOwner)</code></li>
+	 <li><code>JavaCore.create(IFile, WorkingCopyOwner)</code></li>
+	 <li><code>JavaCore.create(IResource, WorkingCopyOwner)</code></li>
+	 <li><code>JavaCore.createCompilationUnitFrom(IFile, WorkingCopyOwner)</code></li>
+	 <li><code>IDOMCompilationUnit.getCompilationUnit(IPackageFragment, WorkingCopyOwner)</code></li>
+	 </ul>
+	 <br>
+</li>
+<li>Added API on <code>ICompilationUnit</code> to find an existing working copy given a working
+	 copy owner (it replaces <code>IWorkingCopy.findSharedWorkingCopy(IBufferFactory)</code>):
+<pre>
+/**
+ * Finds the working copy for this compilation unit, given a <code>WorkingCopyOwner</code>. 
+ * If no working copy has been created for this compilation unit associated with this
+ * working copy owner, returns <code>null</code>.
+ *
+ * Users of this method must not destroy the resulting working copy. 
+ * 
+ * @param owner the given <code>WorkingCopyOwner</code>
+ * @return the found working copy for this compilation unit, <code>null</code> if none
+ * @see WorkingCopyOwner
+ * @since 3.0
+ */
+ICompilationUnit findWorkingCopy(WorkingCopyOwner owner);
+</pre>
+</li>
+<li>Added API on <code>IClassFile</code> to create a working copy on a class file (it replaces 
+	 <code>IClassFile.getWorkingCopy(IProgressMonitor, IBufferFactory)</code>):
+<pre>
+/**
+ * Returns a working copy on the source associated with this class file using the given 
+ * owner to create the buffer, or <code>null</code> if there is no source associated
+ * with the class file.
+ * 
+ * The buffer will be automatically initialized with the source of the class file
+ * upon creation.
+ * 
+ * The only valid operations on this working copy are <code>getBuffer()</code> or <code>getPrimary()</code>.
+ *
+ * @param owner the owner that creates a buffer that is used to get the content of the working copy
+ *                 or <code>null</code> if the primary owner should be used
+ * @param monitor a progress monitor used to report progress while opening this compilation unit
+ *                 or <code>null</code> if no progress should be reported 
+ * @return a  a working copy on the source associated with this class file
+ * @exception JavaModelException if the source of this class file can
+ *   not be determined. Reasons include:
+ *   - This class file does not exist (ELEMENT_DOES_NOT_EXIST)
+ * @since 3.0
+ */
+ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException;
+</pre>
+</li>
+<li>Added API on <code>ITypeBinding</code> to get the binary name of a type binding:
+<pre>
+/**
+ * Returns the binary name (as defined in the Java Language 
+ * Specification Chapter 13 Section 1) of this type binding.
+ * It is however slash ('/') separated instead of dot ('.') separated as said
+ * in the specification.
+ * Returns <code>null</code> if the type is defined in code that is unreachable.
+ *
+ * @return the binary name of this type or <code>null</code> if this type is unreachable
+ */
+String getBinaryName();
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46012">46012</a>
+IllegalArgumentException in StringLiteral
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46769">46769</a>
+NPE in PatternLocator.qualifiedSourceName
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47074">47074</a>
+inability to detect invalid cast between interfaces
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46057">46057</a>
+need mechanism for retrieving the name of anonymous and local classes 
+
+<a name="v_385"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 19th November 2003
+<br>Project org.eclipse.jdt.core v_385
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_385">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46964">46964</a>
+Can not set Javadoc compiler setting
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46901">46901</a>
+Strange compile error in javadoc
+
+<a name="v_384"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 19th November 2003
+<br>Project org.eclipse.jdt.core v_384
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_384">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added API on <code>ICompilationUnit</code> to query whether the working copy's resource has changed 
+	 (it replaces <code>IWorkingCopy.isBasedOn(IResource)</code>):
+<pre>
+/**
+ * Returns whether the resource of this working copy has changed since the
+ * inception of this working copy.
+ * Returns <code>false</code> if this compilation unit is not in working copy mode.
+ * 
+ * @return whether the resource has changed
+ * @since 3.0
+ */
+public boolean hasResourceChanged();
+</pre>
+</li>
+<li>Added APIs on <code>IType</code> to create hierarchies using <code>ICompilationUnits</code> instead of
+     <code>IWorkingCopies</code>:
+<pre>
+/**
+ * Creates and returns a type hierarchy for this type containing
+ * this type and all of its supertypes, considering types in the given 
+ * working copies. In other words, the list of working copies will take 
+ * precedence over their original compilation units in the workspace.
+ *
+ * Note that passing an empty working copy will be as if the original compilation
+ * unit had been deleted.
+ *
+ * @param workingCopies the working copies that take precedence over their original compilation units
+ * @param monitor the given progress monitor
+ * @return a type hierarchy for this type containing this type and all of its supertypes
+ * @exception JavaModelException if this element does not exist or if an
+ *		exception occurs while accessing its corresponding resource.
+ * @since 3.0
+ */
+ITypeHierarchy newSupertypeHierarchy(ICompilationUnit[] workingCopies, IProgressMonitor monitor) throws JavaModelException;
+
+/**
+ * Creates and returns a type hierarchy for this type containing
+ * this type, all of its supertypes, and all its subtypes in the workspace, 
+ * considering types in the given working copies. In other words, the list of working 
+ * copies that will take precedence over their original compilation units in the workspace.
+ * 
+ * Note that passing an empty working copy will be as if the original compilation
+ * unit had been deleted.
+ *
+ * @param workingCopies the working copies that take precedence over their original compilation units
+ * @param monitor the given progress monitor
+ * @return a type hierarchy for this type containing
+ * this type, all of its supertypes, and all its subtypes in the workspace
+ * @exception JavaModelException if this element does not exist or if an
+ *		exception occurs while accessing its corresponding resource.
+ * @since 3.0
+ */
+ITypeHierarchy newTypeHierarchy(ICompilationUnit[] workingCopies, IProgressMonitor monitor) throws JavaModelException;
+</pre>
+<li>Added API on <code>SearchEngine</code> to create a search engine using 
+	 <code>ICompilationUnits</code> instead of <code>IWorkingCopies</code>:
+<pre>
+/**
+ * Creates a new search engine with a list of working copies that will take precedence over 
+ * their original compilation units in the subsequent search operations.
+ *
+ * Note that passing an empty working copy will be as if the original compilation
+ * unit had been deleted.
+ *
+ * Since 3.0 the given working copies take precedence over primary working copies (if any).
+ * 
+ * @param workingCopies the working copies that take precedence over their original compilation units
+ * @since 3.0
+ */
+public SearchEngine(ICompilationUnit[] workingCopies) {...}
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+
+<a name="v_383"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 18th November 2003
+<br>Project org.eclipse.jdt.core v_383
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_383">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>To avoid confusion with annotations introduced in JDK 1.5 grammar, all internal references to "annotation" (added to handle Javadoc comments) 
+got renamed into "Javadoc". As a consequence of this is that IDs for optional Javadoc problems have been updated accordingly:
+<pre>
+	 * COMPILER / Reporting Invalid Javadoc Comment
+	 *    When enabled, the compiler will issue an error or a warning when a javadoc comment is inconsistent,
+	 *    misses a tag entry or contains invalid references.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadoc"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 * COMPILER / Reporting Missing Javadoc Comment
+	 *    When enabled, the compiler will signal cases where public class, interface, method, constructor or field
+	 *    (considered as part of the API) has no javadoc comment.
+	 *    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.invalidJavadoc".
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadoc"
+	 *     - possible values:   { "enabled", "disabled" }
+	 *     - default:           "disabled"
+</pre>
+Note that backward compatibility with previous options IDs: <code>"org.eclipse.jdt.core.compiler.problem.invalidAnnotation"</code> and <code>"org.eclipse.jdt.core.compiler.problem.missingAnnotation"</code>
+will be supported until 3.0M6 build and removed after.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46717">46717</a>
+The code formatter does not insert a new line before /** Javadoc
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45958">45958</a>
+Compiler wrongly complains against valid @see constructor reference
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45112">45112</a>
+Use Javadoc instead of Annotation for comment compiler parsing
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46052">46052</a>
+result of ITypeHierarchy.getAllSuperTypes() does not include Object 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46192">46192</a>
+ILocalVariable.exists() always returns false 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=14103">14103</a>
+[Builder] Too many dependents found when incrementally recompiling
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39601">39601</a>
+[DOM/AST] clarify documentation of source ranges
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39739">39739</a>
+[DOM/AST] VariableDeclarationStatements aren't full statements
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46690">46690</a>
+Code formatter always inserts space after comma in multiple locals or field declarations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46689">46689</a>
+Code formatter always inserts a space in front of the '-' unary operator
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46686">46686</a>
+Code formatter doesn't indent properly statements following a switch statement
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46356">46356</a>
+[Builder] simple/qualified names list for indicting dependents should be hashed collections
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46612">46612</a>
+[DOM/AST] BodyDeclaration should provide a method getModifiers
+
+<a name="v_382"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 10th November 2003
+<br>Project org.eclipse.jdt.core v_382
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_382">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46276">46276</a>
+Search for package declarations incorrectly finds matches in clone project
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46099">46099</a>
+Batch compiler doesn't print stats if errors and not proceeding on errors
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40950">40950</a>
+[infrastructure] NPE from indexer
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46150">46150</a>
+formatter failed to format
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46013">46013</a>
+IBinding.getKey() for local shouldn't return null 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46033">46033</a>
+New formatter not formatting nested constructor/methods properly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46093">46093</a>
+[Builder] Unoptimal pre-check for not writing class files
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45847">45847</a>
+[Builder] Reading build state is slow
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45982">45982</a>
+Array out of bounds error while editing Java file
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41611">41611</a>
+CreateCompilationUnitOperation.executeOperation() should probably force creation more agressively 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45113">45113</a>
+No hierarchy refresh when on region 
+
+
+<a name="v_381"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 4th November 2003
+<br>Project org.eclipse.jdt.core v_381
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_381">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45968">45968</a>
+[new formatter] Formatter introduces empty lines inside line comments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44450">44450</a>
+Strange name range for anonymous classes. 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43139">43139</a>
+Delete member in Outliner not working 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45944">45944</a>
+Stack trace attempting to find markers on a closed project 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44884">44884</a>
+Wrong list displayed while code completion 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45661">45661</a>
+Search for references of default package fails
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45671">45671</a>
+Need source range and getTypeSignature() for local variables 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45575">45575</a>
+Failure in nightly build of formatter tests (test325)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45783">45783</a>
+NPE in MatchLocator
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22073">22073</a>
+Each "format" adds one more level of indentation.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23709">23709</a>
+for (/*comment*/; causes indentation to misbehave 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27249">27249</a>
+incorrect formatting of empty array initialization blocks 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29473">29473</a>
+wrong formatting of if...try... catch... else 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45786">45786</a>
+No selection on method declaration in field initializer 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45721">45721</a>
+Getting wrong deltas 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45674">45674</a>
+Compiler should allow compound assignment to final in unreachable code
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43984">43984</a>
+NPE in background search
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45707">45707</a>
+Autobuild does not kick in when using classpath containers
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45655">45655</a>
+exception while editing java file 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42287">42287</a>
+Should consider qualified name token positions
+
+<a name="v_380"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 28th October 2003
+<br>Project org.eclipse.jdt.core v_380
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_380">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Search is now able to find local variable references and declarations. In order to trigger such a search, the search engine must
+	be fed with an <code>ILocalVariable</code> element. Searching a local variable by its name is not supported.
+</li>
+<li>Search is now finding references in Javadoc comments. Found references are method parameters declared in <code>@param</code> tags, 
+	types of exceptions declared in <code>@throws</code>/<code>@exception</code> tags and all instance variables, methods, types or 
+	packages declared in <code>@see</code> tags.
+	<br>Note that only valid references in Javadoc comments will be reported during search. In order to ensure the integrity of your Javadoc comments,
+	you may want to enable the compiler check for Javadoc (Preferences>Java>Compiler>Style>Problem in Javadoc tags).
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45641">45641</a>
+CCE when using declarations view 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45596">45596</a>
+Wrongly complains about missing parameter javadoc entry in anonymous class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45592">45592</a>
+NPE while searching a method references in jdt-core
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45520">45520</a>
+Potential NPE
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45518">45518</a>
+Search has to find references put in javadoc comments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45436">45436</a>
+Javadoc warnings: wrong errors in AST
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45198">45198</a>
+NPE from AnnotationParser
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45459">45459</a>
+JDT compiler more restrictive than javac
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35899">35899</a>
+"hierarchy of type ... inconsistent" error message wrong
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43967">43967</a>
+Search for references on local variable finds all occurances of variables of that type not just that variable. 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37509">37509</a>
+Open Declaration opens class declaration for local variables 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45433">45433</a>
+Bug7 (and counting ;-): hundretAssignmentsToFinalVariable()
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45357">45357</a>
+Compiler-Bug: "The local variable oResult may not have been initialized".txt
+
+<a name="v_379"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 21st October 2003
+<br>Project org.eclipse.jdt.core v_379
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_379">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Compiler options for controlling the severity of problems for invalid imports or unreachable code got discontinued. Indeed, allowing this kind of problems to be ignored
+or treated as a warning would violate the language spec. As a consequence, <code>JavaCore#COMPILER_PB_INVALID_IMPORT</code> and
+<code>JavaCore#COMPILER_PB_UNREACHABLE_CODE</code> got deprecated, 
+further attempts to set these preferences are now ignored and import problems or unreachable code are always reported as errors.
+<li> The warning level of the batch compiler can now be configured more easily using <code>-warn:+...</code> or <code>-warn:-...</code> command line
+argument (as opposed to only existing <code>-warn:...</code> command line argument). 
+<code>-warn:+...</code> will not override the default warning level, but simply enable
+a few more specific warnings. Similarily, <code>-warn:-...</code> will only disable specific warnings.
+<br>Note, by default the batch compiler is reporting the following warnings:
+	<ul>
+	<li>'assert' used as identifier</li>
+	<li>char[] in String concat</li>
+	<li>method with constructor name</li>
+	<li>deprecation outside deprecated code</li>
+	<li>finally block not completing normally</li>
+	<li>interface non-inherited method compatibility</li>
+	<li>hidden catch block</li>
+	<li>assignment without effect</li>
+	<li>attempt to override package-default method</li>
+	<li>unused import declaration</li>
+	<li>non-static reference to static member</li>
+	</ul>
+</li>
+<li>Code select (i.e. <code>ICodeAssit.codeSelect(...)</code>) now returns an <code>ILocalVariable</code>
+     element when a local variable or an argument is selected. 
+     <br>Note that <code>ILocalVariable</code>s are pseudo-elements:
+     they are not part of the Java model (<code>exists()</code> always returns <code>false</code>), 
+     they are not returned when asking for the children of a method, and there is no other way to create such
+     an element. One can only ask for the source range (<code>ISourceReference.getSourceRange()</code>) or
+     for the name range (<code>ILocalVariable.getNameRange()</code>) of the local variable.
+     <br>Searching a local variable is not yet implemented, but it is on the plan.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35389">35389</a>
+Compiler settings can violate JLS [build path]
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44869">44869</a>
+Search: no refs found to overridden method in binary subclass
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45110">45110</a>
+No constant for '..compiler.problem.missingAnnotation'
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45100">45100</a>
+[formatter] test144 fails
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45036">45036</a>
+[formatter] New formatter fails formatting multiple field declarations using K_CLASSBODY_DECLARATION kind
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45037">45037</a>
+[formatter] New formatter doesn't insert a new line before the while in a do/while
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45014">45014</a>
+Formatter misplaces semicolon
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44757">44757</a>
+New code formatter does not format switch statements correctly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44647">44647</a>
+NPE code completion
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43754">43754</a>
+How to position this comment?
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44839">44839</a>
+New formater fails with out of memory error
+
+<a name="v_378"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 15th October 2003
+<br>Project org.eclipse.jdt.core v_378
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_378">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Removed dependency on Xerces.
+</li>
+<li> Remove deprecated previously added API <code>IJavaProject#forceClasspathReload(IProgressMonitor)</code>
+(see comment of <a href="#v_368">v_368</a> drop below).
+</li>
+<li>Added optional compiler problem to signal problems with javadoc annotation.
+<pre>
+	 * COMPILER / Reporting Invalid Javadoc Annotation
+	 *    When enabled, the compiler will issue an error or a warning when a javadoc annotation is inconsistent,
+	 *    misses a tag entry or contains invalid references.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidAnnotation"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 * COMPILER / Reporting Missing Javadoc Annotation
+	 *    When enabled, the compiler will signal cases where public class, interface, method, constructor or field
+	 *    (considered as part of the API) has no javadoc annotation.
+	 *    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.invalidAnnotation".
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingAnnotation"
+	 *     - possible values:   { "enabled", "disabled" }
+	 *     - default:           "disabled"
+	 * 
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44715">44715</a>
+NullPointerException compiling Java file
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44697">44697</a>
+Bug when i search reference of 'String' in 3.0M4
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38091">38091</a>
+DCR - Generate warnings for JavaDoc missing entries
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44637">44637</a>
+NPE in Initializer.getPrimaryElement() 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42762">42762</a>
+Compiler tests should run both in 1.3 and 1.4 mode 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44580">44580</a>
+No outline when unit name is not valid
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44651">44651</a>
+Wrong formatting of multiple local variables declarations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44643">44643</a>
+Remove dependancy to xerces
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44662">44662</a>
+Should not validate unit/classfile handles upon creation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44400">44400</a>
+Unnecessary cast not being picked up
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44143">44143</a>
+[JSR202] Remove usage of jsr bytecodes in 1.5 mode
+
+<a name="v_377"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 9th October 2003 - 3.0 MILESTONE-4
+<br>Project org.eclipse.jdt.core v_377
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_377">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44576">44576</a>
+Code formatter option "Insert a new line before an opening brace" has no effect for single else
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44570">44570</a>
+Code formatter option "Insert a new line inside an empty block" has no effect
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44503">44503</a>
+Unoptimal formatting for long constructor argument
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44546">44546</a>
+New formatter unable to format
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44506">44506</a>
+Type hierarchy is missing anonymous type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44481">44481</a>
+"Insert new line between else and if" is not working as expected
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44480">44480</a>
+Formatting the formatted string should not produce edits
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44444">44444</a>
+jdt.core in trouble when project has no JRE
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44437">44437</a>
+Typo in plugin.properties
+
+<a name="v_376"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 8th October 2003
+<br>Project org.eclipse.jdt.core v_376
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_376">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Fix for bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44289">44289</a>
+     requires the index format to be changed. Indexes will be automatically regenerated upon
+     subsequent search queries (accounting for indexing notification in search progress dialogs).
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44308">44308</a>
+NullPointerException when searching jars
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44341">44341</a>
+NPE from  delta processor
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44119">44119</a>
+NPE while searching for references to Action#run() 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44331">44331</a>
+Need indication that removal/add was targeted to a primary working copy 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32639">32639</a>
+Missing empty fine-grain delta when reconciling 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44292">44292</a>
+IDOMType.setFlags(Flag.AccPublic) when applied to an interface having default visibility produces uncompilable code
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44293">44293</a>
+DOMFactory.createInitializer() always creates a static intializer
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44289">44289</a>
+Search broken 
+
+<a name="v_374"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 7th October 2003
+<br>Project org.eclipse.jdt.core v_374
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_374">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>The new code formatter can be activated in the ui. See the work in progress section. This first release doesn't expose
+yet all the preferences of the new code formatter. This will be done after M4. However the old formatter options should be honored by 
+the new code formatter. This is a work in progress and all problems should be reported against JDT/Core.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44242">44242</a>
+Deadlock during jdt/debug test 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44066">44066</a>
+Package Explorer doesn't show new file 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44219">44219</a>
+NPE while creating TypeHierarchy for binary type "Group" 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44073">44073</a>
+Override methods action does not work for local types [code manipulation] 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=16231">16231</a>
+formatter creates ugly array initializer expressions
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=6284">6284</a>
+Java formatter enhancements
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=6268">6268</a>
+Code formatting
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44036">44036</a>
+Java code formatter wraps line too much.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43651">43651</a>
+Linewrapping of throws declarations (if many)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43545">43545</a>
+Code Formatter: Don't separate long "import" clause.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43272">43272</a>
+feature request : extend the code formatter to support blanks between method / class name and bracket.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43050">43050</a>
+Formatting long arguments not very readable
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40777">40777</a>
+Incorrect formatting for anonymous inner class with comment
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39607">39607</a>
+Incorrect formatting of anonymous inner class inside if statement
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39603">39603</a>
+for-Statement not correctly formatted by Codeformatter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39357">39357</a>
+Better code formatting
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38151">38151</a>
+Code formatter adds an unwanted blank line after an abstract method with a "throws" clause.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37106">37106</a>
+Code Formatter: Option to double indent wrapped lines in if statments, etc.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37057">37057</a>
+Code Formatter: Reduce number of blank lines to 1
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36832">36832</a>
+wrong indent on Code Format of anonymous class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36455">36455</a>
+[Formatting] Too long lines look ugly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36108">36108</a>
+Code Formatter Clear Blank Lines Doesn't Work
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35799">35799</a>
+code formatter: missing space after last array initializer
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35433">35433</a>
+Simple Feature Request - Code Formatter Enhancement
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35173">35173</a>
+Code formatter incorrectly formats this case:
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29110">29110</a>
+RFE: Disable line splitting in the code formatter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28098">28098</a>
+Code Formatter doesn't format JavaDoc indentation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27196">27196</a>
+Code Formatter Won't Indent Braces
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25559">25559</a>
+more code formatter options
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24200">24200</a>
+"Space inside parens &amp; brackets" option in Code Formatter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23144">23144</a>
+formatter issues
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22528">22528</a>
+Code formatter incorrectly indents lines
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22313">22313</a>
+Formatter doesn't like some comment
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21943">21943</a>
+Formatter should allow removing space after for/while/if
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20721">20721</a>
+Code formatter bug
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=19999">19999</a>
+Code Formatter always clears blank lines to 1
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=19811">19811</a>
+Code formatter bugs
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=17349">17349</a>
+Code Formatter incorrectly formats static initializer
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=16233">16233</a>
+formatter problem with constructor, array and line-end comments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=15286">15286</a>
+Code formatter: long param lists and line wrapping
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=14659">14659</a>
+Align method arguments on line break
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=12456">12456</a>
+Add formatter options for controlling spaces
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=12321">12321</a>
+Code formatter and comments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=10052">10052</a>
+CodeFormatter - line splitting enhancement.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=7439">7439</a>
+incorrect formatting: empty inner class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=7224">7224</a>
+Formatting splits package names in ugly ways
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=6747">6747</a>
+Code Formatter exchange several blank lines w/ one
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=5824">5824</a>
+Code Formatter needs to be more customizable to be useful
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3327">3327</a>
+Formatter - should ensure one empty line before a method declaration (1GHOJWD)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3276">3276</a>
+DCR: (LOW) Formatter option to not indent methods (1GE39ZO)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3181">3181</a>
+Does not format nicely anonymous type (1FRLTO1)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44085">44085</a>
+becomeWorkingCopy() should add the working copy in the model 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44052">44052</a>
+Deadlock on startup
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44092">44092</a>
+Methods to generate parser files are not correct 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44084">44084</a>
+No refresh when deleting edited unit 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41643">41643</a>
+Code assist doesn't propose all valid types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44065">44065</a>
+NPE during hot code replace 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43897">43897</a>
+No completion in cast expression
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44061">44061</a>
+CodeAssist - no completion after class literal access
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44018">44018</a>
+Change superfluous semicolon error message
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43872">43872</a>
+Hierarchy does not update properly when local class eliminated [type hierarchy] 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43294">43294</a>
+Primary working copy: No updates when changed in working copy mode 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43907">43907</a>
+Too many warnings reported by the jdt compiler adapter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43847">43847</a>
+IPackageFragment not updated after CUs have moved 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43879">43879</a>
+working copy commit outside classpath doesn't save buffer
+
+<a name="v_373"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 30th September 2003
+<br>Project org.eclipse.jdt.core v_373
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_373">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43728">43728</a>
+Optimize CompilerOptions(Map....)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43842">43842</a>
+JDTCompilerAdapter doesn't find bootclasspath 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40782">40782</a>
+Primary working copies: unnecessary deltas on save 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43300">43300</a>
+SearchEngine(IWorkingCopy[] workingCopies) not backward compatible 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43670">43670</a>
+No classpath refresh when replacing binary project with source form
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43600">43600</a>
+NPE from JDTCompilerAdapter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43636">43636</a>
+Compiler complain that class cannot be resolved when it should be only not visible
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43208">43208</a>
+ICompilation.move not supported when in workingCopyMode 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40793">40793</a>
+Primary working copies: Type search does not find type in modified CU 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43587">43587</a>
+Searching for references to default constructors reports questionable results
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36143">36143</a>
+Type hierarchy doesn't include anonymous subclasses 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=8613">8613</a>
+Outline should show anonymous inner classes 
+
+
+<a name="v_372"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 24th September 2003
+<br>Project org.eclipse.jdt.core v_372
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_372">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42692">42692</a>
+JavaCC files cause VerifyError when compiled with Eclipse
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43437">43437</a>
+Scanner does not like string literals
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43485">43485</a>
+NPE in SearchEngine
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37659">37659</a>
+[plan item] Improve shared working copies 
+
+
+<a name="v_371"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 22nd September 2003
+<br>Project org.eclipse.jdt.core v_371
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_371">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> As a consequence of migrating to background autobuild, the JavaModel will no longer broadcast deltas
+during PRE_AUTO_BUILD event notification. These were somewhat inconsistent in so far as the model wasn't
+totally up to date anyway. Now the model will only fire deltas during POST_CHANGE, or working copy reconcile
+operations.
+</li>
+<li>Part of the new support for local and anonymous types in the Java model has been released. 
+	<p>
+	This includes:
+	<ul>
+	<li>local and anonymous types are shown in the Outline view and the Package Explorer view</li>
+	<li>Java element deltas for these types are notified</li>
+	<li>handles on these types can be created (see <code>IMember.getType(String, int)</code>)</li>
+	<li><code>getChildren()</code> on a method, a field or an initializer returns the local or anonymous types defined in this element</li>
+	<li>mementos for these handles are supported</li>
+	<li>open on selection (F3) in a Java editor goes to the local type definition</li>
+	<li>type hierarchies contain anonymous and local types</li>
+	</ul>
+	<p>
+	This doesn't yet include:
+	<ul>
+	<li>search on these types</li>
+	<li>anonymous/local binary types</li>
+	</ul>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42832">42832</a>
+Cannot get rid of this error even if the compiler settings is ignore for incompatible required binaries
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41583">41583</a>
+[misc] Eclipse cannot save or compile files in non-Java project anymore
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43274">43274</a>
+Type hierarchy broken 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38931">38931</a>
+Migrate delta processor to comply to new notification scheme in 3.0
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42281">42281</a>
+"Resource *.java does not exist"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38931">38931</a>
+org.eclipse.jdt.internal.corext.dom.NodeFinder needed in API 
+
+
+<a name="v_370"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 16th September 2003
+<br>Project org.eclipse.jdt.core v_370 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_370">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43026">43026</a>
+Running jdt/core tests on Linux is failing
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43045">43045</a>
+Copy/move of package fragments with read-only subpackages fails on Linux
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43116">43116</a>
+NPE copy and pasting a method
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43089">43089</a>
+Search engine doesn't report all matches
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43080">43080</a>
+NPE when searching in CU with incomplete method declaration 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42856">42856</a>
+CodeAssist - Does not work after an inner type reference
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42839">42839</a>
+Incorrect position in org.eclipse.jdt.core.dom.ArrayType
+
+<a name="v_369"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 9th September 2003
+<br>Project org.eclipse.jdt.core v_369 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_369">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Default compiler compliance setting got raised to 1.4 level. Default source level is 1.3, and default target level is 1.2.
+To ease the 1.4 migration, the default severity for optional problem 'assert used as identifier' got raised to warning.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42760">42760</a>
+NullPointerException in JobManager when searching 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42629">42629</a>
+javac error message with missing classpath entry when claims entry dropped from path 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42614">42614</a>
+1.3 compliant mode should select default enclosing instance
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42588">42588</a>
+Incorrect selection of current enclosing instance
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35567">35567</a>
+Classpath validation error messages should contain project name
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42443">42443</a>
+Error when inner class name has the same name than another class, but with not the same case sensitive
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42459">42459</a>
+DebugEvaluationTests don't run if target is 1.2
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39887">39887</a>
+Resource exception while indexing
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42366">42366</a>
+Classpath validation error message removed while rebuilding a project.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41680">41680</a>
+Unnecessary cast  wrongly reported
+
+<a name="v_368"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 1st September 2003
+<br>Project org.eclipse.jdt.core v_368 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_368">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added optional compiler problem to signal unqualified access to a non-static field. In order to improve
+code readability, qualifying field accesses is a simple way to syntactically distinguish a field access from 
+a local variable access, and thus avoid resorting to a special naming convention for fields (such as "fField").
+<pre>
+* COMPILER / Reporting Unqualified Access to Field
+*    When enabled, the compiler will issue an error or a warning when a field is access without any qualification.
+*    In order to improve code readability, it should be qualified, e.g. 'x' should rather be written 'this.x'.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>
+</li>
+<li>Added optional compiler problem to signal method/constructor declared thrown checked exception which
+aren't actually raised inside the method/constructor body.
+<pre>
+* COMPILER / Reporting Unused Declared Thrown Exception
+*    When enabled, the compiler will issue an error or a warning when a method or a constructor is declaring a
+*    thrown checked exception, but never actually raises it in its body.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>
+</li>
+<li>Added optional compiler problem to flag situations where a finally block does not complete normally.
+<pre>
+* COMPILER / Reporting Finally Blocks Not Completing Normally
+*    When enabled, the compiler will issue an error or a warning when a finally block does not complete normally.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "warning"
+</pre>
+</li>
+<li>Improved problem description for unreachable catch block problems. Message will now mention the exception type 
+name and better diagnose the cause of the problem. Also changed problem source range 
+to rather highlight the caught exception type instead of entire catch block. 
+<pre></pre>
+</li>
+<li>Added two new API methods <code>readRawClasspath()</code> and <code>readOutputLocation()</code> on <code>IJavaProject</code>
+interface so as to allow user to read classpath directly from disk (<code>.classpath</code> file contents). This is useful to configure
+a Java project before it is associated with the Java nature, or before the automatic classpath reconciliation mechanism has performed (within
+a resource modifying operation, and prior to the change notification). Note that these API additions are obsoleting the previously
+added API <code>IJavaProject#forceClasspathReload(IProgressMonitor)</code> (also see bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20931">20931</a>)
+which has thus been deprecated. Forcing the classpath reload can simply be achieved by: <code>p.setRawClasspath(p.readRawClasspath(), p.readOutputLocation(), ...)</code>.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40383">40383</a>
+Search - should only special treat unsaved working copies 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40658">40658</a>
+IJavaProject.getOutputLocation/getRawClasspath require Java nature
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42196">42196</a>
+Method popup extremely slow for JOGL code 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41534">41534</a>
+incorrect shadowing reported by rename [refactoring] 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40937">40937</a>
+ISourceReference.getSource throws ArrayIndexOutOfBoundsException 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41373">41373</a>
+SourceField.getConstant() returns null for final fields set in initializer
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41604">41604</a>
+Possible Compiler Bug 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22976">22976</a>
+DCR - warning for unused declarations of thrown exceptions
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40736">40736</a>
+JDT compiler fails to compile legitimate Java code.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40020">40020</a>
+Exceptions in console 
+
+<a name="v_367"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M3 Build - 22nd August 2003 - 3.0 MILESTONE-3
+<br>Project org.eclipse.jdt.core v_367
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_367">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40464">40464</a>
+Index states not saved
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41805">41805</a>
+ArrayIndexOutOfBoundsException while creating AST
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39831">39831</a>
+Search finds only "inexact" matches 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35980">35980</a>
+illegal code completion suggested (abstract methods) 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40779">40779</a>
+Primary working copies: no deltas on destroy 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36271">36271</a>
+CodeAssist should treat array.clone() as visible
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40681">40681</a>
+no warnings for some externalized strings
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40584">40584</a>
+Test suite configuration should be more flexible
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41674">41674</a>
+ToolFactory.createDefaultClassFileReader does not close zipfile
+	  	
+<a name="v_366"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M3 Build - 19th August 2003
+<br>Project org.eclipse.jdt.core v_366 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_366">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>In 1.4 mode, the compiler is now JCK 1.4a compliant (previously was passing JCK1.4).
+</li>
+<li>To reduce the memory consumption and improve performance, the following new APIs were added:
+<ul>
+<li>AST.parsePartialCompilationUnit(ICompilationUnit unit, int position, boolean resolveBindings)</li>
+<li>AST.parsePartialCompilationUnit(ICompilationUnit unit, int position, boolean resolveBindings, WorkingCopyOwner owner)</li>
+</ul>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41602">41602</a>
+missing @exception in javadoc of IPackageFragment.getNonJavaResources 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38635">38635</a>
+Refactor / Rename Package doesn't allow rename to same name with different case [refactoring]
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40476">40476</a>
+refactor change method signature reports erroneous non-constant case statements
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40995">40995</a>
+NPE in ast.ExplicitConstructorCall.analyseCode
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40880">40880</a>
+Wrong error range for 'indirect static access'
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40174">40174</a>
+Performance issues with builder
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39108">39108</a>
+Numerous single type imports can slow compiler down significantly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41019">41019</a>
+org.eclipse.jdt.core.Signature cannot resolve complex type that has package name starting with letters as any primitive type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38633">38633</a>
+Search should not open requested types with match locator parser
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40954">40954</a>
+ArrayIndexOutOfBoundsException during sort members
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40804">40804</a>
+NPE in MethodBinding.sourceMethod()
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40474">40474</a>
+DOM/AST: Add API to parse only part of a compilation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40839">40839</a>
+Deprecation is reported even if there is an empty member declaration prior to the field declaration
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40606">40606</a>
+Unable to discard empty package if containing .class files 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39174">39174</a>
+NPE in type hierarchy when opening type 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40082">40082</a>
+NPE in TypeHierarchy.packageRegionContainsSamePackageFragment(TypeHierarchy.java:1314) 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40090">40090</a>
+No need to close Java model on shutdown 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42589">42589</a>
+jck1.4a failures
+
+<a name="v_365a"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M3 Build - 24th July 2003
+<br>Project org.eclipse.jdt.core v_365a 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_365a">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40752">40752</a>
+internal compiler error: java.lang.ClassCastException: org.eclipse.jdt.internal.compiler.lookup.ArrayBinding
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40594">40594</a>
+wrong location set for org.apache.ant when building jdt component with baseLocation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40715">40715</a>
+getWorkingCopy(...) should always return a new working copy for primary cus 
+
+<a name="v_365"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M3 Build - 22nd July 2003
+<br>Project org.eclipse.jdt.core v_365 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_365">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Added optional diagnosis for undocumented empty blocks
+<pre>
+* COMPILER / Reporting Undocumented Empty Block
+*    When enabled, the compiler will issue an error or a warning when an empty block is detected and it is not
+*    documented with any comment.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>
+</li>
+<li> Removed optional diagnosis for boolean methods throwing exception, since it proved to be useless as is.
+</li>
+<li>Fix for bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40116">40116</a>
+     requires the index format to be changed. Indexes will be automatically regenerated upon
+     subsequent search queries (accounting for indexing notification in search progress dialogs).
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40382">40382</a>
+JavaModelException#printStackTrace should be improved 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40572">40572</a>
+Unnecessary cast warning for necessary cast
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40322">40322</a>
+Error creating new Java projects 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40421">40421</a>
+Unnecessary cast warning...true but...
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32285">32285</a>
+DCR - extra java compiler markers
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40514">40514</a>
+ArrayIndexOutOfBoundsException during detection of unnecessary casts
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40442">40442</a>
+Abstract class fails to invoke interface-defined method in 1.4 compliance mode.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40116">40116</a>
+Search for references to nested class doesn't find anything 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40334">40334</a>
+Model should be more tolerant for possible compiler failures
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36479">36479</a>
+Rename operation during refactoring fails 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39865">39865</a>
+Misleading error diagnosis on broken method signatures
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=12800">12800</a>
+suboptimal error messages on mistyped 'throw/throws' keywords 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38568">38568</a>
+Search for method declarations fooled by array types 
+
+<a name="v_364b"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 18th July 2003 - 3.0 MILESTONE-2
+<br>Project org.eclipse.jdt.core v_364b 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_364b">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40495">40495</a>
+VerifyError with return statements containing a cast expression
+
+<a name="v_364a"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 17th July 2003
+<br>Project org.eclipse.jdt.core v_364a 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_364a">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40423">40423</a>
+NPE Saving a file
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40288">40288</a>
+NPE while building
+
+<a name="v_364"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 16th July 2003
+<br>Project org.eclipse.jdt.core v_364 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_364">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40210">40210</a>
+ICompilationUnit#isWorkingCopy() misbehaving for discarded working copies
+
+<a name="v_363"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 15th July 2003
+<br>Project org.eclipse.jdt.core v_363 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_363">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added flag <code>IJavaElementDelta.F_PRIMARY_WORKING_COPY</code> that signals that a compilation unit has become a
+     primary working copy, or that a primary working copy has reverted to a compilation unit (i.e. primary working copies are not notified
+     as being added/removed like other working copies, since the primary unit is only changing mode, also see bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40028">40028</a>).
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40028">40028</a>
+Deltas and deleted working copies 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39823">39823</a>
+AST: Would like to have binding of Serializable and Clonable
+	  	
+<a name="v_362"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 14th July 2003 
+<br>Project org.eclipse.jdt.core v_362
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_362">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Added optional diagnosis for unnecessary cast or instanceof operations (matching problem IDs are
+<code>IProblem.UnnecessaryCast</code>, <code>IProblem.UnnecessaryArgumentCast</code>, <code>IProblem.UnnecessaryInstanceof</code>).
+<pre>
+* COMPILER / Reporting Unnecessary Type Check
+*    When enabled, the compiler will issue an error or a warning when a cast or an instanceof operation 
+*    is unnecessary.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>	 
+</li>
+<li> Changed Java element delta processing to be thread-safe.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39926">39926</a>
+deleting default package (not in source folder) does nothing 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39877">39877</a>
+Rebuild All generates extra "Unable to read classpath" entry. 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39925">39925</a>
+Unnecessary instanceof checking leads to a NullPointerException
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35442">35442</a>
+flag unnecessary casts
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39841">39841</a>
+Give better explanation of why abstract class can't be instantiated
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39467">39467</a>
+Classes not implementing abstract methods compile without error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39763">39763</a>
+Non NLS string is reported and it should not
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39779">39779</a>
+End position of IType exceeds the size of CompilationUnit 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39766">39766</a>
+compilation unit cannot be saved 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39664">39664</a>
+setSuperInterfaces(String[] interfaceNames) API of org.eclipse.jdt.core.jdom.IDOMType interface does not work for an empty array parameter as Input
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39663">39663</a>
+setSuperclass(String superclassName) API of org.eclipse.jdt.core.jdom.IDOMType interface does not work for null as Input
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39736">39736</a>
+JavaModelException on copying read-only CompilationUnits 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39009">39009</a>
+NPE in Delta processor while executing JDT/UI tests 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35739">35739</a>
+Stack dump on console 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35632">35632</a>
+NPE in DeltaProcessor 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39281">39281</a>
+Unable Refacter (renaming) an inner class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38450">38450</a>
+Delete: Removing default package removes source folder 
+
+<a name="v_361"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 7th July 2003 
+<br>Project org.eclipse.jdt.core v_361
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_361">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Added optional compiler diagnosis for boolean method declaring thrown exceptions
+(matching problem ID is <code>IProblem.BooleanMethodThrowingException</code>)
+<pre>
+* COMPILER / Reporting Boolean Method Declaring Thrown Exceptions
+*    When enabled, the compiler will issue an error or a warning when a boolean method declaration 
+*    is specifying a clause for thrown exceptions. Some of them are predicates, and these should only 
+*    return a boolean value and not raise exceptions.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.booleanMethodThrowingException"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>
+<li> Added optional compiler diagnosis for indirect references to static members (matching problem IDs are:
+<code>IProblem.IndirectAccessToStaticField</code>, <code>IProblem.IndirectAccessToStaticMethod</code>, <code>IProblem.IndirectAccessToStaticType</code>).
+<pre>
+* COMPILER / Reporting Indirect Reference to a Static Member
+*    When enabled, the compiler will issue an error or a warning whenever a static field
+*    or method is accessed in an indirect way. A reference to a static member should
+*    preferably be qualified with its declaring type name.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.indirectStaticAccess"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>
+</li>
+<li> Removed method <code>Parser#grammar()</code>, which was hosting the Java grammar as a massive comment. 
+From now on, the grammar is defined in its own separate file: <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/grammar/java_1_4.g"><code>java_1_4.g</code></a>.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39624">39624</a>
+Should warn about predicate throwing exceptions
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39168">39168</a>
+Could remove JavaElement.fLEType field 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36989">36989</a>
+Incorrect error for "super must be first statement in constructor"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3319">3319</a>
+wrong compile-time error message (1GG1LDK)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39268">39268</a>
+Optional warning for indirect static references
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39533">39533</a>
+Working copy with no corresponding file not considered by NameLookup 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39502">39502</a>
+No completion in message send
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39475">39475</a>
+Extra error diagnosis in editor from siblings
+
+<a name="v_360"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 1st July 2003 
+<br>Project org.eclipse.jdt.core v_360
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_360">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Plugin version ID got incremented to 3.0.0. 
+</li>
+<li> Removed tolerance for relative source attachments in <code>JavaCore.newLibraryEntry(...)</code>. Only
+allowing relative empty pathes so as to permit using classpath variables to denote the absence of a source attachment.
+<li>To finish closing the gap between compilation units and working copies 
+(see <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36888">bug 36888</a>), new APIs were added to generalize
+the usage of a working copy owner (entire JavaModel is now aware of owned working copies). These new APIs are copies of existing APIs augmented with
+a <code>WorkingCopyOwner</code> parameter, that defines the working copies to consider in the operation. 
+When specifying an owner parameter, all working copies belonging to this owner will implicitly take precedence over primary ones
+(without requiring the owner to remember all its working copies, as in 2.1 era). Note that when no owned working copy is found, a primary
+unit will be considered instead, and since primary units have a built-in working copy (see <code>ICompilationUnit.becomeWorkingCopy(...)</code>),
+the primary unit may already be in working copy mode (very likely since an editor got opened on it). This means that an owner will already 
+transparently see unsaved editor contents for all units for which it has no better working copy to contribute.
+The following new APIs were added:
+	<ul>
+	<li><code>AST.parseCompilationUnit(char[] source, String unitName, IJavaProject project, WorkingCopyOwner owner)</code></li>
+	<li><code>AST.parseCompilationUnit(IClassFile classFile, boolean resolveBindings, WorkingCopyOwner owner)</code></li>
+	<li><code>AST.parseCompilationUnit(ICompilationUnit unit, boolean resolveBindings, WorkingCopyOwner owner)</code></li>
+	<li><code>IEvaluationContext.codeComplete(String codeSnippet, int position, ICompletionRequestor requestor, WorkingCopyOwner owner)</code></li>
+	<li><code>IEvaluationContext.codeSelect(String codeSnippet, int offset, int length, WorkingCopyOwner owner)</code></li>
+	<li><code>IDOMCompilationUnit.getCompilationUnit(IPackageFragment parent, WorkingCopyOwner owner)</code></li>
+	<li><code>ICodeAssist.codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner owner)</code></li>
+	<li><code>ICodeAssist.codeSelect(int offset, int length, WorkingCopyOwner owner)</code></li>
+	<li><code>ICompilationUnit.reconcile(boolean forceProblemDetection, WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+	<li><code>IJavaProject.findElement(IPath path, WorkingCopyOwner owner)</code></li>
+	<li><code>IJavaProject.findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner)</code></li>
+	<li><code>IJavaProject.findType(String fullyQualifiedName, WorkingCopyOwner owner)</code></li>
+	<li><code>IJavaProject.newTypeHierarchy(IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+	<li><code>IJavaProject.newTypeHierarchy(IType type, IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+	<li><code>IPackageFragment.getCompilationUnit(String name, WorkingCopyOwner owner)</code></li>
+	<li><code>IPackageFragment.getCompilationUnits(WorkingCopyOwner owner)</code></li>
+	<li><code>IType.codeComplete(char[] snippet, int insertion, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic, ICompletionRequestor requestor, WorkingCopyOwner owner)</code></li>
+	<li><code>IType.newSupertypeHierarchy(WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+	<li><code>IType.newTypeHierarchy(IJavaProject project, WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+	<li><code>IType.newTypeHierarchy(WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+	<li><code>IType.resolveType(String typeName, WorkingCopyOwner owner)</code></li>
+	<li><code>JavaCore.create(IFile file, WorkingCopyOwner owner)</code></li>
+	<li><code>JavaCore.create(IResource resource, WorkingCopyOwner owner)</code></li>
+	<li><code>JavaCore.create(String handleIdentifier, WorkingCopyOwner owner)</code></li>
+	<li><code>JavaCore.createCompilationUnitFrom(IFile file, WorkingCopyOwner owner)</code></li>
+	<li><code>JavaCore.getWorkingCopies(WorkingCopyOwner owner)</code></li>
+	<li><code>SearchEngine.SearchEngine(WorkingCopyOwner workingCopyOwner)</code></li>
+	<li><code>SearchEngine.createHierarchyScope(IType type, WorkingCopyOwner owner)</code></li>
+	</ul>
+</li>
+<li> Added optional problem to signal superfluous semicolons (matching problem ID is <code>IProblem.SuperfluousSemicolon</code>).
+<pre>
+* COMPILER / Reporting Superfluous Semicolon
+*    When enabled, the compiler will issue an error or a warning if a superfluous semicolon is met.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.superfluousSemicolon"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26281">26281</a>
+error hover text indicates wrong problem
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23166">23166</a>
+Syntax error message from Java compiler is confusing. 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33213">33213</a>
+Same error reported more than once? 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36214">36214</a>
+TODOs reported twice when located at the end of the method declaration 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36232">36232</a>
+binding do not fully consider working copies 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36888">36888</a>
+Close the gap between original and working copies 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39311">39311</a>
+Outliner did not refresh after method rename (refactor) 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39259">39259</a>
+While statement has wrong source position
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39007">39007</a>
+Infinite loop trying to index a non-existing external jar
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39172">39172</a>
+Incorrect error reported if extra semi-colon exists on a return statement
+
+
+<a name="v_359"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 23rd June 2003 
+<br>Project org.eclipse.jdt.core v_359
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_359">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added API on <code>ICompilationUnit</code> to get the primary compilation unit of a working copy 
+	 (it replaces <code>IWorkingCopy.getOriginalElement()</code>):
+<pre>
+/**
+ * Returns the primary compilation unit (whose owner is the primary owner)
+ * this working copy was created from, or this compilation unit if this a primary
+ * compilation unit.
+ * Note that the returned primary compilation unit can be in working copy mode.
+ * 
+ * @return the primary compilation unit this working copy was created from,
+ * or this compilation unit if it is primary
+ * @since 3.0
+ */
+ICompilationUnit getPrimary();
+</pre>
+</li>
+<li>Added API on <code>IJavaElement</code> to get the primary element of a working copy 
+	 element (it replaces <code>IWorkingCopy.getOriginalElement(IJavaElement)</code>):
+<pre>
+/**
+ * Returns the primary element (whose compilation unit is the primary compilation unit)
+ * this working copy element was created from, or this element if it is a descendant of a
+ * primary compilation unit or if it is not a descendant of a working copy (e.g. it is a
+ * binary member).
+ * The returned element may or may not exist.
+ * 
+ * @return the primary element this working copy element was created from, or this
+ * 	element.
+ * @since 3.0
+ */
+IJavaElement getPrimaryElement();
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38678">38678</a>
+workspace did not shutdown
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37006">37006</a>
+2 tasks in the tasks view instead of one
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38759">38759</a>
+Task Tags: should not consider text in substrings/parts of text
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36066">36066</a>
+Outliner did not refresh after field rename 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38951">38951</a>
+NPE in editor while saving contents 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35877">35877</a>
+Stack overflow in code assist
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35409">35409</a>
+RC2 Compiler produces bogus error messages
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38838">38838</a>
+SyntaxError- unoptimal syntax error message
+
+
+<a name="v_357b"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 18th June 2003 
+<br>Project org.eclipse.jdt.core v_357b
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_357b">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Backported index manager deadlock fix on top of v_357</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38901">38901</a>
+IndexManager hangs in end-less loop
+
+
+<a name="v_358"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 16th June 2003 
+<br>Project org.eclipse.jdt.core v_358
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_358">cvs</a>).
+
+<p><b>NOTE:</b> This version got backed out due to severe regression
+(see <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38951">38951</a> NPE in editor while saving contents).
+Until subsequent version is made available (see above), integration builds will revert to previous version (v_357).
+
+<h2>
+What's new in this drop</h2>
+<ul>
+<li><code>JavaCore.newLibraryEntry(...)</code> will now allow an empty source attachment (<code>new Path("")</code>) to
+be equivalent to no source attachment (i.e. <code>null</code>). This adjustment is made necessary for
+library entries generated from classpath variables which cannot be set to <code>null</code>. Also see 
+bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38531">38531</a>.
+<pre>
+* @param sourceAttachmentPath the absolute path of the corresponding source archive or folder, 
+*    or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
+*   and will be automatically converted to <code>null</code>.
+</pre>
+</li>
+<li>Added API <code>IJavaProject#forceClasspathReload(IProgressMonitor)</code> to force reload of <code>.classpath</code> file
+before next automatic update occurs.
+<pre>
+/**
+ * Force the project to reload its <code>.classpath</code> file from disk and update the classpath accordingly.
+ * Usually, a change to the <code>.classpath</code> file is automatically noticed and reconciled at the next 
+ * resource change notification event. If required to consider such a change prior to the next automatic
+ * refresh, then this functionnality should be used to trigger a refresh. In particular, if a change to the file is performed,
+ * during an operation where this change needs to be reflected before the operation ends, then an explicit refresh is
+ * necessary.
+ * 
+ * @param monitor a progress monitor for reporting operation progress
+ * @exception JavaModelException if the classpath could not be updated. Reasons
+ * include:
+ *  - This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ *  - Two or more entries specify source roots with the same or overlapping paths (NAME_COLLISION)
+ *  - A entry of kind <code>CPE_PROJECT</code> refers to this project (INVALID_PATH)
+ *  - This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ *  - The output location path refers to a location not contained in this project (<code>PATH_OUTSIDE_PROJECT</code>)
+ *  - The output location path is not an absolute path (<code>RELATIVE_PATH</code>)
+ *  - The output location path is nested inside a package fragment root of this project (<code>INVALID_PATH</code>)
+ *  - The classpath is being modified during resource change event notification (CORE_EXCEPTION)
+ * @since 3.0
+ */
+</pre>
+</li>
+<li>In the process of closing the gap between compilation units and working copies 
+(see <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36888 ">bug 36888 </a>), the following new APIs 
+are added to <code>ICompilationUnit</code>:
+	<ul>
+	<li><pre>
+/**
+ * Changes this compilation unit handle into a working copy. A new IBuffer is
+ * created using this compilation unit handle's owner. Uses the primary owner is none was
+ * specified when this compilation unit handle was created.
+ *
+ * When switching to working copy mode, problems are reported to given 
+ * IProblemRequestor.
+ *
+ * Once in working copy mode, changes to this compilation unit or its children are done in memory.
+ * Only the new buffer is affected. Using commitWorkingCopy(boolean, IProgressMonitor)
+ * will bring the underlying resource in sync with this compilation unit.
+ *
+ * If this compilation unit was already in working copy mode, an internal counter is incremented and no
+ * other action is taken on this compilation unit. To bring this compilation unit back into the original mode 
+ * (where it reflects the underlying resource), discardWorkingCopy must be call as many 
+ * times as becomeWorkingCopy.
+ * 
+ * @param problemRequestor a requestor which will get notified of problems detected during
+ * 	reconciling as they are discovered. The requestor can be set to null indicating
+ * 	that the client is not interested in problems.
+ * @param monitor a progress monitor used to report progress while opening this compilation unit
+ * 	or null if no progress should be reported 
+ * @exception JavaModelException if this compilation unit could not become a working copy.
+ * @see discardWorkingCopy
+ * @since 3.0
+ */
+void becomeWorkingCopy(IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException;	
+	</pre></li>
+	<li><pre>
+/**
+ * Commits the contents of this working copy to its underlying resource.
+ *
+ * It is possible that the contents of the original resource have changed
+ * since this working copy was created, in which case there is an update conflict.
+ * The value of the force parameter effects the resolution of
+ * such a conflict:
+ * - true - in this case the contents of this working copy are applied to
+ * 	the underlying resource even though this working copy was created 
+ * 	before a subsequent change in the resource
+ * - false - in this case a JavaModelException is thrown
+ * 
+ * Since 2.1, a working copy can be created on a not-yet existing compilation
+ * unit. In particular, such a working copy can then be committed in order to create
+ * the corresponding compilation unit.
+ * 
+ * @param force a flag to handle the cases when the contents of the original resource have changed
+ * since this working copy was created
+ * @param monitor the given progress monitor
+ * @exception JavaModelException if this working copy could not commit. Reasons include:
+ * - A CoreException occurred while updating an underlying resource
+ * - This element is not a working copy (INVALID_ELEMENT_TYPES)
+ * - A update conflict (described above) (UPDATE_CONFLICT)
+ * @since 3.0
+ */
+void commitWorkingCopy(boolean force, IProgressMonitor monitor) throws JavaModelException;	
+	</pre></li>
+	<li><pre>
+/**
+ * Changes this compilation unit in working copy mode back to its original mode.
+ *
+ * This has no effect if this compilation unit was not in working copy mode.
+ * 
+ * If becomeWorkingCopy was called several times on this
+ * compilation unit, discardWorkingCopy must be called as 
+ * many times before it switches back to the original mode.
+ * 
+ * @see becomeWorkingCopy
+ * @exception JavaModelException if this working copy could not return in its original mode.
+ * @since 3.0
+ */
+void discardWorkingCopy() throws JavaModelException;
+	</pre></li>
+	<li><pre>
+/**
+ * Returns the working copy owner of this working copy.
+ * Returns null if it is not a working copy or if it has no owner.
+ * 
+ * @return WorkingCopyOwner the owner of this working copy or null
+ * @since 3.0
+ */
+WorkingCopyOwner getOwner();
+	</pre></li>	
+	<li><pre>
+/**
+ * Returns a new working copy of this element if this element is not
+ * a working copy, or this element if this element is already a working copy.
+ * 
+ * Note: if intending to share a working copy amongst several clients, then 
+ * getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor) 
+ * should be used instead.
+ * 
+ * When the working copy instance is created, an ADDED IJavaElementDelta is 
+ * reported on this working copy.
+ * 
+ * Since 2.1, a working copy can be created on a not-yet existing compilation
+ * unit. In particular, such a working copy can then be committed in order to create
+ * the corresponding compilation unit.
+ * 
+* @param monitor a progress monitor used to report progress while opening this compilation unit
+ * 	or null if no progress should be reported 
+ * @exception JavaModelException if the contents of this element can
+ * 	not be determined. 
+ * @return a new working copy of this element if this element is not
+ * 	a working copy, or this element if this element is already a working copy
+ * @since 3.0
+ */
+ICompilationUnit getWorkingCopy(IProgressMonitor monitor) throws JavaModelException;
+	</pre></li>	
+	<li><pre>
+/**
+ * Returns a shared working copy on this element using the given working copy owner to create
+ * the buffer, or this element if this element is already a working copy.
+ * This API can only answer an already existing working copy if it is based on the same
+ * original compilation unit AND was using the same working copy owner (that is, as defined by Object.equals).	 
+ * 
+ * The life time of a shared working copy is as follows:
+ * - The first call to getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)
+ *   creates a new working copy for this element
+ * - Subsequent calls increment an internal counter.
+ * - A call to discardWorkingCopy() decrements the internal counter.
+ * - When this counter is 0, the working copy is discarded.
+ * 
+ * So users of this method must discard exactly once the working copy.
+ *
+ * Note that the working copy owner will be used for the life time of this working copy, that is if the 
+ * working copy is closed then reopened, this owner will be used.
+ * The buffer will be automatically initialized with the original's compilation unit content
+ * upon creation.
+ * 
+ * When the shared working copy instance is created, an ADDED IJavaElementDelta is reported on this
+ * working copy.
+ * 
+ * Since 2.1, a working copy can be created on a not-yet existing compilation
+ * unit. In particular, such a working copy can then be committed in order to create
+ * the corresponding compilation unit.
+ * 
+ * @param owner the working copy owner that creates a buffer that is used to get the content 
+ *  	of the working copy
+ * @param problemRequestor a requestor which will get notified of problems detected during
+ * 	reconciling as they are discovered. The requestor can be set to null indicating
+ * 	that the client is not interested in problems.
+ * @param monitor a progress monitor used to report progress while opening this compilation unit
+ * 	or null if no progress should be reported 
+ * @exception JavaModelException if the contents of this element can
+ *  	not be determined. 
+ * @return a new working copy of this element using the given factory to create
+ * the buffer, or this element if this element is already a working copy
+ * @since 3.0
+ */
+ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException;	
+	</pre></li>
+	</ul>
+And the following abstract class replaces <code>IBufferFactory</code>:
+	<pre>
+/**
+ * The owner of an ICompilationUnit handle in working copy mode. 
+ * An owner is used to identify a working copy and to create its buffer.
+ * 
+ * @see ICompilationUnit#becomeWorkingCopy
+ * @see ICompilationUnit#discardWorkingCopy
+ * @since 3.0
+ */
+public abstract class WorkingCopyOwner {
+	/**
+	 * Creates a buffer for the given working copy.
+	 * The new buffer will be initialized with the contents of the underlying file
+	 * if and only if it was not already initialized by the compilation owner (a buffer is 
+	 * uninitialized if its content is null).
+	 * 
+	 * @param workingCopy the working copy of the buffer
+	 * @return IBuffer the created buffer for the given working copy
+	 * @see IBuffer
+	 */
+	public IBuffer createBuffer(ICompilationUnit workingCopy) {
+		...
+	}
+}
+	</pre>
+	The intent for the primary owner is to use a buffer factory that would be
+	provided by the org.eclipse.text infractructure. This infrastructure not being
+	ready yet, in the meantime one can change the primary owner's 
+	<code>IBufferFactory</code> using the following internal API:
+	<pre>
+org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner.PRIMARY.factory = ...;
+	</pre>
+
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38901">38901</a>
+IndexManager hangs in end-less loop
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38908">38908</a>
+Ant script reports that the bootclasspath cannot be infer
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38531">38531</a>
+IllegalArgumentException "Source attachment path should be absolute"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38424">38424</a>
+Mistake on Web site
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38732">38732</a>
+organize imports does not work with assert in source code
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38447">38447</a>
+AST: Source ranges with missing bracket
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36854">36854</a>
+NPE opening type hierarchy 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33530">33530</a>
+JavaModel synchronization model should be more optimistic 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20931">20931</a>
+Need an API to reload the classpath from the file
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38393">38393</a>
+bytecode generated for evaluation with parentheses is wrong
+
+<a name="v_357"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M1 Build - 5th June 2003 - 3.0 MILESTONE-1
+<br>Project org.eclipse.jdt.core v_357
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_357">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37274">37274</a>
+Deadlock on plugin import
+
+
+<a name="v_356"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M1 Build - 4th June 2003
+<br>Project org.eclipse.jdt.core v_356
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_356">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38362">38362</a>
+Inconsistent output when using comparrisson operators
+
+
+<a name="v_355"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M1 Build - 3rd June 2003
+<br>Project org.eclipse.jdt.core v_355
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_355">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Fix for bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37111">37111</a> may issue some outgoing changes
+to .classpath file since the source attachment will be shortened into a project relative path when applicable. The .classpath file
+is still backward compatible, and will continue to accept non relative source attachments as well. </li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37111">37111</a>
+classpath file - java source attachment shouldn't hardcode project name
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38143">38143</a>
+this = null; should raise compile time error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38124">38124</a>
+Brackets around cast accepted by Eclipse but not javac
+
+
+<a name="v_354"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M1 Build - 26th May 2003
+<br>Project org.eclipse.jdt.core v_354
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_354">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added <code>JavaCore</code> optional problem to detect incompatible required binaries, so as to flag situations where
+some prerequisite binaries are required a JRE level higher than the project target platform; i.e. compiling against 1.4 libraries 
+when deploying for 1.1 platform is likely unwanted.
+<pre>
+* JAVACORE / Reporting Incompatible JDK Level for Required Binaries
+*    Indicate the severity of the problem reported when a project prerequisites another project 
+*    or library with an incompatible target JDK level (e.g. project targeting 1.1 vm, but compiled against 1.4 libraries).
+*     - option id:         "org.eclipse.jdt.core.incompatibleJDKLevel"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37750">37750</a>
+incorrect handle identifier for IImportContainer
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36674">36674</a>
+compiler can generate Java 1.4-only bytecode regardless of compatibility settings
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37962">37962</a>
+Unexpected transient problem during reconcile 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37166">37166</a>
+NPE in SearchEngine when matching type against ProblemReferenceBinding 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37438">37438</a>
+searchenging NPE in searchDeclarationsOfReferencedTypes 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37779">37779</a>
+ExceptionInInitializerError when using JDTCompilerAdapter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36307">36307</a>
+JDK1.4.2: Wrong declaring class for clone method on array class
+
+
+<a name="v_353"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M1 Build - 19th May 2003
+<br>Project org.eclipse.jdt.core v_353
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_353">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37621">37621</a>
+java compiler creates class with internal inconsistency
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37646">37646</a>
+Help for JDTCompilerAdapter is dated
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36894">36894</a>
+JobManager could wait when idle
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37541">37541</a>
+Unoptimal deprecation diagnosis
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37565">37565</a>
+JACKS: Class literal should not cause class initialization
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37503">37503</a>
+Compiler does not take care of exclusion filter
+
+
+<a name="v_352"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M1 Build - 13th May 2003
+<br>Project org.eclipse.jdt.core v_352
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_352">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Lowered default severity of field/local variable hiding optional diagnosis to <code>"ignore"</code>.
+</li>
+<li>Lowered default severity of accidental boolean assignment optional diagnosis to <code>"ignore"</code>.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37501">37501</a>
+VerifyError with assert when optimizing out unused local variables
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37387">37387</a>
+Compiler generates unnecessary byte codes
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37381">37381</a>
+AST: Wrong source ranges on VariableDeclExpression
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37200">37200</a>
+"Source->Generate Delegate Methods..." fails
+
+<a name="v_351"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M1 Build - 29th April 2003
+<br>Project org.eclipse.jdt.core v_351
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_351">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37040">37040</a>
+VerifyError "Illegal target of jump or branch"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36490">36490</a>
+Java compiler misses dependency on 'static final' class variables
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36814">36814</a>
+NaiveASTFlattener does not serialize try-finally statements correctly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36772">36772</a>
+AST: CompilationUnit.findDeclaringNode: Spec/Impl not same
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36711">36711</a>
+Resource duplication message should list location of duplicate
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36718">36718</a>
+Compiler should not generate references to classes not on the classpath
+
+<a name="v_350"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M1 Build - 22nd April 2003
+<br>Project org.eclipse.jdt.core v_350
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_350">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added new compiler optional problem to signal cases where a boolean variable is assigned
+in a condition expression. It is likely an accidental situation, where a comparison was actually meant.
+<pre>
+* COMPILER / Reporting Possible Accidental Boolean Assignment
+*    When enabled, the compiler will issue an error or a warning if a boolean assignment is acting as the condition
+*    of a control statement  (where it probably was meant to be a boolean comparison).
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "warning"
+</pre>
+</li>
+<li>Added new compiler settings to control the diagnosis of variable hiding other ones.
+<pre>
+* COMPILER / Reporting Local Variable Declaration Hiding another Variable
+*    When enabled, the compiler will issue an error or a warning whenever a local variable
+*    declaration is hiding some field or local variable (either locally, inherited or defined in enclosing type).
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.localVariableHiding"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "warning"
+*
+* COMPILER / Reporting Field Declaration Hiding another Variable
+*    When enabled, the compiler will issue an error or a warning whenever a field
+*    declaration is hiding some field or local variable (either locally, inherited or defined in enclosing type).
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.fieldHiding"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "warning"
+*
+* COMPILER / Reporting Special Parameter Hiding another Field
+*    When enabled, the compiler will signal cases where a constructor or setter method parameter declaration 
+*    is hiding some field (either locally, inherited or defined in enclosing type).
+*    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.localVariableHiding".
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.specialParameterHidingField"
+*     - possible values:   { "enabled", "disabled" }
+*     - default:           "disabled"
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36510">36510</a>
+Automatically attach source for source files located in a class folder 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36499">36499</a>
+exists() returns true for a source file inside a classfolder 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36438">36438</a>
+null == null causes java.lang.VerifyError
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35755">35755</a>
+Search in hierarchy misses dependent projects 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36465">36465</a>
+Unable to create multiple source folders when not using bin for output
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36339">36339</a>
+Try codegen issues slightly incorrect ANY exception handler
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35965">35965</a>
+Source not found in source attachment 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36447">36447</a>
+Unoptimal wide conditional branch bytecode sequence
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=19286">19286</a>
+Suspicious synchronized operations 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36213">36213</a>
+ArrayIndex out of bounds
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36244">36244</a>
+JDK1.4.2: Add -cp as a batch option 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35528">35528</a>
+When I check out a project from CVS, Updating takes a very long time
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36058">36058</a>
+Unknown NPE in log
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21661">21661</a>
+Compile dependency problems
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28937">28937</a>
+Compiler Problem Marker: Accidental Boolean Assignment
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33831">33831</a>
+ast API: add FieldAccess.resolveFieldBinding
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35649">35649</a>
+The SourceMapper instances could share the fileNamefilter 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34896">34896</a>
+compiler setting "unused private fields"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33751">33751</a>
+The numbering of anonymous could be optimized
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35849">35849</a>
+Incremental compilation ignores linked folders
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35926">35926</a>
+Batch compiler compile should return false when the command line is incorrect
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35421">35421</a>
+[nls] Inconsistencies between properties files and nls strings
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34173">34173</a>
+Create a compiler warning when an instance variable is "re-declared" as a local variable.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21140">21140</a>
+Warning/error on shadowing definition of data member?
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35490">35490</a>
+Search doesn't work for reference of 'cursorLocation'
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35338">35338</a>
+Cannot save file, "Save failed:null" error message received
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35438">35438</a>
+CastExpression resolution departs from JLS section 6.5.1
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36165">36165</a>
+[DOM/AST] Incorrect grammar rule in TypeDeclaration
+
+
+<a name="v_312"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 2.1 Build (before 3.0/2.1.1 branching) - 31st March 2003
+<br>Project org.eclipse.jdt.core v_312
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_312">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35831">35831</a>
+NPE navigating references using links
+
+<p><hr>
+For earlier build notes, also see <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.jdt.core/notes/R21_buildnotes_jdt-core.html">build notes up to Release 2.1</a>.
+
+<br>&nbsp;
+</body>
+</html>
diff --git a/org.eclipse.jdt.core/notes/porting_guide.html b/org.eclipse.jdt.core/notes/porting_guide.html
index cd27d06..4786a55 100644
--- a/org.eclipse.jdt.core/notes/porting_guide.html
+++ b/org.eclipse.jdt.core/notes/porting_guide.html
@@ -1,6 +1,8 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
 <html>
 
 <head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <title>JDT Core Porting Guide</title>
 <meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 <meta name="ProgId" content="FrontPage.Editor.Document">
@@ -9,7 +11,7 @@
 <body>
 
 <h1>JDT Core 3.0 Porting Guide</h1>
-<p>Last modified January 30, 2004</p>
+<p>Last modified January 30, 2004</p> 
 <p>These entries for the porting guide cover Debug-related items.</p>
 <h2>Required changes for 3.0</h2>
 <p>None.</p>
diff --git a/org.eclipse.jdt.core/plugin.xml b/org.eclipse.jdt.core/plugin.xml
index 9b7c1b5..7337604 100644
--- a/org.eclipse.jdt.core/plugin.xml
+++ b/org.eclipse.jdt.core/plugin.xml
@@ -6,7 +6,7 @@
 <plugin
     name = "%pluginName"
     id = "org.eclipse.jdt.core"
-    version = "3.0.0"
+    version = "3.1.0"
     provider-name = "%providerName"
     class="org.eclipse.jdt.core.JavaCore">
 
@@ -200,5 +200,13 @@
         file-names="MANIFEST.MF"
         default-charset="UTF-8"/>
 </extension>
+      
+<!-- =================================================================================== -->
+<!-- Extension: Eclipse preferences initializer                                          -->
+<!-- =================================================================================== -->
+<extension
+      point="org.eclipse.core.runtime.preferences">
+   <initializer class="org.eclipse.jdt.internal.core.JavaCorePreferenceInitializer"/>
+</extension>
 
 </plugin>
diff --git a/org.eclipse.jdt.core/schema/classpathContainerInitializer.exsd b/org.eclipse.jdt.core/schema/classpathContainerInitializer.exsd
index 96a64b0..f1e97e2 100644
--- a/org.eclipse.jdt.core/schema/classpathContainerInitializer.exsd
+++ b/org.eclipse.jdt.core/schema/classpathContainerInitializer.exsd
@@ -35,6 +35,9 @@
                <documentation>

                   an optional name of the extension instance

                </documentation>

+               <appInfo>

+                  <meta.attribute translatable="true"/>

+               </appInfo>

             </annotation>

          </attribute>

       </complexType>

@@ -114,5 +117,5 @@
 href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

       </documentation>

    </annotation>

-   

+

 </schema>

diff --git a/org.eclipse.jdt.core/schema/classpathVariableInitializer.exsd b/org.eclipse.jdt.core/schema/classpathVariableInitializer.exsd
index e803ebc..6f8e08e 100644
--- a/org.eclipse.jdt.core/schema/classpathVariableInitializer.exsd
+++ b/org.eclipse.jdt.core/schema/classpathVariableInitializer.exsd
@@ -2,14 +2,14 @@
 <!-- Schema file written by PDE -->

 <schema targetNamespace="org.eclipse.jdt.core">

 <annotation>

-   <appInfo>

-      <meta.schema plugin="org.eclipse.jdt.core" id="classpathVariableInitializer" name="Classpath Variable Initializers"/>

-   </appInfo>

-   <documentation>

-      This extension point allows clients to contribute custom classpath variable initializers, 

+      <appInfo>

+         <meta.schema plugin="org.eclipse.jdt.core" id="classpathVariableInitializer" name="Classpath Variable Initializers"/>

+      </appInfo>

+      <documentation>

+         This extension point allows clients to contribute custom classpath variable initializers, 

       which are used to lazily bind classpath variables.

-   </documentation>

-</annotation>

+      </documentation>

+   </annotation>

 

    <element name="extension">

       <complexType>

@@ -35,6 +35,9 @@
                <documentation>

                   an optional name of the extension instance

                </documentation>

+               <appInfo>

+                  <meta.attribute translatable="true"/>

+               </appInfo>

             </annotation>

          </attribute>

       </complexType>

@@ -74,11 +77,11 @@
          <meta.section type="examples"/>

       </appInfo>

       <documentation>

-         Example of a declaration of a &lt;code&gt;ClasspathVariableInitializer&lt;/code&gt; for a classpath variable named "FOO":  &lt;pre&gt;                                                                       

-&lt;extension point="org.eclipse.jdt.core.classpathVariableInitializer"&gt;            

+         Example of a declaration of a &lt;code&gt;ClasspathVariableInitializer&lt;/code&gt; for a classpath variable named &quot;FOO&quot;:  &lt;pre&gt;                                                                       

+&lt;extension point=&quot;org.eclipse.jdt.core.classpathVariableInitializer&quot;&gt;            

    &lt;classpathVariableInitializer                                          

-      variable="FOO"                                                        

-      class="com.example.CPVInitializer"/&gt;                           

+      variable=&quot;FOO&quot;                                                        

+      class=&quot;com.example.CPVInitializer&quot;/&gt;                           

 &lt;/extension&gt;

 &lt;/pre&gt;

       </documentation>

diff --git a/org.eclipse.jdt.core/schema/codeFormatter.exsd b/org.eclipse.jdt.core/schema/codeFormatter.exsd
index a14d9b6..b5aa9e8 100644
--- a/org.eclipse.jdt.core/schema/codeFormatter.exsd
+++ b/org.eclipse.jdt.core/schema/codeFormatter.exsd
@@ -1,109 +1,111 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!-- Schema file written by PDE -->
-<schema targetNamespace="org.eclipse.jdt.core">
-<annotation>
-   <appInfo>
-      <meta.schema plugin="org.eclipse.jdt.core" id="codeFormatter" name="Code Formatters"/>
-   </appInfo>
-   <documentation>
-      This extension point allows clients to contribute new source code formatter implementations.
-   </documentation>
-</annotation>
-
-   <element name="extension">
-      <complexType>
-         <sequence>
-            <element ref="codeFormatter" minOccurs="0" maxOccurs="unbounded"/>
-         </sequence>
-         <attribute name="point" type="string" use="required">
-            <annotation>
-               <documentation>
-                  a fully qualified identifier of the target extension point
-               </documentation>
-            </annotation>
-         </attribute>
-         <attribute name="id" type="string">
-            <annotation>
-               <documentation>
-                  an optional identifier of the extension instance
-               </documentation>
-            </annotation>
-         </attribute>
-         <attribute name="name" type="string">
-            <annotation>
-               <documentation>
-                  an optional name of the extension instance
-               </documentation>
-            </annotation>
-         </attribute>
-      </complexType>
-   </element>
-
-   <element name="codeFormatter">
-      <complexType>
-         <attribute name="class" type="string" use="required">
-            <annotation>
-               <documentation>
-                  the class that defines the code formatter implementation. This class must be a public implementation of &lt;code&gt;org.eclipse.jdt.core.ICodeFormatter&lt;/code&gt; with a public 0-argument constructor.
-               </documentation>
-            </annotation>
-         </attribute>
-      </complexType>
-   </element>
-
-   <annotation>
-      <appInfo>
-         <meta.section type="since"/>
-      </appInfo>
-      <documentation>
-         2.0
-      </documentation>
-   </annotation>
-
-   <annotation>
-      <appInfo>
-         <meta.section type="examples"/>
-      </appInfo>
-      <documentation>
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.jdt.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.jdt.core" id="codeFormatter" name="Code Formatters"/>

+      </appInfo>

+      <documentation>

+         This extension point allows clients to contribute new source code formatter implementations.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="codeFormatter" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+               <appInfo>

+                  <meta.attribute translatable="true"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="codeFormatter">

+      <complexType>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  the class that defines the code formatter implementation. This class must be a public implementation of &lt;code&gt;org.eclipse.jdt.core.ICodeFormatter&lt;/code&gt; with a public 0-argument constructor.

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="since"/>

+      </appInfo>

+      <documentation>

+         2.0

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

          Example of an implementation of &lt;code&gt;ICodeFormatter&lt;/code&gt;:  &lt;pre&gt;                                                                       
-&lt;extension point="org.eclipse.jdt.core.codeFormatter"&gt;            
+&lt;extension point=&quot;org.eclipse.jdt.core.codeFormatter&quot;&gt;            
    &lt;codeFormatter                                                                                              
-      class="com.example.MyCodeFormatter"/&gt;                           
+      class=&quot;com.example.MyCodeFormatter&quot;/&gt;                           
 &lt;/extension&gt;
-&lt;/pre&gt;
-      </documentation>
-   </annotation>
-
-   <annotation>
-      <appInfo>
-         <meta.section type="apiInfo"/>
-      </appInfo>
-      <documentation>
-         
-      </documentation>
-   </annotation>
-
-   <annotation>
-      <appInfo>
-         <meta.section type="implementation"/>
-      </appInfo>
-      <documentation>
-         
-      </documentation>
-   </annotation>
-
-   <annotation>
-      <appInfo>
-         <meta.section type="copyright"/>
-      </appInfo>
-      <documentation>
+&lt;/pre&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="implementation"/>

+      </appInfo>

+      <documentation>

+         

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

          Copyright (c) 2000, 2004 IBM Corporation and others.&lt;br&gt;
 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 &lt;a 
-href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;
-      </documentation>
-   </annotation>
-
-
-</schema>
+href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/org.eclipse.jdt.core/scripts/GenerateBuildScript.class b/org.eclipse.jdt.core/scripts/GenerateBuildScript.class
index 4e5222d..61cd251 100644
--- a/org.eclipse.jdt.core/scripts/GenerateBuildScript.class
+++ b/org.eclipse.jdt.core/scripts/GenerateBuildScript.class
Binary files differ
diff --git a/org.eclipse.jdt.core/scripts/GenerateBuildScript.java b/org.eclipse.jdt.core/scripts/GenerateBuildScript.java
new file mode 100644
index 0000000..187e56d
--- /dev/null
+++ b/org.eclipse.jdt.core/scripts/GenerateBuildScript.java
@@ -0,0 +1,94 @@
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+
+public class GenerateBuildScript {
+
+	private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+	private static final String HEADER=
+		"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + LINE_SEPARATOR +
+		"<project name=\"export-executable\" default=\"build_executable\">" +LINE_SEPARATOR +
+		"    <target name=\"build_executable\">" + LINE_SEPARATOR +
+		"        <echo message=\"compiling resources   -> .o\"/>" + LINE_SEPARATOR;
+		
+	private static final String FOOTER =
+		"	    <echo message=\"compiling sources      -> .o\"/>" + LINE_SEPARATOR +
+		"        <apply failonerror=\"true\" executable=\"${gcc-path}/bin/gcj.exe\" dest=\"${work}\" parallel=\"false\">" + LINE_SEPARATOR +
+		"  			 <arg value=\"--verbose\"/>" + LINE_SEPARATOR +
+		"            <arg value=\"--classpath=${work}\"/>" + LINE_SEPARATOR +
+		"            <arg value=\"-O2\"/>" + LINE_SEPARATOR +
+		"            <arg value=\"-c\"/>" + LINE_SEPARATOR +
+		"            <arg value=\"-fassume-compiled\"/>" + LINE_SEPARATOR +
+		"            <arg value=\"-march=pentium4\"/>" + LINE_SEPARATOR +
+		"            <arg value=\"-mfpmath=sse\"/>" + LINE_SEPARATOR +
+		"            <srcfile/>" + LINE_SEPARATOR +
+		"            <arg value=\"-o\"/>" + LINE_SEPARATOR +
+		"            <targetfile/>" + LINE_SEPARATOR +
+		"            <fileset dir=\"${work}\" includes=\"**/*.java\"/>" + LINE_SEPARATOR +
+		"            <mapper type=\"glob\" from=\"*.java\" to=\"*.o\"/>" + LINE_SEPARATOR +
+		"        </apply>" + LINE_SEPARATOR + LINE_SEPARATOR +
+		"        <echo message=\"linking .o -> ${binaryname}\"/>" + LINE_SEPARATOR +
+		"        <apply failonerror=\"true\" executable=\"${gcc-path}/bin/gcj.exe\" parallel=\"true\">" + LINE_SEPARATOR +
+		"        	<arg value=\"--verbose\"/>" + LINE_SEPARATOR +
+		"            <arg line =\"-o ${dest}${binaryname}.exe\"/>" + LINE_SEPARATOR +
+		"            <arg value=\"-fassume-compiled\"/>" + LINE_SEPARATOR +
+		"            <arg value=\"-march=pentium4\"/>" + LINE_SEPARATOR +
+		"            <arg value=\"-mfpmath=sse\"/>" + LINE_SEPARATOR +
+		"            <arg line=\"--main=org.eclipse.jdt.internal.compiler.batch.Main\"/>" + LINE_SEPARATOR +
+		"            <fileset dir=\"${work}\" includes=\"**/*.o\"/>" + LINE_SEPARATOR +
+		"       </apply>" + LINE_SEPARATOR +
+		"    </target>" + LINE_SEPARATOR +
+		"</project>" + LINE_SEPARATOR;
+
+	private static void collectAllPropertiesFiles(File root, ArrayList collector) {
+		File[] files = root.listFiles();
+		for (int i = 0; i < files.length; i++) {
+			if (files[i].isDirectory()) {
+				collectAllPropertiesFiles(files[i], collector);
+			} else if (files[i].getName().endsWith(".rsc") || files[i].getName().endsWith(".properties")) { //$NON-NLS-1$
+				String newElement = files[i].getAbsolutePath();
+				newElement = newElement.replace('\\', '/');
+				collector.add(newElement);
+			}
+		}
+	}
+
+	private static void dumpAllProperties(Writer writer, File sourceDir, ArrayList collector) throws IOException {
+		for (int i = 0, max = collector.size(); i < max; i++) {
+			String absolutePath = (String) collector.get(i);
+			String fileName = absolutePath.substring(sourceDir.getAbsolutePath().length() + 1); 
+			writer.write("  		<exec dir=\"${work}\" executable=\"${gcc-path}/bin/gcj.exe\">" + LINE_SEPARATOR);
+			writer.write("  		  <arg line=\"--resource ");
+			writer.write(fileName + " " + fileName + " -c -o " + getObjectName(fileName) + "\"/>" + LINE_SEPARATOR);
+			writer.write("  		</exec>" + LINE_SEPARATOR);
+		}
+	}
+
+	private static String getObjectName(String fileName) {
+		return fileName.substring(0, fileName.lastIndexOf('.')) + ".o";
+	}
+			
+	public static void main(String[] args) {
+		if (args.length != 2) {
+			return;
+		}
+		try {
+			BufferedWriter writer = new BufferedWriter(new FileWriter(new File(args[0])));
+			writer.write(HEADER);
+			File sourceDir = new File(args[1]);
+			if (sourceDir.exists()) { 
+				ArrayList collector = new ArrayList();
+				collectAllPropertiesFiles(sourceDir, collector);
+				dumpAllProperties(writer, sourceDir, collector);
+			}
+			writer.write(FOOTER);
+			writer.flush();
+			writer.close();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+}
diff --git a/org.eclipse.jdt.core/scripts/build.xml b/org.eclipse.jdt.core/scripts/build.xml
new file mode 100644
index 0000000..cd38f4e
--- /dev/null
+++ b/org.eclipse.jdt.core/scripts/build.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="export-executable" default="build" basedir=".">
+
+	<property name="version" value="3.1.0" />
+	<property name="gcc-path" value="C:/java_tools/thisiscool-gcc/gcc-4.0" />
+	<property name="binaryname" value="ejavac${version}" />
+	<property name="dest" value="c:/temp/bingcj" />
+	<property name="extract_folder" value="${dest}/src/" />
+	<property name="work" value="${dest}/tmp/" />
+	<property name="source" value="C:/eclipse/I1111/eclipse/plugins/org.eclipse.jdt.source_3.1.0/src/org.eclipse.jdt.core_3.1.0/jdtcoresrc.zip" />
+	<property name="binaries" value="C:/eclipse/I1111/eclipse/plugins/org.eclipse.jdt.core_3.1.0/jdtcore.jar" />
+	<property name="gcj_script_name" value="export-executable.xml" />
+
+	<target name="build">
+		<echo message="target: ${dest}" />
+		<delete dir="${dest}" failonerror="no" />
+		<mkdir dir="${dest}" />
+
+		<unzip overwrite="yes" dest="${work}" src="${source}">
+			<patternset>
+				<include name="**/compiler/**" />
+				<exclude name="**/compiler/**/*.html" />
+				<exclude name="**/IScanner.java" />
+				<exclude name="**/ITerminalSymbols.java" />
+				<exclude name="**/DocumentElementParser.java" />
+				<exclude name="**/IDocumentElementRequestor.java" />
+				<exclude name="**/ISourceElementRequestor.java" />
+				<exclude name="**/SourceElementParser.java" />
+				<exclude name="**/SourceElementRequestorAdapter.java" />
+				<exclude name="**/SourceConstructorDeclaration.java" />
+				<exclude name="**/SourceFieldDeclaration.java" />
+				<exclude name="**/SourceMethodDeclaration.java" />
+				<exclude name="**/SourceTypeConverter.java" />
+			</patternset>
+		</unzip>
+
+		<unzip overwrite="yes" dest="${work}" src="${binaries}">
+			<patternset>
+				<include name="**/compiler/**/*.properties" />
+				<include name="**/*.rsc" />
+				<exclude name="**/*.class" />
+				<exclude name="**/*.mf" />
+			</patternset>
+		</unzip>
+
+		<!-- echo message="generate build script" />
+		<java classname="GenerateBuildScript">
+			<sysproperty key="user.dir" value="${basedir}/scripts"/>
+			<arg value="${gcj_script_name}"/>
+			<arg value="${basedir}/${work}"/>
+			<classpath>
+				<pathelement path="${basedir}/scripts"/>
+			</classpath>
+		</java>
+		
+		<echo message="run the new build script" />
+		<ant antfile="${basedir}/scripts/export-executable.xml"/>
+		<delete file="${basedir}/scripts/export-executable.xml"/ -->
+	</target>
+</project>
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/scripts/export-ejavac.xml b/org.eclipse.jdt.core/scripts/export-ejavac.xml
index 96faf31..a04444f 100644
--- a/org.eclipse.jdt.core/scripts/export-ejavac.xml
+++ b/org.eclipse.jdt.core/scripts/export-ejavac.xml
@@ -1,29 +1,24 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project name="export-executable" default="build" basedir="..">
 
-	<property name="gcc-path" value="d:/gcc/gcc-3.4" />
-	<property name="binaryname" value="ejavac" />
+	<property name="version" value="310" />
+	<property name="gcc-path" value="C:/java_tools/thisiscool-gcc/gcc-4.0" />
+	<property name="binaryname" value="ejavac${version}" />
 	<property name="dest" value="../../bingcj/" />
 	<property name="work" value="${dest}tmp/" />
+	<property name="source" value="C:/eclipse/workspaces/head/org.eclipse.jdt.core" />
 	<property name="gcj_script_name" value="export-executable.xml"/>
 
     <target name="build">
-
 		<echo message="target: ${dest}" />
-		<mkdir dir="${dest}" />
-		<delete dir="${dest}" />
+		<delete dir="${dest}" failonerror="no"/>
 		<mkdir dir="${dest}" />
 	
 		<copy todir="${work}">
-		    <fileset dir="batch/" excludes='**/*.html' />
+		    <fileset dir="${source}/batch/" excludes='**/*.html' />
 		</copy>
-		
 		<copy todir="${work}">
-		    <fileset dir="../GcjHelper/" includes='**/*.java' />
-		</copy>
-		
-		<copy todir="${work}">
-		    <fileset dir="compiler/" excludes='**/*.html' />
+		    <fileset dir="${source}/compiler/" excludes='**/*.html' />
 		</copy>
 	
 		<echo message="generate build script" />
diff --git a/org.eclipse.jdt.core/scripts/exportplugin.xml b/org.eclipse.jdt.core/scripts/exportplugin.xml
index 67612f9..69af5f3 100644
--- a/org.eclipse.jdt.core/scripts/exportplugin.xml
+++ b/org.eclipse.jdt.core/scripts/exportplugin.xml
@@ -1,8 +1,13 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!-- build script to create a plugin from ${plugin} -->
-<project name="${plugin}" default="export plug-in [_3.0.0]" basedir="..">
+<project name="${plugin}" default="export plug-in [_3.1.0]" basedir="..">
 
+<target name="export plug-in [_3.1.0]">
+	<antcall target="zz_internal_export">
+		<param name="jdt_core_version" value="3.1.0"/>
+	</antcall>
+</target>
 
 <target name="export plug-in [_3.0.0]">
 	<antcall target="zz_internal_export">
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java
index 9897d79..4a45a72 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java
@@ -68,6 +68,18 @@
 	 */
 	int INTERFACE= 6;
 
+	/**
+	 * The searched element is an enum.
+	 * More selective than using TYPE
+	 */
+	int ENUM= 7;
+
+	/**
+	 * The searched element is an annotation type.
+	 * More selective than using TYPE
+	 */
+	int ANNOTATION_TYPE= 8;
+
 	/* Nature of match */
 	
 	/**
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/MethodReferenceMatch.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/MethodReferenceMatch.java
index 9a58c28..f6a9b2a 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/MethodReferenceMatch.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/MethodReferenceMatch.java
@@ -23,6 +23,8 @@
  * @since 3.0
  */
 public class MethodReferenceMatch extends SearchMatch {
+	private boolean constructor;
+	private boolean synthetic;
 
 	/**
 	 * Creates a new method reference match.
@@ -40,4 +42,49 @@
 		super(enclosingElement, accuracy, offset, length, participant, resource);
 		setInsideDocComment(insideDocComment);
 	}
+
+	/**
+	 * Creates a new method reference match.
+	 * 
+	 * @param enclosingElement the inner-most enclosing member that references this method
+	 * @param accuracy one of {@link #A_ACCURATE} or {@link #A_INACCURATE}
+	 * @param offset the offset the match starts at, or -1 if unknown
+	 * @param length the length of the match, or -1 if unknown
+	 * @param constructor <code>true</code> if this search match a constructor
+	 * <code>false</code> otherwise
+	 * @param synthetic <code>true</code> if this search match a synthetic element
+	 * <code>false</code> otherwise
+	 * @param insideDocComment <code>true</code> if this search match is inside a doc
+	 * comment, and <code>false</code> otherwise
+	 * @param participant the search participant that created the match
+	 * @param resource the resource of the element
+	 * @since 3.1
+	 */
+	public MethodReferenceMatch(IJavaElement enclosingElement, int accuracy, int offset, int length, boolean constructor, boolean synthetic, boolean insideDocComment, SearchParticipant participant, IResource resource) {
+		this(enclosingElement, accuracy, offset, length, insideDocComment, participant, resource);
+		this.constructor = constructor;
+		this.synthetic = synthetic;
+	}
+
+	/**
+	 * Returns whether the reference is on a constructor.
+	 *
+	 * @return Returns whether the reference is on a constructor or not.
+	 * @since 3.1
+	 */
+	public final boolean isConstructor() {
+		return this.constructor;
+	}
+	
+	/**
+	 * Returns whether the reference is on a synthetic element.
+	 * Note that this field is only used for constructor reference. This happens when default constructor
+	 * declaration is used or implicit super constructor is called.
+	 * 
+	 * @return whether the reference is synthetic or not.
+	 * @since 3.1
+	 */
+	public final boolean isSynthetic() {
+		return this.synthetic;
+	}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchEngine.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchEngine.java
index 7426d74..2ca000d 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchEngine.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchEngine.java
@@ -10,25 +10,12 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.search;
 
-import java.util.*;
-
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.*;
 
 import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.parser.Parser;
-import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
-import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
-import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.search.*;
-import org.eclipse.jdt.internal.core.search.indexing.*;
 import org.eclipse.jdt.internal.core.search.matching.*;
-import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * A <code>SearchEngine</code> searches for Java elements following a search pattern.
@@ -92,34 +79,14 @@
 		}
 	}
 		
-	/*
-	 * A default parser to parse non-reconciled working copies
-	 */
-	private Parser parser;
-	private CompilerOptions compilerOptions;
-		
-	/*
-	 * A list of working copies that take precedence over their original 
-	 * compilation units.
-	 */
-	private ICompilationUnit[] workingCopies;
-	
-	/*
-	 * A working copy owner whose working copies will take precedent over 
-	 * their original compilation units.
-	 */
-	private WorkingCopyOwner workingCopyOwner;
-	
-	/**
-	 * For tracing purpose.
-	 */	
-	public static boolean VERBOSE = false;	
+	// Search engine now uses basic engine functionalities
+	private SearchBasicEngine basicEngine;
 	
 	/**
 	 * Creates a new search engine.
 	 */
 	public SearchEngine() {
-		// will use working copies of PRIMARY owner
+		this.basicEngine = new SearchBasicEngine();
 	}
 	
 	/**
@@ -135,7 +102,7 @@
 	 * @since 3.0
 	 */
 	public SearchEngine(ICompilationUnit[] workingCopies) {
-		this.workingCopies = workingCopies;
+		this.basicEngine = new SearchBasicEngine(workingCopies);
 	}
 	/**
 	 * Creates a new search engine with a list of working copies that will take precedence over 
@@ -152,7 +119,9 @@
 	 */
 	public SearchEngine(IWorkingCopy[] workingCopies) {
 		int length = workingCopies.length;
-		System.arraycopy(workingCopies, 0, this.workingCopies = new ICompilationUnit[length], 0, length);
+		ICompilationUnit[] units = new ICompilationUnit[length];
+		System.arraycopy(workingCopies, 0, units, 0, length);
+		this.basicEngine = new SearchBasicEngine(units);
 	}
 	
 	/**
@@ -164,9 +133,9 @@
 	 * @since 3.0
 	 */
 	public SearchEngine(WorkingCopyOwner workingCopyOwner) {
-		this.workingCopyOwner = workingCopyOwner;
+		this.basicEngine = new SearchBasicEngine(workingCopyOwner);
 	}
-	
+
 	/**
 	 * Returns a Java search scope limited to the hierarchy of the given type.
 	 * The Java elements resulting from a search with this scope will
@@ -177,7 +146,7 @@
 	 * @exception JavaModelException if the hierarchy could not be computed on the given type
 	 */
 	public static IJavaSearchScope createHierarchyScope(IType type) throws JavaModelException {
-		return createHierarchyScope(type, DefaultWorkingCopyOwner.PRIMARY);
+		return SearchBasicEngine.createHierarchyScope(type);
 	}
 	
 	/**
@@ -194,7 +163,7 @@
 	 * @since 3.0
 	 */
 	public static IJavaSearchScope createHierarchyScope(IType type, WorkingCopyOwner owner) throws JavaModelException {
-		return new HierarchyScope(type, owner);
+		return SearchBasicEngine.createHierarchyScope(type, owner);
 	}
 
 	/**
@@ -240,7 +209,7 @@
 	 * @since 2.0
 	 */
 	public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements) {
-		return createJavaSearchScope(elements, true);
+		return SearchBasicEngine.createJavaSearchScope(elements);
 	}
 
 	/**
@@ -264,11 +233,7 @@
 	 * @since 2.0
 	 */
 	public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements, boolean includeReferencedProjects) {
-		int includeMask = IJavaSearchScope.SOURCES | IJavaSearchScope.APPLICATION_LIBRARIES | IJavaSearchScope.SYSTEM_LIBRARIES;
-		if (includeReferencedProjects) {
-			includeMask |= IJavaSearchScope.REFERENCED_PROJECTS;
-		}
-		return createJavaSearchScope(elements, includeMask);
+		return SearchBasicEngine.createJavaSearchScope(elements, includeReferencedProjects);
 	}
 
 	/**
@@ -303,23 +268,7 @@
 	 * @since 3.0
 	 */
 	public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements, int includeMask) {
-		JavaSearchScope scope = new JavaSearchScope();
-		HashSet visitedProjects = new HashSet(2);
-		for (int i = 0, length = elements.length; i < length; i++) {
-			IJavaElement element = elements[i];
-			if (element != null) {
-				try {
-					if (element instanceof JavaProject) {
-						scope.add((JavaProject)element, includeMask, visitedProjects);
-					} else {
-						scope.add(element);
-					}
-				} catch (JavaModelException e) {
-					// ignore
-				}
-			}
-		}
-		return scope;
+		return SearchBasicEngine.createJavaSearchScope(elements, includeMask);
 	}
 	
 	/**
@@ -413,69 +362,14 @@
 	public static ISearchPattern createSearchPattern(IJavaElement element, int limitTo) {
 		return new SearchPatternAdapter(SearchPattern.createPattern(element, limitTo));
 	}
-	
+
 	/**
 	 * Returns a Java search scope with the workspace as the only limit.
 	 *
 	 * @return a new workspace scope
 	 */
 	public static IJavaSearchScope createWorkspaceScope() {
-		return new JavaWorkspaceScope();
-	}
-	
-	/**
-	 * Searches for matches to a given query. Search queries can be created using helper
-	 * methods (from a String pattern or a Java element) and encapsulate the description of what is
-	 * being searched (for example, search method declarations in a case sensitive way).
-	 *
-	 * @param scope the search result has to be limited to the given scope
-	 * @param requestor a callback object to which each match is reported
-	 */
-	private 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 */
-		if (monitor != null)
-			monitor.beginTask(Util.bind("engine.searching"), 100); //$NON-NLS-1$
-		if (SearchEngine.VERBOSE)
-			System.out.println("Searching for " + this + " in " + scope); //$NON-NLS-1$//$NON-NLS-2$
-	
-		IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
-		try {
-			requestor.beginReporting();
-			for (int i = 0, l = participants == null ? 0 : participants.length; i < l; i++) {
-				if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
-	
-				SearchParticipant participant = participants[i];
-				try {
-					participant.beginSearching();
-					requestor.enterParticipant(participant);
-					PathCollector pathCollector = new PathCollector();
-					indexManager.performConcurrentJob(
-						new PatternSearchJob(pattern, participant, scope, pathCollector),
-						IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
-						monitor);
-					if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
-	
-					// locate index matches if any (note that all search matches could have been issued during index querying)
-					String[] indexMatchPaths = pathCollector.getPaths();
-					pathCollector = null; // release
-					int indexMatchLength = indexMatchPaths == null ? 0 : indexMatchPaths.length;
-					SearchDocument[] indexMatches = new SearchDocument[indexMatchLength];
-					for (int j = 0; j < indexMatchLength; j++)
-						indexMatches[j] = participant.getDocument(indexMatchPaths[j]);
-					SearchDocument[] matches = MatchLocator.addWorkingCopies(pattern, indexMatches, getWorkingCopies(), participant);
-					participant.locateMatches(matches, pattern, scope, requestor, monitor);
-				} finally {		
-					requestor.exitParticipant(participant);
-					participant.doneSearching();
-				}
-			}
-		} finally {
-			requestor.endReporting();
-			if (monitor != null)
-				monitor.done();
-		}
+		return SearchBasicEngine.createWorkspaceScope();
 	}
 	/**
 	 * Returns a new default Java search participant.
@@ -484,148 +378,9 @@
 	 * @since 3.0
 	 */
 	public static SearchParticipant getDefaultSearchParticipant() {
-		return new JavaSearchParticipant();
+		return SearchBasicEngine.getDefaultSearchParticipant();
 	}
 
-	private Parser getParser() {
-		if (this.parser == null) {
-			this.compilerOptions = new CompilerOptions(JavaCore.getOptions());
-			ProblemReporter problemReporter =
-				new ProblemReporter(
-					DefaultErrorHandlingPolicies.proceedWithAllProblems(),
-					this.compilerOptions,
-					new DefaultProblemFactory());
-			this.parser = new Parser(problemReporter, true);
-		}
-		return this.parser;
-	}
-	
-	/**
-	 * Returns the underlying resource of the given element.
-	 * @param element an IJavaElement
-	 * @return an IResource
-	 */
-	private IResource getResource(IJavaElement element) {
-		if (element instanceof IMember) {
-			ICompilationUnit cu = ((IMember)element).getCompilationUnit();
-			if (cu != null) {
-				return cu.getResource();
-			} 
-		} 
-		return element.getResource();
-	}
-	
-	/*
-	 * Returns the list of working copies used by this search engine.
-	 * Returns null if none.
-	 */
-	private ICompilationUnit[] getWorkingCopies() {
-		ICompilationUnit[] copies;
-		if (this.workingCopies != null) {
-			if (this.workingCopyOwner == null) {
-				copies = JavaModelManager.getJavaModelManager().getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, false/*don't add primary WCs a second time*/);
-				if (copies == null) {
-					copies = this.workingCopies;
-				} else {
-					HashMap pathToCUs = new HashMap();
-					for (int i = 0, length = copies.length; i < length; i++) {
-						ICompilationUnit unit = copies[i];
-						pathToCUs.put(unit.getPath(), unit);
-					}
-					for (int i = 0, length = this.workingCopies.length; i < length; i++) {
-						ICompilationUnit unit = this.workingCopies[i];
-						pathToCUs.put(unit.getPath(), unit);
-					}
-					int length = pathToCUs.size();
-					copies = new ICompilationUnit[length];
-					pathToCUs.values().toArray(copies);
-				}
-			} else {
-				copies = this.workingCopies;
-			}
-		} else if (this.workingCopyOwner != null) {
-			copies = JavaModelManager.getJavaModelManager().getWorkingCopies(this.workingCopyOwner, true/*add primary WCs*/);
-		} else {
-			copies = JavaModelManager.getJavaModelManager().getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, false/*don't add primary WCs a second time*/);
-		}
-		if (copies == null) return null;
-		
-		// filter out primary working copies that are saved
-		ICompilationUnit[] result = null;
-		int length = copies.length;
-		int index = 0;
-		for (int i = 0; i < length; i++) {
-			CompilationUnit copy = (CompilationUnit)copies[i];
-			try {
-				if (!copy.isPrimary()
-						|| copy.hasUnsavedChanges()
-						|| copy.hasResourceChanged()) {
-					if (result == null) {
-						result = new ICompilationUnit[length];
-					}
-					result[index++] = copy;
-				}
-			}  catch (JavaModelException e) {
-				// copy doesn't exist: ignore
-			}
-		}
-		if (index != length && result != null) {
-			System.arraycopy(result, 0, result = new ICompilationUnit[index], 0, index);
-		}
-		return result;
-	}
-	
-	/**
-	 * Returns the list of working copies used to do the search on the given Java element.
-	 * @param element an IJavaElement
-	 * @return an array of ICompilationUnit
-	 */
-	private ICompilationUnit[] getWorkingCopies(IJavaElement element) {
-		if (element instanceof IMember) {
-			ICompilationUnit cu = ((IMember)element).getCompilationUnit();
-			if (cu != null && cu.isWorkingCopy()) {
-				ICompilationUnit[] copies = getWorkingCopies();
-				int length = copies == null ? 0 : copies.length;
-				if (length > 0) {
-					ICompilationUnit[] newWorkingCopies = new ICompilationUnit[length+1];
-					System.arraycopy(copies, 0, newWorkingCopies, 0, length);
-					newWorkingCopies[length] = cu;
-					return newWorkingCopies;
-				} 
-				return new ICompilationUnit[] {cu};
-			}
-		}
-		return getWorkingCopies();
-	}
-
-	boolean match(char classOrInterface, char[] patternPkg, char[] patternTypeName, int matchRule, boolean isClass, char[] pkg, char[] typeName) {
-		switch(classOrInterface) {
-			case IIndexConstants.CLASS_SUFFIX :
-				if (!isClass) return false;
-			case IIndexConstants.INTERFACE_SUFFIX :
-				if (isClass) return false;
-			case IIndexConstants.TYPE_SUFFIX : // nothing
-		}
-	
-		boolean isCaseSensitive = (matchRule & SearchPattern.R_CASE_SENSITIVE) != 0;
-		if (patternPkg != null && !CharOperation.equals(patternPkg, pkg, isCaseSensitive))
-				return false;
-		
-		if (patternTypeName != null) {
-			int matchMode = matchRule - (isCaseSensitive ? SearchPattern.R_CASE_SENSITIVE : 0);
-			switch(matchMode) {
-				case SearchPattern.R_EXACT_MATCH :
-					return CharOperation.equals(patternTypeName, typeName, isCaseSensitive);
-				case SearchPattern.R_PREFIX_MATCH :
-					return CharOperation.prefixEquals(patternTypeName, typeName, isCaseSensitive);
-				case SearchPattern.R_PATTERN_MATCH :
-					return CharOperation.match(patternTypeName, typeName, isCaseSensitive);
-			}
-		}
-		return true;
-	
-	}	
-
 	/**
 	 * Searches for the Java element determined by the given signature. The signature
 	 * can be incomplete. For example, a call like 
@@ -754,7 +509,7 @@
 	 *@since 3.0
 	 */
 	public void search(SearchPattern pattern, SearchParticipant[] participants, IJavaSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException {
-		findMatches(pattern, participants, scope, requestor, monitor);
+		this.basicEngine.search(pattern, participants, scope, requestor, monitor);
 	}
 
 	/**
@@ -811,164 +566,11 @@
 		final ITypeNameRequestor nameRequestor,
 		int waitingPolicy,
 		IProgressMonitor progressMonitor)  throws JavaModelException {
-	
-		IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
-			
-		final char classOrInterface;
-		switch(searchFor){
-			case IJavaSearchConstants.CLASS :
-				classOrInterface = IIndexConstants.CLASS_SUFFIX;
-				break;
-			case IJavaSearchConstants.INTERFACE :
-				classOrInterface = IIndexConstants.INTERFACE_SUFFIX;
-				break;
-			default : 
-				classOrInterface = IIndexConstants.TYPE_SUFFIX;
-				break;
-		}
-		final TypeDeclarationPattern pattern = new TypeDeclarationPattern(
-			packageName,
-			null, // do find member types
-			typeName,
-			classOrInterface,
-			matchRule);
 		
-		final HashSet workingCopyPaths = new HashSet();
-		ICompilationUnit[] copies = getWorkingCopies();
-		if (copies != null) {
-			for (int i = 0, length = copies.length; i < length; i++) {
-				ICompilationUnit workingCopy = copies[i];
-				workingCopyPaths.add(workingCopy.getPath().toString());
-			}
-		}
-	
-		IndexQueryRequestor searchRequestor = new IndexQueryRequestor(){
-			public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant) {
-				TypeDeclarationPattern record = (TypeDeclarationPattern)indexRecord;
-				if (record.enclosingTypeNames != IIndexConstants.ONE_ZERO_CHAR  // filter out local and anonymous classes
-						&& !workingCopyPaths.contains(documentPath)) { // filter out working copies
-					boolean isClass = record.classOrInterface != IIndexConstants.INTERFACE_SUFFIX;
-					if (isClass) {
-						nameRequestor.acceptClass(record.pkg, record.simpleName, record.enclosingTypeNames, documentPath);
-					} else {
-						nameRequestor.acceptInterface(record.pkg, record.simpleName, record.enclosingTypeNames, documentPath);
-					}
-				}
-				return true;
-			}
-		};
-	
-		try {
-			if (progressMonitor != null) {
-				progressMonitor.beginTask(Util.bind("engine.searching"), 100); //$NON-NLS-1$
-			}
-			// add type names from indexes
-			indexManager.performConcurrentJob(
-				new PatternSearchJob(
-					pattern, 
-					getDefaultSearchParticipant(), // Java search only
-					scope, 
-					searchRequestor),
-				waitingPolicy,
-				progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100));	
-				
-			// add type names from working copies
-			if (copies != null) {
-				for (int i = 0, length = copies.length; i < length; i++) {
-					ICompilationUnit workingCopy = copies[i];
-					final String path = workingCopy.getPath().toString();
-					if (workingCopy.isConsistent()) {
-						IPackageDeclaration[] packageDeclarations = workingCopy.getPackageDeclarations();
-						char[] packageDeclaration = packageDeclarations.length == 0 ? CharOperation.NO_CHAR : packageDeclarations[0].getElementName().toCharArray();
-						IType[] allTypes = workingCopy.getAllTypes();
-						for (int j = 0, allTypesLength = allTypes.length; j < allTypesLength; j++) {
-							IType type = allTypes[j];
-							IJavaElement parent = type.getParent();
-							char[][] enclosingTypeNames;
-							if (parent instanceof IType) {
-								char[] parentQualifiedName = ((IType)parent).getTypeQualifiedName('.').toCharArray();
-								enclosingTypeNames = CharOperation.splitOn('.', parentQualifiedName);
-							} else {
-								enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
-							}
-							char[] simpleName = type.getElementName().toCharArray();
-							if (match(classOrInterface, packageName, typeName, matchRule, type.isClass(), packageDeclaration, simpleName)) {
-								if (type.isClass()) {
-									nameRequestor.acceptClass(packageDeclaration, simpleName, enclosingTypeNames, path);
-								} else {
-									nameRequestor.acceptInterface(packageDeclaration, simpleName, enclosingTypeNames, path);
-								}
-							}
-						}
-					} else {
-						Parser basicParser = getParser();
-						final char[] contents = workingCopy.getBuffer().getCharacters();
-						org.eclipse.jdt.internal.compiler.env.ICompilationUnit unit = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit() {
-							public char[] getContents() {
-								return contents;
-							}
-							public char[] getMainTypeName() {
-								return null;
-							}
-							public char[][] getPackageName() {
-								return null;
-							}
-							public char[] getFileName() {
-								return null;
-							}
-						};
-						CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.compilerOptions.maxProblemsPerUnit);
-						CompilationUnitDeclaration parsedUnit = basicParser.dietParse(unit, compilationUnitResult);
-						if (parsedUnit != null) {
-							final char[] packageDeclaration = parsedUnit.currentPackage == null ? CharOperation.NO_CHAR : CharOperation.concatWith(parsedUnit.currentPackage.getImportName(), '.');
-							class AllTypeDeclarationsVisitor extends ASTVisitor {
-								public boolean visit(TypeDeclaration typeDeclaration, BlockScope blockScope) {
-									return false; // no local/anonymous type
-								}
-								public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope compilationUnitScope) {
-									if (match(classOrInterface, packageName, typeName, matchRule, !typeDeclaration.isInterface(), packageDeclaration, typeDeclaration.name)) {
-										if (!typeDeclaration.isInterface()) {
-											nameRequestor.acceptClass(packageDeclaration, typeDeclaration.name, CharOperation.NO_CHAR_CHAR, path);
-										} else {
-											nameRequestor.acceptInterface(packageDeclaration, typeDeclaration.name, CharOperation.NO_CHAR_CHAR, path);
-										}
-									}
-									return true;
-								}
-								public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope classScope) {
-									if (match(classOrInterface, packageName, typeName, matchRule, !memberTypeDeclaration.isInterface(), packageDeclaration, memberTypeDeclaration.name)) {
-										// compute encloising type names
-										TypeDeclaration enclosing = memberTypeDeclaration.enclosingType;
-										char[][] enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
-										while (enclosing != null) {
-											enclosingTypeNames = CharOperation.arrayConcat(new char[][] {enclosing.name}, enclosingTypeNames);
-											if ((enclosing.bits & ASTNode.IsMemberTypeMASK) != 0) {
-												enclosing = enclosing.enclosingType;
-											} else {
-												enclosing = null;
-											}
-										}
-										// report
-										if (!memberTypeDeclaration.isInterface()) {
-											nameRequestor.acceptClass(packageDeclaration, memberTypeDeclaration.name, enclosingTypeNames, path);
-										} else {
-											nameRequestor.acceptInterface(packageDeclaration, memberTypeDeclaration.name, enclosingTypeNames, path);
-										}
-									}
-									return true;
-								}
-							}
-							parsedUnit.traverse(new AllTypeDeclarationsVisitor(), parsedUnit.scope);
-						}
-					}
-				}
-			}	
-		} finally {
-			if (progressMonitor != null) {
-				progressMonitor.done();
-			}
-		}
+		TypeNameRequestorWrapper requestorWrapper = new TypeNameRequestorWrapper(nameRequestor);
+		this.basicEngine.searchAllTypeNames(packageName, typeName, matchRule, searchFor, scope, requestorWrapper, waitingPolicy, progressMonitor);
 	}
+
 	/**
 	 * 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
@@ -1035,48 +637,6 @@
 			waitingPolicy, 
 			progressMonitor);
 	}	
-	
-	/**
-	 * @deprecated mark deprecated as it uses deprecated code
-	 */
-	private void searchDeclarations(IJavaElement enclosingElement, IJavaSearchResultCollector resultCollector, SearchPattern pattern) throws JavaModelException {
-		searchDeclarations(enclosingElement, new ResultCollectorAdapter(resultCollector), pattern, resultCollector.getProgressMonitor());
-	}
-	
-	private void searchDeclarations(IJavaElement enclosingElement, SearchRequestor requestor, SearchPattern pattern, IProgressMonitor monitor) throws JavaModelException {
-		IJavaSearchScope scope = createJavaSearchScope(new IJavaElement[] {enclosingElement});
-		IResource resource = this.getResource(enclosingElement);
-		try {
-			if (resource instanceof IFile) {
-				if (VERBOSE) {
-					System.out.println("Searching for " + pattern + " in " + resource.getFullPath()); //$NON-NLS-1$//$NON-NLS-2$
-				}
-				SearchParticipant participant = getDefaultSearchParticipant();
-				SearchDocument[] documents = MatchLocator.addWorkingCopies(
-					pattern,
-					new SearchDocument[] {new JavaSearchDocument(enclosingElement.getPath().toString(), participant)},
-					getWorkingCopies(enclosingElement),
-					participant);
-				participant.locateMatches(
-					documents, 
-					pattern, 
-					scope, 
-					requestor, 
-					monitor);
-			} else {
-				search(
-					pattern, 
-					new SearchParticipant[] {getDefaultSearchParticipant()}, 
-					scope, 
-					requestor, 
-					monitor);
-			}
-		} catch (CoreException e) {
-			if (e instanceof JavaModelException)
-				throw (JavaModelException) e;
-			throw new JavaModelException(e);
-		}
-	}
 
 	/**
 	 * Searches for all declarations of the fields accessed in the given element.
@@ -1116,8 +676,7 @@
 	 * @since 3.0
 	 */	
 	public void searchDeclarationsOfAccessedFields(IJavaElement enclosingElement, SearchRequestor requestor, IProgressMonitor monitor) throws JavaModelException {
-		SearchPattern pattern = new DeclarationOfAccessedFieldsPattern(enclosingElement);
-		searchDeclarations(enclosingElement, requestor, pattern, monitor);
+		this.basicEngine.searchDeclarationsOfAccessedFields(enclosingElement, requestor, monitor);
 	}
 	
 	/**
@@ -1159,7 +718,7 @@
 	 */	
 	public void searchDeclarationsOfAccessedFields(IWorkspace workspace, IJavaElement enclosingElement, IJavaSearchResultCollector resultCollector) throws JavaModelException {
 		SearchPattern pattern = new DeclarationOfAccessedFieldsPattern(enclosingElement);
-		searchDeclarations(enclosingElement, resultCollector, pattern);
+		this.basicEngine.searchDeclarations(enclosingElement, new ResultCollectorAdapter(resultCollector), pattern, resultCollector.getProgressMonitor());
 	}
 	
 	/**
@@ -1200,8 +759,7 @@
 	 * @since 3.0
 	 */	
 	public void searchDeclarationsOfReferencedTypes(IJavaElement enclosingElement, SearchRequestor requestor, IProgressMonitor monitor) throws JavaModelException {
-		SearchPattern pattern = new DeclarationOfReferencedTypesPattern(enclosingElement);
-		searchDeclarations(enclosingElement, requestor, pattern, monitor);
+		this.basicEngine.searchDeclarationsOfReferencedTypes(enclosingElement, requestor, monitor);
 	}
 	
 	/**
@@ -1243,7 +801,7 @@
 	 */	
 	public void searchDeclarationsOfReferencedTypes(IWorkspace workspace, IJavaElement enclosingElement, IJavaSearchResultCollector resultCollector) throws JavaModelException {
 		SearchPattern pattern = new DeclarationOfReferencedTypesPattern(enclosingElement);
-		searchDeclarations(enclosingElement, resultCollector, pattern);
+		this.basicEngine.searchDeclarations(enclosingElement, new ResultCollectorAdapter(resultCollector), pattern, resultCollector.getProgressMonitor());
 	}
 	
 	/**
@@ -1287,8 +845,7 @@
 	 * @since 3.0
 	 */	
 	public void searchDeclarationsOfSentMessages(IJavaElement enclosingElement, SearchRequestor requestor, IProgressMonitor monitor) throws JavaModelException {
-		SearchPattern pattern = new DeclarationOfReferencedMethodsPattern(enclosingElement);
-		searchDeclarations(enclosingElement, requestor, pattern, monitor);
+		this.basicEngine.searchDeclarationsOfSentMessages(enclosingElement, requestor, monitor);
 	}
 
 	/**
@@ -1333,6 +890,6 @@
 	 */	
 	public void searchDeclarationsOfSentMessages(IWorkspace workspace, IJavaElement enclosingElement, IJavaSearchResultCollector resultCollector) throws JavaModelException {
 		SearchPattern pattern = new DeclarationOfReferencedMethodsPattern(enclosingElement);
-		searchDeclarations(enclosingElement, resultCollector, pattern);
+		this.basicEngine.searchDeclarations(enclosingElement, new ResultCollectorAdapter(resultCollector), pattern, resultCollector.getProgressMonitor());
 	}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchMatch.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchMatch.java
index a7a5c27..40e93ae 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchMatch.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchMatch.java
@@ -21,7 +21,6 @@
  * merely potential matches (<code>A_INACCURATE</code>). The latter occurs when
  * a compile-time problem prevents the search engine from completely resolving
  * the match.
- * </p>
  * <p>
  * This class is intended to be instantiated and subclassed by clients.
  * </p>
@@ -33,6 +32,8 @@
 	
 	/**
 	 * The search result corresponds an exact match of the search pattern.
+	 * 
+	 * @see #getAccuracy()
 	 */
 	public static final int A_ACCURATE = 0;
 
@@ -40,6 +41,8 @@
 	 * The search result is potentially a match for the search pattern,
 	 * but the search engine is unable to fully check it (for example, because
 	 * there are errors in the code or the classpath are not correctly set).
+	 * 
+	 * @see #getAccuracy()
 	 */
 	public static final int A_INACCURATE = 1;
 	
@@ -52,6 +55,9 @@
 	private IResource resource;
 
 	private boolean insideDocComment = false;
+	
+	// store the rule used while reporting the match
+	private int matchRule = SearchPattern.R_EXACT_MATCH;
 
 	/**
 	 * Creates a new search match.
@@ -139,6 +145,21 @@
 	}
 
 	/**
+	 * Returns the rule used while creating the match.
+	 * 
+	 * @return the rule of the match. Legal values are combination of following
+	 * {@link SearchPattern} constants:
+	 * <ul>
+	 * 	<li>{@link SearchPattern#R_ERASURE_MATCH}</li>
+	 * 	<li>{@link SearchPattern#R_EQUIVALENT_MATCH}</li>
+	 * </ul>
+	 * @since 3.1
+	 */
+	public final int getMatchRule() {
+		return this.matchRule;
+	}
+
+	/**
 	 * Returns whether this search match is inside a doc comment of a Java
 	 * source file.
 	 * 
@@ -168,6 +189,18 @@
 	public final void setElement (Object element) {
 		this.element = element;
 	}
+
+	/**
+	 * Sets whether this search match is inside a doc comment of a Java
+	 * source file.
+	 * 
+	 * @param insideDoc <code>true</code> if this search match is inside a doc
+	 * comment, and <code>false</code> otherwise
+	 */
+	public final void setInsideDocComment (boolean insideDoc) {
+		this.insideDocComment = insideDoc;
+	}
+
 	/**
 	 * Sets the length of this search match.
 	 * 
@@ -205,14 +238,18 @@
 	}
 
 	/**
-	 * Sets whether this search match is inside a doc comment of a Java
-	 * source file.
+	 * Returns the rule used while creating the match.
 	 * 
-	 * @param insideDoc <code>true</code> if this search match is inside a doc
-	 * comment, and <code>false</code> otherwise
+	 * @param rule the rule to set. Legal values are combination of following
+	 * {@link SearchPattern} constants:
+	 * <ul>
+	 * 	<li>{@link SearchPattern#R_ERASURE_MATCH}</li>
+	 * 	<li>{@link SearchPattern#R_EQUIVALENT_MATCH}</li>
+	 * </ul>
+	 * @since 3.1
 	 */
-	public final void setInsideDocComment (boolean insideDoc) {
-		this.insideDocComment = insideDoc;
+	public final void setMatchRule(int rule) {
+		this.matchRule = rule;
 	}
 
 	/* (non-javadoc)
@@ -223,6 +260,16 @@
 		buffer.append("Search match"); //$NON-NLS-1$
 		buffer.append("\n  accuracy="); //$NON-NLS-1$
 		buffer.append(this.accuracy == A_ACCURATE ? "ACCURATE" : "INACCURATE"); //$NON-NLS-1$ //$NON-NLS-2$
+		buffer.append("\n  rule="); //$NON-NLS-1$
+		if ((this.matchRule & SearchPattern.R_EQUIVALENT_MATCH) != 0) {
+			buffer.append("EQUIVALENT"); //$NON-NLS-1$
+			if ((this.matchRule & SearchPattern.R_ERASURE_MATCH) != 0)
+				buffer.append("+ERASURE"); //$NON-NLS-1$
+		} else if ((this.matchRule & SearchPattern.R_ERASURE_MATCH) != 0) {
+			buffer.append("ERASURE"); //$NON-NLS-1$
+		} else {
+			buffer.append("EXACT"); //$NON-NLS-1$
+		}
 		buffer.append("\n  offset="); //$NON-NLS-1$
 		buffer.append(this.offset);
 		buffer.append("\n  length="); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java
index 34e607c..37a1bd9 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java
@@ -16,6 +16,7 @@
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
 import org.eclipse.jdt.internal.core.LocalVariable;
+import org.eclipse.jdt.internal.core.ParameterizedSourceType;
 import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
 import org.eclipse.jdt.internal.core.search.matching.*;
 
@@ -67,7 +68,64 @@
 	 * Can be combined to previous rules, e.g. R_EXACT_MATCH | R_CASE_SENSITIVE
 	 */
 	public static final int R_CASE_SENSITIVE = 8;
-	
+	/**
+	 * Match rule: The search pattern matches search results as raw/parameterized types/methods with same erasure.
+	 * This mode has no effect on other java elements search.
+	 * Type search example:
+	 * 	<ul>
+	 * 	<li>pattern: <code>List&lt;Exception&gt;</code></li>
+	 * 	<li>match: <code>List&lt;Object&gt;</code></li>
+	 * 	</ul>
+	 * Method search example:
+	 * 	TODO (frederic) This mode is not implemented yet. It will be completed in next milestone.
+	 * 	<ul>
+	 * 	<li>declaration: <code>&lt;T&gt;foo(T t)</code></li>
+	 * 	<li>pattern: <code>&lt;Exception&gt;foo(new Exception())</code></li>
+	 * 	<li>match: <code>&lt;Object&gt;foo(new Object())</code></li>
+	 * 	</ul>
+	 * Can be combined to all other match rules, e.g. {@link #R_CASE_SENSITIVE} | {@link #R_ERASURE_MATCH}
+	 * This rule is not activated by default, so raw types or parameterized types with same erasure will not be found
+	 * for pattern List&lt;String&gt;,
+	 * Note that with this pattern, the match selection will be only on the erasure even for parameterized types.
+	 * @since 3.1
+	 */
+	public static final int R_ERASURE_MATCH = 16;
+	/**
+	 * Match rule: The search pattern matches search results as raw/parameterized types/methods with equivalent type parameters.
+	 * This mode has no effect on other java elements search.
+	 * Type search example:
+	 * <ul>
+	 * 	<li>pattern: <code>List&lt;Exception&gt;</code></li>
+	 * 	<li>match:
+	 * 		<ul>
+	 * 		<li><code>List&lt;? extends Throwable&gt;</code></li>
+	 * 		<li><code>List&lt;? super RuntimeException&gt;</code></li>
+	 * 		<li><code>List&lt;?&gt;</code></li>
+	 *			</ul>
+	 * 	</li>
+	 * 	</ul>
+	 * Method search example:
+	 * 	TODO (frederic) This mode is not implemented yet. It will be completed in next milestone.
+	 * 	<ul>
+	 * 	<li>declaration: <code>&lt;T&gt;foo(T t)</code></li>
+	 * 	<li>pattern: <code>&lt;Exception&gt;foo(new Exception())</code></li>
+	 * 	<li>match:
+	 * 		<ul>
+	 * 		<li><code>&lt;? extends Throwable&gt;foo(new Exception())</code></li>
+	 * 		<li><code>&lt;? super RuntimeException&gt;foo(new Exception())</code></li>
+	 * 		<li><code>foo(new Exception())</code></li>
+	 *			</ul>
+	 * 	</ul>
+	 * Can be combined to all other match rules, e.g. {@link #R_CASE_SENSITIVE} | {@link #R_EQUIVALENT_MATCH}
+	 * This rule is not activated by default, so raw types or equivalent parameterized types will not be found
+	 * for pattern List&lt;String&gt;,
+	 * This mode is overridden by {@link  #R_ERASURE_MATCH} as erasure matches obviously include equivalent ones.
+	 * That means that pattern with rule set to {@link #R_EQUIVALENT_MATCH} | {@link  #R_ERASURE_MATCH}
+	 * will return same results than rule only set with {@link  #R_ERASURE_MATCH}.
+	 * @since 3.1
+	 */
+	public static final int R_EQUIVALENT_MATCH = 32;
+
 	private int matchRule;
 
 	/**
@@ -78,6 +136,8 @@
 	 * @param matchRule one of R_EXACT_MATCH, R_PREFIX_MATCH, R_PATTERN_MATCH, R_REGEXP_MATCH combined with R_CASE_SENSITIVE,
 	 *   e.g. R_EXACT_MATCH | R_CASE_SENSITIVE if an exact and case sensitive match is requested, 
 	 *   or R_PREFIX_MATCH if a prefix non case sensitive match is requested.
+	 * [TODO (frederic) Expand spec for matchRule to allow R_ERASURE_MATCH ?
+     * If yes, we have a problem because getMatchRule() locks in set of existing values.]
 	 */
 	public SearchPattern(int matchRule) {
 		this.matchRule = matchRule;
@@ -226,6 +286,7 @@
 					declaringQualificationChars, 
 					parameterTypeQualifications, 
 					parameterTypeSimpleNames,
+					false,
 					matchRule);
 			case IJavaSearchConstants.REFERENCES :
 				return new ConstructorPattern(
@@ -235,6 +296,7 @@
 					declaringQualificationChars, 
 					parameterTypeQualifications, 
 					parameterTypeSimpleNames,
+					false,
 					matchRule);
 			case IJavaSearchConstants.ALL_OCCURRENCES :
 				return new ConstructorPattern(
@@ -244,12 +306,13 @@
 					declaringQualificationChars, 
 					parameterTypeQualifications, 
 					parameterTypeSimpleNames,
+					false,
 					matchRule);
 		}
 		return null;
 	}
 	/**
-	 * Field pattern are formed by [declaringType.]name[type]
+	 * Field pattern are formed by [declaringType.]name[ type]
 	 * e.g. java.lang.String.serialVersionUID long
 	 *		field*
 	 */
@@ -420,7 +483,7 @@
 		return null;
 	}
 	/**
-	 * Method pattern are formed by [declaringType.]selector[(parameterTypes)][returnType]
+	 * Method pattern are formed by [declaringType.]selector[(parameterTypes)][ returnType]
 	 * e.g. java.lang.Runnable.run() void
 	 *		main(*)
 	 */
@@ -609,6 +672,7 @@
 					returnTypeSimpleName, 
 					parameterTypeQualifications, 
 					parameterTypeSimpleNames,
+					false,
 					null,
 					matchRule);
 			case IJavaSearchConstants.REFERENCES :
@@ -622,6 +686,7 @@
 					returnTypeSimpleName, 
 					parameterTypeQualifications, 
 					parameterTypeSimpleNames,
+					false,
 					null,
 					matchRule);
 			case IJavaSearchConstants.ALL_OCCURRENCES :
@@ -635,6 +700,7 @@
 					returnTypeSimpleName, 
 					parameterTypeQualifications, 
 					parameterTypeSimpleNames,
+					false,
 					null,
 					matchRule);
 		}
@@ -709,6 +775,7 @@
 	 *   e.g. R_EXACT_MATCH | R_CASE_SENSITIVE if an exact and case sensitive match is requested, 
 	 *   or R_PREFIX_MATCH if a prefix non case sensitive match is requested.
 	 * @return a search pattern on the given string pattern, or <code>null</code> if the string pattern is ill-formed
+	 * [TODO (frederic) Expand spec for matchRule to allow R_ERASURE_MATCH ?]
 	 */
 	public static SearchPattern createPattern(String stringPattern, int searchFor, int limitTo, int matchRule) {
 		if (stringPattern == null || stringPattern.length() == 0) return null;
@@ -727,6 +794,7 @@
 		}
 		return null;
 	}
+
 	/**
 	 * Returns a search pattern based on a given Java element. 
 	 * The pattern is used to trigger the appropriate search, and can be parameterized as follows:
@@ -748,6 +816,35 @@
 	 * @return a search pattern for a Java element or <code>null</code> if the given element is ill-formed
 	 */
 	public static SearchPattern createPattern(IJavaElement element, int limitTo) {
+		return createPattern(element, limitTo, R_EXACT_MATCH | R_CASE_SENSITIVE);
+	}
+
+	/**
+	 * Returns a search pattern based on a given Java element. 
+	 * The pattern is used to trigger the appropriate search, and can be parameterized as follows:
+	 *
+	 * @param element the Java element the search pattern is based on
+	 * @param limitTo determines the nature of the expected matches
+	 * 	<ul>
+	 * 		<li><code>IJavaSearchConstants.DECLARATIONS</code>: will search declarations matching with the corresponding
+	 * 			element. In case the element is a method, declarations of matching methods in subtypes will also
+	 *  		be found, allowing to find declarations of abstract methods, etc.</li>
+	 *
+	 *		 <li><code>IJavaSearchConstants.REFERENCES</code>: will search references to the given element.</li>
+	 *
+	 *		 <li><code>IJavaSearchConstants.ALL_OCCURRENCES</code>: will search for either declarations or references as specified
+	 *  		above.</li>
+	 *
+	 *		 <li><code>IJavaSearchConstants.IMPLEMENTORS</code>: for interface, will find all types which implements a given interface.</li>
+	 *	</ul>
+	 * @param matchRule Same possible values than those described in method {@link #createPattern(String,int,int,int)} plus another possible
+	 * 	new value {@link #R_ERASURE_MATCH} which can be combined with the others. When match rule includes {@link #R_ERASURE_MATCH},
+	 * 	the search engine finds all types whose erasures match the given pattern erasure.
+	 * 	By default, the search engine only finds exact or compatible matches for generic or parameterized types.
+	 * @return a search pattern for a Java element or <code>null</code> if the given element is ill-formed
+	 * @since 3.1
+	 */
+	public static SearchPattern createPattern(IJavaElement element, int limitTo, int matchRule) {
 		SearchPattern searchPattern = null;
 		int lastDot;
 		switch (element.getElementType()) {
@@ -762,17 +859,25 @@
 				char[] name = field.getElementName().toCharArray();
 				char[] typeSimpleName;
 				char[] typeQualification;
+				String typeSignature;
 				try {
-					String typeSignature = Signature.toString(field.getTypeSignature()).replace('$', '.');
-					if ((lastDot = typeSignature.lastIndexOf('.')) == -1) {
-						typeSimpleName = typeSignature.toCharArray();
+					typeSignature = field.getTypeSignature();
+					char[] signature = typeSignature.toCharArray();
+					char[] typeErasure = Signature.toCharArray(Signature.getTypeErasure(signature));
+					if (CharOperation.indexOf(Signature.C_GENERIC_START, signature) < 0) {
+						typeSignature = null;
+					}
+					CharOperation.replace(typeErasure, '$', '.');
+					if ((lastDot = CharOperation.lastIndexOf('.', typeErasure)) == -1) {
+						typeSimpleName = typeErasure;
 						typeQualification = null;
 					} else {
-						typeSimpleName = typeSignature.substring(lastDot + 1).toCharArray();
-						typeQualification = field.isBinary()
-							? typeSignature.substring(0, lastDot).toCharArray()
+						typeSimpleName = CharOperation.subarray(typeErasure, lastDot + 1, typeErasure.length);
+						typeQualification = CharOperation.subarray(typeErasure, 0, lastDot);
+						if (!field.isBinary()) {
 							// prefix with a '*' as the full qualification could be bigger (because of an import)
-							: CharOperation.concat(IIndexConstants.ONE_STAR, typeSignature.substring(0, lastDot).toCharArray());
+							CharOperation.concat(IIndexConstants.ONE_STAR, typeQualification);
+						}
 					}
 				} catch (JavaModelException e) {
 					return null;
@@ -789,7 +894,8 @@
 								declaringSimpleName, 
 								typeQualification, 
 								typeSimpleName,
-								R_EXACT_MATCH | R_CASE_SENSITIVE);
+								typeSignature,
+								matchRule);
 						break;
 					case IJavaSearchConstants.REFERENCES :
 						searchPattern = 
@@ -802,7 +908,8 @@
 								declaringSimpleName, 
 								typeQualification, 
 								typeSimpleName,
-								R_EXACT_MATCH | R_CASE_SENSITIVE);
+								typeSignature,
+								matchRule);
 						break;
 					case IJavaSearchConstants.READ_ACCESSES :
 						searchPattern = 
@@ -815,7 +922,8 @@
 								declaringSimpleName, 
 								typeQualification, 
 								typeSimpleName,
-								R_EXACT_MATCH | R_CASE_SENSITIVE);
+								typeSignature,
+								matchRule);
 						break;
 					case IJavaSearchConstants.WRITE_ACCESSES :
 						searchPattern = 
@@ -828,7 +936,8 @@
 								declaringSimpleName, 
 								typeQualification, 
 								typeSimpleName,
-								R_EXACT_MATCH | R_CASE_SENSITIVE);
+								typeSignature,
+								matchRule);
 						break;
 					case IJavaSearchConstants.ALL_OCCURRENCES :
 						searchPattern =
@@ -841,7 +950,8 @@
 								declaringSimpleName, 
 								typeQualification, 
 								typeSimpleName,
-								R_EXACT_MATCH | R_CASE_SENSITIVE);
+								typeSignature,
+								matchRule);
 						break;
 				}
 				break;
@@ -851,14 +961,17 @@
 				if (lastDot == -1) return null; // invalid import declaration
 				IImportDeclaration importDecl = (IImportDeclaration)element;
 				if (importDecl.isOnDemand()) {
-					searchPattern = createPackagePattern(elementName.substring(0, lastDot), limitTo, R_EXACT_MATCH | R_CASE_SENSITIVE);
+					searchPattern = createPackagePattern(elementName.substring(0, lastDot), limitTo, matchRule);
 				} else {
 					searchPattern = 
 						createTypePattern(
 							elementName.substring(lastDot+1).toCharArray(),
 							elementName.substring(0, lastDot).toCharArray(),
 							null,
-							limitTo);
+							false, // does not need signature
+							null,
+							limitTo,
+							matchRule);
 				}
 				break;
 			case IJavaElement.LOCAL_VARIABLE :
@@ -871,7 +984,7 @@
 								false, // no read access
 								false, // no write access
 								localVar,
-								R_EXACT_MATCH | R_CASE_SENSITIVE);
+								matchRule);
 						break;
 					case IJavaSearchConstants.REFERENCES :
 						searchPattern = 
@@ -880,7 +993,7 @@
 								true, // read access
 								true, // write access
 								localVar,
-								R_EXACT_MATCH | R_CASE_SENSITIVE);
+								matchRule);
 						break;
 					case IJavaSearchConstants.READ_ACCESSES :
 						searchPattern = 
@@ -889,7 +1002,7 @@
 								true, // read access only
 								false,
 								localVar,
-								R_EXACT_MATCH | R_CASE_SENSITIVE);
+								matchRule);
 						break;
 					case IJavaSearchConstants.WRITE_ACCESSES :
 						searchPattern = 
@@ -898,7 +1011,7 @@
 								false,
 								true, // write access only
 								localVar,
-								R_EXACT_MATCH | R_CASE_SENSITIVE);
+								matchRule);
 						break;
 					case IJavaSearchConstants.ALL_OCCURRENCES :
 						searchPattern =
@@ -907,7 +1020,7 @@
 								true, // read access
 								true, // write access
 								localVar,
-								R_EXACT_MATCH | R_CASE_SENSITIVE);
+								matchRule);
 						break;
 				}
 				break;
@@ -928,6 +1041,7 @@
 				char[] selector = method.getElementName().toCharArray();
 				char[] returnSimpleName;
 				char[] returnQualification;
+				boolean varargs = false;
 				try {
 					String returnType = Signature.toString(method.getReturnType()).replace('$', '.');
 					if ((lastDot = returnType.lastIndexOf('.')) == -1) {
@@ -940,6 +1054,7 @@
 							// prefix with a '*' as the full qualification could be bigger (because of an import)
 							: CharOperation.concat(IIndexConstants.ONE_STAR, returnType.substring(0, lastDot).toCharArray());
 					}
+					varargs = Flags.isVarargs(method.getFlags());
 				} catch (JavaModelException e) {
 					return null;
 				}
@@ -958,7 +1073,7 @@
 							? signature.substring(0, lastDot).toCharArray()
 							// prefix with a '*' as the full qualification could be bigger (because of an import)
 							: CharOperation.concat(IIndexConstants.ONE_STAR, signature.substring(0, lastDot).toCharArray());
-				}
+					}
 				}
 				switch (limitTo) {
 					case IJavaSearchConstants.DECLARATIONS :
@@ -971,7 +1086,8 @@
 									declaringQualification, 
 									parameterQualifications, 
 									parameterSimpleNames,
-									R_EXACT_MATCH | R_CASE_SENSITIVE);
+									varargs,
+									matchRule);
 						} else {
 							searchPattern = 
 								new MethodPattern(
@@ -984,8 +1100,9 @@
 									returnSimpleName, 
 									parameterQualifications, 
 									parameterSimpleNames,
+									varargs,
 									null,
-									R_EXACT_MATCH | R_CASE_SENSITIVE);
+									matchRule);
 						}
 						break;
 					case IJavaSearchConstants.REFERENCES :
@@ -998,7 +1115,8 @@
 									declaringQualification, 
 									parameterQualifications, 
 									parameterSimpleNames,
-									R_EXACT_MATCH | R_CASE_SENSITIVE);
+									varargs,
+									matchRule);
 						} else {
 							searchPattern = 
 								new MethodPattern(
@@ -1011,8 +1129,9 @@
 									returnSimpleName, 
 									parameterQualifications, 
 									parameterSimpleNames,
+									varargs,
 									method.getDeclaringType(),
-									R_EXACT_MATCH | R_CASE_SENSITIVE);
+									matchRule);
 						}
 						break;
 					case IJavaSearchConstants.ALL_OCCURRENCES :
@@ -1025,7 +1144,8 @@
 									declaringQualification, 
 									parameterQualifications, 
 									parameterSimpleNames,
-									R_EXACT_MATCH | R_CASE_SENSITIVE);
+									varargs,
+									matchRule);
 						} else {
 							searchPattern =
 								new MethodPattern(
@@ -1038,31 +1158,42 @@
 									returnSimpleName, 
 									parameterQualifications, 
 									parameterSimpleNames,
+									varargs,
 									method.getDeclaringType(),
-									R_EXACT_MATCH | R_CASE_SENSITIVE);
+									matchRule);
 						}
 						break;
 				}
 				break;
 			case IJavaElement.TYPE :
 				IType type = (IType)element;
-				searchPattern = 
-					createTypePattern(
-						type.getElementName().toCharArray(), 
-						type.getPackageFragment().getElementName().toCharArray(),
-						enclosingTypeNames(type),
-						limitTo);
+				String signature = type instanceof ParameterizedSourceType ? ((ParameterizedSourceType) type).uniqueKey : null;
+				searchPattern = 	createTypePattern(
+							type.getElementName().toCharArray(), 
+							type.getPackageFragment().getElementName().toCharArray(),
+							enclosingTypeNames(type),
+							true, // need signature
+							signature,
+							limitTo,
+							matchRule);
+				if (searchPattern == null) { // TODO (frederic) remove when new API IType.getParameterizedName() will be available
+					searchPattern = new TypeReferencePattern(
+						CharOperation.concatWith(type.getPackageFragment().getElementName().toCharArray(), enclosingTypeNames(type), '.'), 
+						type.getElementName().toCharArray(),
+						type,
+						matchRule);
+				}
 				break;
 			case IJavaElement.PACKAGE_DECLARATION :
 			case IJavaElement.PACKAGE_FRAGMENT :
-				searchPattern = createPackagePattern(element.getElementName(), limitTo, R_EXACT_MATCH | R_CASE_SENSITIVE);
+				searchPattern = createPackagePattern(element.getElementName(), limitTo, matchRule);
 				break;
 		}
 		if (searchPattern != null)
 			MatchLocator.setFocus(searchPattern, element);
 		return searchPattern;
 	}
-	private static SearchPattern createTypePattern(char[] simpleName, char[] packageName, char[][] enclosingTypeNames, int limitTo) {
+	private static SearchPattern createTypePattern(char[] simpleName, char[] packageName, char[][] enclosingTypeNames, boolean needSignature, String typeSignature, int limitTo, int matchRule) {
 		switch (limitTo) {
 			case IJavaSearchConstants.DECLARATIONS :
 				return new TypeDeclarationPattern(
@@ -1070,18 +1201,20 @@
 					enclosingTypeNames, 
 					simpleName, 
 					IIndexConstants.TYPE_SUFFIX,
-					R_EXACT_MATCH | R_CASE_SENSITIVE);
+					matchRule);
 			case IJavaSearchConstants.REFERENCES :
+				if (needSignature && typeSignature == null) return null;
 				return new TypeReferencePattern(
 					CharOperation.concatWith(packageName, enclosingTypeNames, '.'), 
 					simpleName,
-					R_EXACT_MATCH | R_CASE_SENSITIVE);
+					typeSignature,
+					matchRule);
 			case IJavaSearchConstants.IMPLEMENTORS : 
 				return new SuperTypeReferencePattern(
 					CharOperation.concatWith(packageName, enclosingTypeNames, '.'), 
 					simpleName,
 					true,
-					R_EXACT_MATCH | R_CASE_SENSITIVE);
+					matchRule);
 			case IJavaSearchConstants.ALL_OCCURRENCES :
 				return new OrPattern(
 					new TypeDeclarationPattern(
@@ -1089,19 +1222,30 @@
 						enclosingTypeNames, 
 						simpleName, 
 						IIndexConstants.TYPE_SUFFIX,
-						R_EXACT_MATCH | R_CASE_SENSITIVE), 
+						matchRule), 
 					new TypeReferencePattern(
 						CharOperation.concatWith(packageName, enclosingTypeNames, '.'), 
 						simpleName,
-						R_EXACT_MATCH | R_CASE_SENSITIVE));
+						typeSignature,
+						matchRule));
 		}
 		return null;
 	}
 	/**
-	 * Type pattern are formed by [qualification.]type
+	 * Type pattern are formed by [qualification.]type.
 	 * e.g. java.lang.Object
 	 *		Runnable
 	 *
+	 * @since 3.1
+	 *		Type arguments can be specified to search references to parameterized types.
+	 * 	Then patterns will look as follow:
+	 * 		[qualification.] type [ '<' [ [ '?' {'extends'|'super'} ] type ( ',' [ '?' {'extends'|'super'} ] type )* ] '>' ]
+	 * 	Please note that:
+	 * 		- '*' is not valid inside type arguments definition <>
+	 * 		- '?' is treated as a wildcard when it is inside <> (ie. it must be put on first position of the type argument)
+	 * 		- nested <> are not allowed; List<List<Object>> will be treated as pattern List<List>
+	 * 		- only one type arguments definition is allowed; Gen<Exception>.Member<Object>
+	 *				will be treated as pattern Gen<Exception>.Member
 	 */
 	private static SearchPattern createTypePattern(String patternString, int limitTo, int matchRule) {
 		
@@ -1114,11 +1258,23 @@
 		} catch (InvalidInputException e) {
 			return null;
 		}
+		int paramCount = 0;
 		while (token != TerminalTokens.TokenNameEOF) {
 			switch (token) {
 				case TerminalTokens.TokenNameWHITESPACE:
-					break;
+					if (paramCount == 0) break;
+					// fall through default case if we're inside a type argument...
 				default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
+					switch (token) {
+						case TerminalTokens.TokenNameGREATER:
+						case TerminalTokens.TokenNameRIGHT_SHIFT:
+						case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT:
+							paramCount--;
+							break;
+						case TerminalTokens.TokenNameLESS:
+							paramCount++;
+							break;
+					}
 					if (type == null)
 						type = new String(scanner.getCurrentTokenSource());
 					else
@@ -1131,12 +1287,26 @@
 			}
 		}
 		if (type == null) return null;
-	
+		String typeSignature = null;
 		char[] qualificationChars = null, typeChars = null;
 	
 		// extract declaring type infos
 		if (type != null) {
-			char[] typePart = type.toCharArray();
+			// get type part and signature
+			char[] typePart = null;
+			try {
+				typeSignature = Signature.createTypeSignature(type, false);
+				if (typeSignature.indexOf(Signature.C_GENERIC_START) < 0) {
+					typePart = type.toCharArray();
+				} else {
+					typePart = Signature.toCharArray(Signature.getTypeErasure(typeSignature.toCharArray()));
+				}
+			}
+			catch (IllegalArgumentException iae) {
+				// string is not a valid type syntax
+				return null;
+			}
+			// get qualification name
 			int lastDotPosition = CharOperation.lastIndexOf('.', typePart);
 			if (lastDotPosition >= 0) {
 				qualificationChars = CharOperation.subarray(typePart, 0, lastDotPosition);
@@ -1154,7 +1324,7 @@
 			case IJavaSearchConstants.DECLARATIONS : // cannot search for explicit member types
 				return new QualifiedTypeDeclarationPattern(qualificationChars, typeChars, IIndexConstants.TYPE_SUFFIX, matchRule);
 			case IJavaSearchConstants.REFERENCES :
-				return new TypeReferencePattern(qualificationChars, typeChars, matchRule);
+				return new TypeReferencePattern(qualificationChars, typeChars, typeSignature, matchRule);
 			case IJavaSearchConstants.IMPLEMENTORS : 
 				return new SuperTypeReferencePattern(qualificationChars, typeChars, true, matchRule);
 			case IJavaSearchConstants.ALL_OCCURRENCES :
@@ -1195,6 +1365,7 @@
 				return null;
 		}
 	}
+
 	/**
 	 * Decode the given index key in this pattern. The decoded index key is used by 
 	 * {@link #matchesDecodedKey(SearchPattern)} to find out if the corresponding index entry 
@@ -1256,6 +1427,7 @@
 	 * @return one of R_EXACT_MATCH, R_PREFIX_MATCH, R_PATTERN_MATCH, R_REGEXP_MATCH combined with R_CASE_SENSITIVE,
 	 *   e.g. R_EXACT_MATCH | R_CASE_SENSITIVE if an exact and case sensitive match is requested, 
 	 *   or R_PREFIX_MATCH if a prefix non case sensitive match is requested.
+	 * [TODO (frederic) I hope R_ERASURE_MATCH doesn't need to be on this list. Because it would be a breaking API change.]
 	 */	
 	public final int getMatchRule() {
 		return this.matchRule;
@@ -1288,7 +1460,10 @@
 		if (pattern == null) return true; // null is as if it was "*"
 		if (name != null) {
 			boolean isCaseSensitive = (this.matchRule & R_CASE_SENSITIVE) != 0;
-			int matchMode = this.matchRule - (isCaseSensitive ? R_CASE_SENSITIVE : 0);
+			boolean isRawMatch = (this.matchRule & R_ERASURE_MATCH) != 0;
+			int matchMode = this.matchRule
+						- (isCaseSensitive ? R_CASE_SENSITIVE : 0)
+						- (isRawMatch ? R_ERASURE_MATCH : 0);
 			switch (matchMode) {
 				case R_EXACT_MATCH :
 					return CharOperation.equals(pattern, name, isCaseSensitive);
@@ -1299,7 +1474,7 @@
 						pattern = CharOperation.toLowerCase(pattern);
 					return CharOperation.match(pattern, name, isCaseSensitive);
 				case R_REGEXP_MATCH :
-					// TODO (jerome) implement regular expression match
+					// TODO (frederic) implement regular expression match
 					return true;
 			}
 		}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchRequestor.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchRequestor.java
index aa4d3b2..85a79ca 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchRequestor.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchRequestor.java
@@ -37,7 +37,6 @@
 	 * @param match the found match
 	 * @throws CoreException
 	 */
-	// TODO (jerome) - remove throws CoreException
 	public abstract void acceptSearchMatch(SearchMatch match) throws CoreException;
 
 	/**
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DiskIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DiskIndex.java
index a9f684e..0934384 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DiskIndex.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DiskIndex.java
@@ -16,6 +16,7 @@
 import org.eclipse.jdt.internal.core.util.*;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfIntValues;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 
 public class DiskIndex {
 
@@ -32,7 +33,7 @@
 private String[][] cachedChunks; // decompressed chunks of document names
 private HashtableOfObject categoryTables; // category name -> HashtableOfObject(words -> int[] of document #'s) or offset if not read yet
 
-public static final String SIGNATURE= "INDEX VERSION 1.001"; //$NON-NLS-1$
+public static final String SIGNATURE= "INDEX VERSION 1.011"; //$NON-NLS-1$
 public static boolean DEBUG = false;
 
 private static final int RE_INDEXED = -1;
@@ -250,7 +251,7 @@
 	}
 	return newDocNames;
 }
-private void copyQueryResults(HashtableOfObject categoryToWords, int newPosition) throws IOException {
+private void copyQueryResults(HashtableOfObject categoryToWords, int newPosition) {
 	char[][] categoryNames = categoryToWords.keyTable;
 	Object[] wordSets = categoryToWords.valueTable;
 	for (int i = 0, l = categoryNames.length; i < l; i++) {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/Index.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/Index.java
index 44a4f5b..a3132fe 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/Index.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/Index.java
@@ -19,6 +19,7 @@
 import org.eclipse.jdt.internal.core.util.*;
 import org.eclipse.jdt.internal.core.search.indexing.InternalSearchDocument;
 import org.eclipse.jdt.internal.core.search.indexing.ReadWriteMonitor;
+import org.eclipse.jdt.internal.core.search.matching.JavaSearchPattern;
 
 /**
  * An <code>Index</code> maps document names to their referenced words in various categories.
@@ -69,7 +70,8 @@
 public static boolean isMatch(char[] pattern, char[] word, int matchRule) {
 	if (pattern == null) return true;
 
-	switch(matchRule) {
+	// need to mask some bits of pattern rule (bug 79790)
+	switch(matchRule & JavaSearchPattern.MATCH_RULE_INDEX_MASK) {
 		case SearchPattern.R_EXACT_MATCH :
 			return CharOperation.equals(pattern, word, false);
 		case SearchPattern.R_PREFIX_MATCH :
@@ -173,11 +175,11 @@
 	if (numberOfChanges > 1000)
 		System.gc(); // reclaim space if the MemoryIndex was very BIG
 }
-public void startQuery() throws IOException {
+public void startQuery() {
 	if (this.diskIndex != null)
 		this.diskIndex.startQuery();
 }
-public void stopQuery() throws IOException {
+public void stopQuery() {
 	if (this.diskIndex != null)
 		this.diskIndex.stopQuery();
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/MemoryIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/MemoryIndex.java
index ca44041..3656e51 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/MemoryIndex.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/MemoryIndex.java
@@ -14,6 +14,7 @@
 import org.eclipse.jdt.internal.core.search.indexing.InternalSearchDocument;
 import org.eclipse.jdt.internal.core.util.*;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 
 public class MemoryIndex {
 
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IRestrictedAccessTypeRequestor.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IRestrictedAccessTypeRequestor.java
new file mode 100644
index 0000000..ee917f8
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IRestrictedAccessTypeRequestor.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.search;
+
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+
+/**
+ * A <code>IRestrictedAccessTypeRequestor</code> collects search results from a <code>searchAllTypeNames</code>
+ * query to a <code>SearchBasicEngine</code> providing restricted access information when a class or an interface is accepted.
+ * @see org.eclipse.jdt.core.search.ITypeNameRequestor
+ */
+public interface IRestrictedAccessTypeRequestor {
+	
+	public void acceptAnnotation(char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path, AccessRestriction access);
+
+	public void acceptClass(char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path, AccessRestriction access);
+
+	public void acceptEnum(char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path, AccessRestriction access);
+
+	public void acceptInterface(char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path, AccessRestriction access);
+
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexQueryRequestor.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexQueryRequestor.java
index 327dcee..198450c 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexQueryRequestor.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexQueryRequestor.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.jdt.core.search.SearchParticipant;
 import org.eclipse.jdt.core.search.SearchPattern;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 
 /**
  * TODO add spec
@@ -19,6 +20,6 @@
 public abstract class IndexQueryRequestor {
 	
 	// answer false if requesting cancel
-	public abstract boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant);
+	public abstract boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant, AccessRestriction access);
 	
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchDocument.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchDocument.java
index 3d23b40..1117c79 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchDocument.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchDocument.java
@@ -19,7 +19,6 @@
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jdt.core.search.IJavaSearchScope;
 import org.eclipse.jdt.core.search.SearchDocument;
-import org.eclipse.jdt.core.search.SearchEngine;
 import org.eclipse.jdt.core.search.SearchParticipant;
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
 
@@ -46,7 +45,7 @@
 		try {
 			return org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(getLocation().toFile());
 		} catch (IOException e) {
-			if (SearchEngine.VERBOSE || JobManager.VERBOSE) { // used during search and during indexing
+			if (SearchBasicEngine.VERBOSE || JobManager.VERBOSE) { // used during search and during indexing
 				e.printStackTrace();
 			}
 			return null;
@@ -57,7 +56,7 @@
 		try {
 			return org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(getLocation().toFile(), getEncoding());
 		} catch (IOException e) {
-			if (SearchEngine.VERBOSE || JobManager.VERBOSE) { // used during search and during indexing
+			if (SearchBasicEngine.VERBOSE || JobManager.VERBOSE) { // used during search and during indexing
 				e.printStackTrace();
 			}
 			return null;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchParticipant.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchParticipant.java
index 231a7f6..22175c6 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchParticipant.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchParticipant.java
@@ -68,7 +68,7 @@
 		document.removeAllIndexEntries(); // in case the document was already indexed
 
 		String documentPath = document.getPath();
-		if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(documentPath)) {
+		if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(documentPath)) {
 			new SourceIndexer(document).indexDocument();
 		} else if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(documentPath)) {
 			new BinaryIndexer(document).indexDocument();
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java
index 44f8400..b2ab4c6 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java
@@ -25,12 +25,14 @@
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IMember;
 import org.eclipse.jdt.core.IOpenable;
-import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.core.*;
 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.util.Util;
 
 /**
  * A Java-specific scope for searching relative to one or more java elements.
@@ -44,9 +46,11 @@
 	   if the resources are projects) */
 	private IPath[] paths;
 	private boolean[] pathWithSubFolders;
+	private AccessRestriction[] pathRestrictions;
 	private int pathsCount;
 	
 	private IPath[] enclosingProjectsAndJars;
+	public final static AccessRestriction UNINIT_RESTRICTION = new AccessRestriction(null, null, null, null);
 	
 public JavaSearchScope() {
 	this.initialize();
@@ -69,7 +73,25 @@
 	this.enclosingProjectsAndJars[length] = path;
 }
 
-public void add(JavaProject javaProject, int includeMask, HashSet visitedProjects) throws JavaModelException {
+/**
+ * Add java project all fragment roots to current java search scope.
+ * @see #add(JavaProject, IPath, int, HashSet, IClasspathEntry)
+ */
+public void add(JavaProject project, int includeMask, HashSet visitedProject) throws JavaModelException {
+	add(project, null, includeMask, visitedProject, null);
+}
+/**
+ * Add a path to current java search scope or all project fragment roots if null.
+ * Use project resolved classpath to retrieve and store access restriction on each classpath entry.
+ * Recurse if dependent projects are found.
+ * @param javaProject Project used to get resolved classpath entries
+ * @param pathToAdd Path to add in case of single element or null if user want to add all project package fragment roots
+ * @param includeMask Mask to apply on classpath entries
+ * @param visitedProjects Set to avoid infinite recursion
+ * @param referringEntry Project raw entry in referring project classpath
+ * @throws JavaModelException May happen while getting java model info 
+ */
+void add(JavaProject javaProject, IPath pathToAdd, int includeMask, HashSet visitedProjects, IClasspathEntry referringEntry) throws JavaModelException {
 	IProject project = javaProject.getProject();
 	if (!project.isAccessible() || !visitedProjects.add(project)) return;
 
@@ -77,23 +99,35 @@
 
 	IClasspathEntry[] entries = javaProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
 	IJavaModel model = javaProject.getJavaModel();
+	JavaModelManager.PerProjectInfo perProjectInfo = javaProject.getPerProjectInfo();
 	for (int i = 0, length = entries.length; i < length; i++) {
 		IClasspathEntry entry = entries[i];
+		IClasspathEntry rawEntry = null;
+		if (perProjectInfo != null && perProjectInfo.resolvedPathToRawEntries != null) {
+			rawEntry = (IClasspathEntry) perProjectInfo.resolvedPathToRawEntries.get(entry.getPath());
+		}
+		if (rawEntry == null) continue;
+		AccessRestriction access = null;
+		ClasspathEntry cpEntry = null;
+		if (rawEntry instanceof ClasspathEntry) {
+			cpEntry = (ClasspathEntry) rawEntry;
+			if (referringEntry != null) {
+				cpEntry = cpEntry.combineWith(referringEntry);
+//				cpEntry = ((ClasspathEntry)referringEntry).combineWith(cpEntry);
+			}
+			access = cpEntry.getImportRestriction();
+		}
 		switch (entry.getEntryKind()) {
 			case IClasspathEntry.CPE_LIBRARY:
-				IClasspathEntry rawEntry = null;
-				JavaModelManager.PerProjectInfo perProjectInfo = javaProject.getPerProjectInfo();
-				if (perProjectInfo != null && perProjectInfo.resolvedPathToRawEntries != null) {
-					rawEntry = (IClasspathEntry) perProjectInfo.resolvedPathToRawEntries.get(entry.getPath());
-				}
-				if (rawEntry == null) break;
 				switch (rawEntry.getEntryKind()) {
 					case IClasspathEntry.CPE_LIBRARY:
 					case IClasspathEntry.CPE_VARIABLE:
 						if ((includeMask & APPLICATION_LIBRARIES) != 0) {
 							IPath path = entry.getPath();
-							add(path, true);
-							addEnclosingProjectOrJar(path);
+							if (pathToAdd == null || pathToAdd.equals(path)) {
+								add(path, true, access);
+								addEnclosingProjectOrJar(path);
+							}
 						}
 						break;
 					case IClasspathEntry.CPE_CONTAINER:
@@ -102,47 +136,85 @@
 						if ((container.getKind() == IClasspathContainer.K_APPLICATION && (includeMask & APPLICATION_LIBRARIES) != 0)
 								|| (includeMask & SYSTEM_LIBRARIES) != 0) {
 							IPath path = entry.getPath();
-							add(path, true);
-							addEnclosingProjectOrJar(path);
+							if (pathToAdd == null || pathToAdd.equals(path)) {
+								add(path, true, access);
+								addEnclosingProjectOrJar(path);
+							}
 						}
 						break;
 				}
 				break;
 			case IClasspathEntry.CPE_PROJECT:
 				if ((includeMask & REFERENCED_PROJECTS) != 0) {
-					add((JavaProject) model.getJavaProject(entry.getPath().lastSegment()), includeMask, visitedProjects);
+					IPath path = entry.getPath();
+					if (pathToAdd == null || pathToAdd.equals(path)) {
+						add((JavaProject) model.getJavaProject(entry.getPath().lastSegment()), null, includeMask, visitedProjects, cpEntry);
+					}
 				}
 				break;
 			case IClasspathEntry.CPE_SOURCE:
 				if ((includeMask & SOURCES) != 0) {
-					add(entry.getPath(), true);
+					IPath path = entry.getPath();
+					if (pathToAdd == null || pathToAdd.equals(path)) {
+						add(entry.getPath(), true, access);
+					}
 				}
 				break;
 		}
 	}
 }
+/**
+ * Add an element to the java search scope. use element project to retrieve and
+ * store access restriction corresponding to the provided element.
+ * @param element The element we want to add to current java search scope
+ * @throws JavaModelException May happen if some Java Model info are not available
+ */
 public void add(IJavaElement element) throws JavaModelException {
+//	add(element, element.getJavaProject());
+	add(element, null);
+}
+/**
+ * Add an element to the java search scope. If project is not null, then use it to
+ * retrieve and store access restriction corresponding to the provided element.
+ * @param element The element we want to add to current java search scope
+ * @throws JavaModelException May happen if some Java Model info are not available
+ */
+public void add(IJavaElement element, IJavaProject project) throws JavaModelException {
 	IPackageFragmentRoot root = null;
+	int includeMask = SOURCES | APPLICATION_LIBRARIES | SYSTEM_LIBRARIES;
 	switch (element.getElementType()) {
 		case IJavaElement.JAVA_MODEL:
 			// a workspace sope should be used
 			break; 
 		case IJavaElement.JAVA_PROJECT:
-			int includeMask = SOURCES | APPLICATION_LIBRARIES | SYSTEM_LIBRARIES;
-			this.add((JavaProject)element, includeMask, new HashSet(2));
+			if (project == null)
+				add((JavaProject)element, null, includeMask, new HashSet(2), null);
+			else
+				add((JavaProject)project, element.getPath(), includeMask, new HashSet(2), null);
 			break;
 		case IJavaElement.PACKAGE_FRAGMENT_ROOT:
 			root = (IPackageFragmentRoot)element;
-			this.add(root.getPath(), true);
+			if (project == null)
+				add(root.getPath(), true, null);
+			else
+				add((JavaProject)project, root.getPath(), includeMask, new HashSet(2), null);
 			break;
 		case IJavaElement.PACKAGE_FRAGMENT:
 			root = (IPackageFragmentRoot)element.getParent();
 			if (root.isArchive()) {
-				this.add(root.getPath().append(new Path(element.getElementName().replace('.', '/'))), false);
+				String relativePath = Util.concatWith(((PackageFragment) element).names, '/');
+				IPath path = root.getPath().append(new Path(relativePath));
+				if (project == null)
+					add(path, false, null);
+				else
+					add((JavaProject)project, path, includeMask, new HashSet(2), null);
 			} else {
 				IResource resource = element.getResource();
 				if (resource != null && resource.isAccessible()) {
-					this.add(resource.getFullPath(), false);
+					if (project == null)
+						add(resource.getFullPath(), false, null);
+					else
+						add((JavaProject)project, resource.getFullPath(), includeMask, new HashSet(2), null);
 				}
 			}
 			break;
@@ -154,7 +226,7 @@
 				}
 				this.elements.add(element);
 			}
-			this.add(this.fullPath(element), true);
+			this.add(this.fullPath(element), true, null);
 			
 			// find package fragment root including this java element
 			IJavaElement parent = element.getParent();
@@ -176,9 +248,10 @@
 }
 
 /**
- * Adds the given path to this search scope. Remember if subfolders need to be included as well.
+ * Adds the given path to this search scope. Remember if subfolders need to be included
+ * and associated access restriction as well.
  */
-private void add(IPath path, boolean withSubFolders) {
+private void add(IPath path, boolean withSubFolders, AccessRestriction access) {
 	if (this.paths.length == this.pathsCount) {
 		System.arraycopy(
 			this.paths,
@@ -192,15 +265,25 @@
 			this.pathWithSubFolders = new boolean[this.pathsCount * 2],
 			0,
 			this.pathsCount);
+		System.arraycopy(
+			this.pathRestrictions,
+			0,
+			this.pathRestrictions = new AccessRestriction[this.pathsCount * 2],
+			0,
+			this.pathsCount);
 	}
 	this.paths[this.pathsCount] = path;
-	this.pathWithSubFolders[this.pathsCount++] = withSubFolders; 
+	this.pathWithSubFolders[this.pathsCount] = withSubFolders; 
+	this.pathRestrictions[this.pathsCount++] = access;
 }
 
 /* (non-Javadoc)
  * @see IJavaSearchScope#encloses(String)
  */
 public boolean encloses(String resourcePathString) {
+	return this.encloses(fullPath(resourcePathString)) >= 0;
+}
+private IPath fullPath(String resourcePathString) {
 	IPath resourcePath;
 	int separatorIndex = resourcePathString.indexOf(JAR_FILE_ENTRY_SEPARATOR);
 	if (separatorIndex != -1) {
@@ -210,17 +293,17 @@
 	} else {
 			resourcePath = new Path(resourcePathString);
 	}
-	return this.encloses(resourcePath);
+	return resourcePath;
 }
 
 /**
- * Returns whether this search scope encloses the given path.
+ * Returns paths list index of given path or -1 if not found.
  */
-private boolean encloses(IPath path) {
+private int encloses(IPath path) {
 	for (int i = 0; i < this.pathsCount; i++) {
 		if (this.pathWithSubFolders[i]) {
 			if (this.paths[i].isPrefixOf(path)) {
-				return true;
+				return i;
 			}
 		} else {
 			// if not looking at subfolders, this scope encloses the given path 
@@ -230,11 +313,11 @@
 			if (scopePath.isPrefixOf(path) 
 				&& ((scopePath.segmentCount() == path.segmentCount() - 1)
 					|| (scopePath.segmentCount() == path.segmentCount()))) {
-				return true;
+				return i;
 			}
 		}
 	}
-	return false;
+	return -1;
 }
 
 /* (non-Javadoc)
@@ -253,7 +336,7 @@
 		}
 		return false;
 	}
-	return this.encloses(this.fullPath(element));
+	return this.encloses(this.fullPath(element)) >= 0;
 }
 
 /* (non-Javadoc)
@@ -269,8 +352,9 @@
 	IJavaElement parent = element.getParent();
 	IPath parentPath = parent == null ? null : this.fullPath(parent);
 	IPath childPath;
-	if (element instanceof IPackageFragment) {
-		childPath = new Path(element.getElementName().replace('.', '/'));
+	if (element instanceof PackageFragment) {
+		String relativePath = Util.concatWith(((PackageFragment) element).names, '/');
+		childPath = new Path(relativePath);
 	} else if (element instanceof IOpenable) {
 		childPath = new Path(element.getElementName());
 	} else {
@@ -279,9 +363,25 @@
 	return parentPath == null ? childPath : parentPath.append(childPath);
 }
 
+/**
+ * Get access restriction corresponding to a given path.
+ * @param path The path user want to have restriction access
+ * @return The access restriction for given path or null if none is set for it.
+ * 	Returns specific uninit restriction when scope does not enclose the given path.
+ */
+public AccessRestriction getAccessRestriction(String path) {
+	int index = encloses(fullPath(path));
+	if (index == -1) {
+		// this search scope does not enclose given path
+		return UNINIT_RESTRICTION;
+	}
+	return this.pathRestrictions[index];
+}
+
 protected void initialize() {
 	this.paths = new IPath[1];
 	this.pathWithSubFolders = new boolean[1];
+	this.pathRestrictions = new AccessRestriction[1];
 	this.pathsCount = 0;
 	this.enclosingProjectsAndJars = new IPath[0];
 }
@@ -356,5 +456,4 @@
 	}
 	return result.toString();
 }
-
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaWorkspaceScope.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaWorkspaceScope.java
index 8d3d176..3611d6c 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaWorkspaceScope.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaWorkspaceScope.java
@@ -77,7 +77,7 @@
 		IJavaProject[] projects = JavaModelManager.getJavaModelManager().getJavaModel().getJavaProjects();
 		for (int i = 0, length = projects.length; i < length; i++) {
 			int includeMask = SOURCES | APPLICATION_LIBRARIES | SYSTEM_LIBRARIES;
-			this.add((JavaProject) projects[i], includeMask, new HashSet(2));
+			add((JavaProject) projects[i], null, includeMask, new HashSet(length*2, 1), null);
 		}
 	} catch (JavaModelException ignored) {
 		// ignore
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PathCollector.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PathCollector.java
index cff112e..ea903d4 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PathCollector.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PathCollector.java
@@ -15,6 +15,7 @@
 
 import org.eclipse.jdt.core.search.SearchParticipant;
 import org.eclipse.jdt.core.search.SearchPattern;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 
 /**
  * Collects the resource paths reported by a client to this search requestor.
@@ -27,7 +28,7 @@
 	/* (non-Javadoc)
 	 * @seeIndexQueryRequestor#acceptIndexMatch(IndexRecord, SearchParticipant, SearchPattern)
 	 */
-	public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant) {
+	public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant, AccessRestriction access) {
 		paths.add(documentPath);
 		return true;
 	}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PatternSearchJob.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PatternSearchJob.java
index 9e25e90..5b7c89d 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PatternSearchJob.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PatternSearchJob.java
@@ -87,9 +87,11 @@
 		// may trigger some index recreation work
 		String indexLocation = indexLocations[i].toOSString();
 		IPath containerPath = (IPath) indexManager.indexLocations.keyForValue(indexLocation);
-		Index index = indexManager.getIndex(containerPath, indexLocations[i].toOSString(), true /*reuse index file*/, false /*do not create if none*/);
-		if (index != null)
-			indexes[count++] = index; // only consider indexes which are ready
+		if (containerPath != null) { // sanity check
+			Index index = indexManager.getIndex(containerPath, indexLocation, true /*reuse index file*/, false /*do not create if none*/);
+			if (index != null)
+				indexes[count++] = index; // only consider indexes which are ready
+		}
 	}
 	if (count == length) 
 		this.areIndexesReady = true;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/SearchBasicEngine.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/SearchBasicEngine.java
new file mode 100644
index 0000000..fb9d69f
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/SearchBasicEngine.java
@@ -0,0 +1,822 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.search;
+
+import java.util.*;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.*;
+import org.eclipse.jdt.internal.compiler.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
+import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.jdt.internal.core.*;
+import org.eclipse.jdt.internal.core.search.indexing.*;
+import org.eclipse.jdt.internal.core.search.matching.*;
+import org.eclipse.jdt.internal.core.util.Util;
+
+/**
+ * Search basic engine. Public search engine (see {@link org.eclipse.jdt.core.search.SearchEngine}
+ * for detailed comment), now uses basic engine functionalities.
+ * Note that serch basic engine does not implement deprecated functionalities...
+ */
+public class SearchBasicEngine {
+
+	/*
+	 * A default parser to parse non-reconciled working copies
+	 */
+	private Parser parser;
+	private CompilerOptions compilerOptions;
+		
+	/*
+	 * A list of working copies that take precedence over their original 
+	 * compilation units.
+	 */
+	private ICompilationUnit[] workingCopies;
+	
+	/*
+	 * A working copy owner whose working copies will take precedent over 
+	 * their original compilation units.
+	 */
+	private WorkingCopyOwner workingCopyOwner;
+
+	/**
+	 * For tracing purpose.
+	 */	
+	public static boolean VERBOSE = false;	
+
+	/*
+	 * Creates a new search basic engine.
+	 */
+	public SearchBasicEngine() {
+		// will use working copies of PRIMARY owner
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.core.search.SearchEngine#SearchEngine(ICompilationUnit[]) for detailed comment.
+	 */
+	public SearchBasicEngine(ICompilationUnit[] workingCopies) {
+		this.workingCopies = workingCopies;
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.core.search.SearchEngine#SearchEngine(WorkingCopyOwner) for detailed comment.
+	 */
+	public SearchBasicEngine(WorkingCopyOwner workingCopyOwner) {
+		this.workingCopyOwner = workingCopyOwner;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.core.search.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.
+	 */
+	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.
+	 */
+	public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements) {
+		return createJavaSearchScope(elements, true);
+	}
+
+	/**
+	 * @see org.eclipse.jdt.core.search.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;
+		if (includeReferencedProjects) {
+			includeMask |= IJavaSearchScope.REFERENCED_PROJECTS;
+		}
+		return createJavaSearchScope(elements, includeMask);
+	}
+
+	/**
+	 * @see org.eclipse.jdt.core.search.SearchEngine#createJavaSearchScope(IJavaElement[], int) for detailed comment.
+	 */
+	public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements, int includeMask) {
+		JavaSearchScope scope = new JavaSearchScope();
+		HashSet visitedProjects = new HashSet(2);
+		try {
+			for (int i = 0, length = elements.length; i < length; i++) {
+				IJavaElement element = elements[i];
+				if (element != null) {
+					if (element instanceof JavaProject) {
+						scope.add((JavaProject)element, includeMask, visitedProjects);
+					} else {
+						scope.add(element);
+					}
+				}
+			}
+		} catch (JavaModelException e) {
+			// ignore
+		}
+		return scope;
+	}
+	
+	/**
+	 * Returns a Java search scope with the workspace as the only limit.
+	 *
+	 * @return a new workspace scope
+	 */
+	public static IJavaSearchScope createWorkspaceScope() {
+		return new JavaWorkspaceScope();
+	}
+	
+	/**
+	 * Searches for matches to a given query. Search queries can be created using helper
+	 * methods (from a String pattern or a Java element) and encapsulate the description of what is
+	 * being searched (for example, search method declarations in a case sensitive way).
+	 *
+	 * @param scope the search result has to be limited to the given scope
+	 * @param 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 {
+		if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
+	
+		/* initialize progress monitor */
+		if (monitor != null)
+			monitor.beginTask(Util.bind("engine.searching"), 100); //$NON-NLS-1$
+		if (VERBOSE)
+			System.out.println("Searching for " + this + " in " + scope); //$NON-NLS-1$//$NON-NLS-2$
+	
+		IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
+		try {
+			requestor.beginReporting();
+			for (int i = 0, l = participants == null ? 0 : participants.length; i < l; i++) {
+				if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
+	
+				SearchParticipant participant = participants[i];
+				SubProgressMonitor subMonitor= monitor==null ? null : new SubProgressMonitor(monitor, 1000);
+				if (subMonitor != null) subMonitor.beginTask("", 1000); //$NON-NLS-1$
+				try {
+					if (subMonitor != null) subMonitor.subTask(Util.bind("engine.searching.indexing", participant.getDescription())); //$NON-NLS-1$
+					participant.beginSearching();
+					requestor.enterParticipant(participant);
+					PathCollector pathCollector = new PathCollector();
+					indexManager.performConcurrentJob(
+						new PatternSearchJob(pattern, participant, scope, pathCollector),
+						IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
+						subMonitor);
+					if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
+	
+					// locate index matches if any (note that all search matches could have been issued during index querying)
+					if (subMonitor != null) subMonitor.subTask(Util.bind("engine.searching.matching", participant.getDescription())); //$NON-NLS-1$
+					String[] indexMatchPaths = pathCollector.getPaths();
+					pathCollector = null; // release
+					int indexMatchLength = indexMatchPaths == null ? 0 : indexMatchPaths.length;
+					SearchDocument[] indexMatches = new SearchDocument[indexMatchLength];
+					for (int j = 0; j < indexMatchLength; j++)
+						indexMatches[j] = participant.getDocument(indexMatchPaths[j]);
+					SearchDocument[] matches = MatchLocator.addWorkingCopies(pattern, indexMatches, getWorkingCopies(), participant);
+					participant.locateMatches(matches, pattern, scope, requestor, subMonitor);
+				} finally {		
+					requestor.exitParticipant(participant);
+					participant.doneSearching();
+				}
+			}
+		} finally {
+			requestor.endReporting();
+			if (monitor != null)
+				monitor.done();
+		}
+	}
+	/**
+	 * Returns a new default Java search participant.
+	 * 
+	 * @return a new default Java search participant
+	 * @since 3.0
+	 */
+	public static SearchParticipant getDefaultSearchParticipant() {
+		return new JavaSearchParticipant();
+	}
+
+	private Parser getParser() {
+		if (this.parser == null) {
+			this.compilerOptions = new CompilerOptions(JavaCore.getOptions());
+			ProblemReporter problemReporter =
+				new ProblemReporter(
+					DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+					this.compilerOptions,
+					new DefaultProblemFactory());
+			this.parser = new Parser(problemReporter, true);
+		}
+		return this.parser;
+	}
+	
+	/**
+	 * Returns the underlying resource of the given element.
+	 * @param element an IJavaElement
+	 * @return an IResource
+	 */
+	private IResource getResource(IJavaElement element) {
+		if (element instanceof IMember) {
+			ICompilationUnit cu = ((IMember)element).getCompilationUnit();
+			if (cu != null) {
+				return cu.getResource();
+			} 
+		} 
+		return element.getResource();
+	}
+	
+	/*
+	 * Returns the list of working copies used by this search engine.
+	 * Returns null if none.
+	 */
+	private ICompilationUnit[] getWorkingCopies() {
+		ICompilationUnit[] copies;
+		if (this.workingCopies != null) {
+			if (this.workingCopyOwner == null) {
+				copies = JavaModelManager.getJavaModelManager().getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, false/*don't add primary WCs a second time*/);
+				if (copies == null) {
+					copies = this.workingCopies;
+				} else {
+					HashMap pathToCUs = new HashMap();
+					for (int i = 0, length = copies.length; i < length; i++) {
+						ICompilationUnit unit = copies[i];
+						pathToCUs.put(unit.getPath(), unit);
+					}
+					for (int i = 0, length = this.workingCopies.length; i < length; i++) {
+						ICompilationUnit unit = this.workingCopies[i];
+						pathToCUs.put(unit.getPath(), unit);
+					}
+					int length = pathToCUs.size();
+					copies = new ICompilationUnit[length];
+					pathToCUs.values().toArray(copies);
+				}
+			} else {
+				copies = this.workingCopies;
+			}
+		} else if (this.workingCopyOwner != null) {
+			copies = JavaModelManager.getJavaModelManager().getWorkingCopies(this.workingCopyOwner, true/*add primary WCs*/);
+		} else {
+			copies = JavaModelManager.getJavaModelManager().getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, false/*don't add primary WCs a second time*/);
+		}
+		if (copies == null) return null;
+		
+		// filter out primary working copies that are saved
+		ICompilationUnit[] result = null;
+		int length = copies.length;
+		int index = 0;
+		for (int i = 0; i < length; i++) {
+			CompilationUnit copy = (CompilationUnit)copies[i];
+			try {
+				if (!copy.isPrimary()
+						|| copy.hasUnsavedChanges()
+						|| copy.hasResourceChanged()) {
+					if (result == null) {
+						result = new ICompilationUnit[length];
+					}
+					result[index++] = copy;
+				}
+			}  catch (JavaModelException e) {
+				// copy doesn't exist: ignore
+			}
+		}
+		if (index != length && result != null) {
+			System.arraycopy(result, 0, result = new ICompilationUnit[index], 0, index);
+		}
+		return result;
+	}
+	
+	/**
+	 * Returns the list of working copies used to do the search on the given Java element.
+	 * @param element an IJavaElement
+	 * @return an array of ICompilationUnit
+	 */
+	private ICompilationUnit[] getWorkingCopies(IJavaElement element) {
+		if (element instanceof IMember) {
+			ICompilationUnit cu = ((IMember)element).getCompilationUnit();
+			if (cu != null && cu.isWorkingCopy()) {
+				ICompilationUnit[] copies = getWorkingCopies();
+				int length = copies == null ? 0 : copies.length;
+				if (length > 0) {
+					ICompilationUnit[] newWorkingCopies = new ICompilationUnit[length+1];
+					System.arraycopy(copies, 0, newWorkingCopies, 0, length);
+					newWorkingCopies[length] = cu;
+					return newWorkingCopies;
+				} 
+				return new ICompilationUnit[] {cu};
+			}
+		}
+		return getWorkingCopies();
+	}
+
+	boolean match(char patternTypeSuffix, char[] patternPkg, char[] patternTypeName, int matchRule, int typeKind, char[] pkg, char[] typeName) {
+		switch(patternTypeSuffix) {
+			case IIndexConstants.CLASS_SUFFIX :
+				if (typeKind != IGenericType.CLASS_DECL) return false;
+				break;
+			case IIndexConstants.INTERFACE_SUFFIX :
+				if (typeKind != IGenericType.INTERFACE_DECL) return false;
+				break;
+			case IIndexConstants.ENUM_SUFFIX :
+				if (typeKind != IGenericType.ENUM_DECL) return false;
+				break;
+			case IIndexConstants.ANNOTATION_TYPE_SUFFIX :
+				if (typeKind != IGenericType.ANNOTATION_TYPE_DECL) return false;
+				break;
+			case IIndexConstants.TYPE_SUFFIX : // nothing
+		}
+	
+		boolean isCaseSensitive = (matchRule & SearchPattern.R_CASE_SENSITIVE) != 0;
+		if (patternPkg != null && !CharOperation.equals(patternPkg, pkg, isCaseSensitive))
+				return false;
+		
+		if (patternTypeName != null) {
+			int matchMode = matchRule - (isCaseSensitive ? SearchPattern.R_CASE_SENSITIVE : 0);
+			switch(matchMode) {
+				case SearchPattern.R_EXACT_MATCH :
+					return CharOperation.equals(patternTypeName, typeName, isCaseSensitive);
+				case SearchPattern.R_PREFIX_MATCH :
+					return CharOperation.prefixEquals(patternTypeName, typeName, isCaseSensitive);
+				case SearchPattern.R_PATTERN_MATCH :
+					return CharOperation.match(patternTypeName, typeName, isCaseSensitive);
+			}
+		}
+		return true;
+	
+	}	
+	
+	/**
+	 * Searches for matches of a given search pattern. Search patterns can be created using helper
+	 * methods (from a String pattern or a Java element) and encapsulate the description of what is
+	 * being searched (for example, search method declarations in a case sensitive way).
+	 *
+	 * @param pattern the pattern to search
+	 * @param participants the particpants in the search
+	 * @param scope the search scope
+	 * @param requestor the requestor to report the matches to
+	 * @param monitor the progress monitor used to report progress
+	 * @exception CoreException if the search failed. Reasons include:
+	 *	<ul>
+	 *		<li>the classpath is incorrectly set</li>
+	 *	</ul>
+	 *@since 3.0
+	 */
+	public void search(SearchPattern pattern, SearchParticipant[] participants, IJavaSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException {
+		findMatches(pattern, participants, scope, requestor, monitor);
+	}
+
+	/**
+	 * Searches for all top-level types and member types in the given scope.
+	 * The search can be selecting specific types (given a package or a type name
+	 * prefix and match modes). 
+	 * 
+	 * @param packageName the full name of the package of the searched types, or a prefix for this
+	 *						package, or a wild-carded string for this package.
+	 * @param typeName the dot-separated qualified name of the searched type (the qualification include
+	 *					the enclosing types if the searched type is a member type), or a prefix
+	 *					for this type, or a wild-carded string for this type.
+	 * @param matchRule one of
+	 * <ul>
+	 *		<li><code>SearchPattern.R_EXACT_MATCH</code> if the package name and type name are the full names
+	 *			of the searched types.</li>
+	 *		<li><code>SearchPattern.R_PREFIX_MATCH</code> if the package name and type name are prefixes of the names
+	 *			of the searched types.</li>
+	 *		<li><code>SearchPattern.R_PATTERN_MATCH</code> if the package name and type name contain wild-cards.</li>
+	 * </ul>
+	 * combined with <code>SearchPattern.R_CASE_SENSITIVE</code>,
+	 *   e.g. <code>R_EXACT_MATCH | R_CASE_SENSITIVE</code> if an exact and case sensitive match is requested, 
+	 *   or <code>R_PREFIX_MATCH</code> if a prefix non case sensitive match is requested.
+	 * @param searchFor one of
+	 * <ul>
+	 * 		<li><code>IJavaSearchConstants.CLASS</code> if searching for classes only</li>
+	 * 		<li><code>IJavaSearchConstants.INTERFACE</code> if searching for interfaces only</li>
+	 * 		<li><code>IJavaSearchConstants.TYPE</code> if searching for both classes and interfaces</li>
+	 * </ul>
+	 * @param scope the scope to search in
+	 * @param nameRequestor the requestor that collects the results of the search
+	 * @param waitingPolicy one of
+	 * <ul>
+	 *		<li><code>IJavaSearchConstants.FORCE_IMMEDIATE_SEARCH</code> if the search should start immediately</li>
+	 *		<li><code>IJavaSearchConstants.CANCEL_IF_NOT_READY_TO_SEARCH</code> if the search should be cancelled if the
+	 *			underlying indexer has not finished indexing the workspace</li>
+	 *		<li><code>IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH</code> if the search should wait for the
+	 *			underlying indexer to finish indexing the workspace</li>
+	 * </ul>
+	 * @param progressMonitor the progress monitor to report progress to, or <code>null</code> if no progress
+	 *							monitor is provided
+	 * @exception JavaModelException if the search failed. Reasons include:
+	 *	<ul>
+	 *		<li>the classpath is incorrectly set</li>
+	 *	</ul>
+	 * @since 3.0
+	 */
+	public void searchAllTypeNames(
+		final char[] packageName, 
+		final char[] typeName,
+		final int matchRule, 
+		int searchFor, 
+		IJavaSearchScope scope, 
+		final IRestrictedAccessTypeRequestor nameRequestor,
+		int waitingPolicy,
+		IProgressMonitor progressMonitor)  throws JavaModelException {
+
+		IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
+			
+		final char typeSuffix;
+		switch(searchFor){
+			case IJavaSearchConstants.CLASS :
+				typeSuffix = IIndexConstants.CLASS_SUFFIX;
+				break;
+			case IJavaSearchConstants.INTERFACE :
+				typeSuffix = IIndexConstants.INTERFACE_SUFFIX;
+				break;
+			case IJavaSearchConstants.ENUM :
+				typeSuffix = IIndexConstants.ENUM_SUFFIX;
+				break;
+			case IJavaSearchConstants.ANNOTATION_TYPE :
+				typeSuffix = IIndexConstants.ANNOTATION_TYPE_SUFFIX;
+				break;
+			default : 
+				typeSuffix = IIndexConstants.TYPE_SUFFIX;
+				break;
+		}
+		final TypeDeclarationPattern pattern = new TypeDeclarationPattern(
+			packageName,
+			null, // do find member types
+			typeName,
+			typeSuffix,
+			matchRule);
+		
+		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, AccessRestriction access) {
+				TypeDeclarationPattern record = (TypeDeclarationPattern)indexRecord;
+				if (record.enclosingTypeNames != IIndexConstants.ONE_ZERO_CHAR  // filter out local and anonymous classes
+						&& !workingCopyPaths.contains(documentPath)) { // filter out working copies
+					if (access != null) {
+						access = access.getViolatedRestriction(CharOperation.concat(record.pkg, record.simpleName, '/'), null);					
+					}
+					switch (record.typeSuffix) {
+						case IIndexConstants.CLASS_SUFFIX :
+							nameRequestor.acceptClass(record.pkg, record.simpleName, record.enclosingTypeNames, documentPath, access);
+							break;
+						case IIndexConstants.INTERFACE_SUFFIX :
+							nameRequestor.acceptInterface(record.pkg, record.simpleName, record.enclosingTypeNames, documentPath, access);
+							break;
+						case IIndexConstants.ENUM_SUFFIX :
+							// TODO (frederic) hack to get enum while getting all type names...
+							nameRequestor.acceptEnum(record.pkg, record.simpleName, record.enclosingTypeNames, documentPath, access);
+							break;
+						case IIndexConstants.ANNOTATION_TYPE_SUFFIX :
+							// TODO (frederic) hack to get annotation while getting all type names...
+							nameRequestor.acceptAnnotation(record.pkg, record.simpleName, record.enclosingTypeNames, documentPath, access);
+							break;
+					}
+				}
+				return true;
+			}
+		};
+	
+		try {
+			if (progressMonitor != null) {
+				progressMonitor.beginTask(Util.bind("engine.searching"), 100); //$NON-NLS-1$
+			}
+			// add type names from indexes
+			indexManager.performConcurrentJob(
+				new PatternSearchJob(
+					pattern, 
+					getDefaultSearchParticipant(), // Java search only
+					scope, 
+					searchRequestor),
+				waitingPolicy,
+				progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100));	
+				
+			// add type names from working copies
+			if (copies != null) {
+				for (int i = 0, length = copies.length; i < length; i++) {
+					ICompilationUnit workingCopy = copies[i];
+					final String path = workingCopy.getPath().toString();
+					if (workingCopy.isConsistent()) {
+						IPackageDeclaration[] packageDeclarations = workingCopy.getPackageDeclarations();
+						char[] packageDeclaration = packageDeclarations.length == 0 ? CharOperation.NO_CHAR : packageDeclarations[0].getElementName().toCharArray();
+						IType[] allTypes = workingCopy.getAllTypes();
+						for (int j = 0, allTypesLength = allTypes.length; j < allTypesLength; j++) {
+							IType type = allTypes[j];
+							IJavaElement parent = type.getParent();
+							char[][] enclosingTypeNames;
+							if (parent instanceof IType) {
+								char[] parentQualifiedName = ((IType)parent).getTypeQualifiedName('.').toCharArray();
+								enclosingTypeNames = CharOperation.splitOn('.', parentQualifiedName);
+							} else {
+								enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
+							}
+							char[] simpleName = type.getElementName().toCharArray();
+							int kind;
+							if (type.isClass()) {
+								kind = IGenericType.CLASS_DECL;
+							} else if (type.isInterface()) {
+								kind = IGenericType.INTERFACE_DECL;
+							} else if (type.isEnum()) {
+								kind = IGenericType.ENUM_DECL;
+							} else /*if (type.isAnnotation())*/ {
+								kind = IGenericType.ANNOTATION_TYPE_DECL;
+							}
+							if (match(typeSuffix, packageName, typeName, matchRule, kind, packageDeclaration, simpleName)) {
+								switch(kind) {
+									case IGenericType.CLASS_DECL:
+										nameRequestor.acceptClass(packageDeclaration, simpleName, enclosingTypeNames, path, null);
+										break;
+									case IGenericType.INTERFACE_DECL:
+										nameRequestor.acceptInterface(packageDeclaration, simpleName, enclosingTypeNames, path, null);
+										break;
+									case IGenericType.ENUM_DECL:
+										// TODO need support
+										break;
+									case IGenericType.ANNOTATION_TYPE_DECL:
+										// TODO need support
+										break;
+								}
+							}
+						}
+					} else {
+						Parser basicParser = getParser();
+						final char[] contents = workingCopy.getBuffer().getCharacters();
+						org.eclipse.jdt.internal.compiler.env.ICompilationUnit unit = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit() {
+							public char[] getContents() {
+								return contents;
+							}
+							public char[] getMainTypeName() {
+								return null;
+							}
+							public char[][] getPackageName() {
+								return null;
+							}
+							public char[] getFileName() {
+								return null;
+							}
+						};
+						CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.compilerOptions.maxProblemsPerUnit);
+						CompilationUnitDeclaration parsedUnit = basicParser.dietParse(unit, compilationUnitResult);
+						if (parsedUnit != null) {
+							final char[] packageDeclaration = parsedUnit.currentPackage == null ? CharOperation.NO_CHAR : CharOperation.concatWith(parsedUnit.currentPackage.getImportName(), '.');
+							class AllTypeDeclarationsVisitor extends ASTVisitor {
+								public boolean visit(TypeDeclaration typeDeclaration, BlockScope blockScope) {
+									return false; // no local/anonymous type
+								}
+								public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope compilationUnitScope) {
+									if (match(typeSuffix, packageName, typeName, matchRule, typeDeclaration.kind(), packageDeclaration, typeDeclaration.name)) {
+										switch(typeDeclaration.kind()) {
+											case IGenericType.CLASS_DECL:
+												nameRequestor.acceptClass(packageDeclaration, typeDeclaration.name, CharOperation.NO_CHAR_CHAR, path, null);
+												break;
+											case IGenericType.INTERFACE_DECL:
+												nameRequestor.acceptInterface(packageDeclaration, typeDeclaration.name, CharOperation.NO_CHAR_CHAR, path, null);
+												break;
+											case IGenericType.ENUM_DECL:
+												// TODO need support
+												break;
+											case IGenericType.ANNOTATION_TYPE_DECL:
+												// TODO need support
+												break;
+										}
+									}
+									return true;
+								}
+								public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope classScope) {
+									if (match(typeSuffix, packageName, typeName, matchRule, memberTypeDeclaration.kind(), packageDeclaration, memberTypeDeclaration.name)) {
+										// compute encloising type names
+										TypeDeclaration enclosing = memberTypeDeclaration.enclosingType;
+										char[][] enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
+										while (enclosing != null) {
+											enclosingTypeNames = CharOperation.arrayConcat(new char[][] {enclosing.name}, enclosingTypeNames);
+											if ((enclosing.bits & ASTNode.IsMemberTypeMASK) != 0) {
+												enclosing = enclosing.enclosingType;
+											} else {
+												enclosing = null;
+											}
+										}
+										// report
+										switch(memberTypeDeclaration.kind()) {
+											case IGenericType.CLASS_DECL:
+												nameRequestor.acceptClass(packageDeclaration, memberTypeDeclaration.name, enclosingTypeNames, path, null);
+												break;
+											case IGenericType.INTERFACE_DECL:
+												nameRequestor.acceptInterface(packageDeclaration, memberTypeDeclaration.name, enclosingTypeNames, path, null);
+												break;
+											case IGenericType.ENUM_DECL:
+												// TODO need support
+												break;
+											case IGenericType.ANNOTATION_TYPE_DECL:
+												// TODO need support
+												break;
+										}
+									}
+									return true;
+								}
+							}
+							parsedUnit.traverse(new AllTypeDeclarationsVisitor(), parsedUnit.scope);
+						}
+					}
+				}
+			}	
+		} finally {
+			if (progressMonitor != null) {
+				progressMonitor.done();
+			}
+		}
+	}
+	
+	public void searchDeclarations(IJavaElement enclosingElement, SearchRequestor requestor, SearchPattern pattern, IProgressMonitor monitor) throws JavaModelException {
+		IJavaSearchScope scope = createJavaSearchScope(new IJavaElement[] {enclosingElement});
+		IResource resource = this.getResource(enclosingElement);
+		try {
+			if (resource instanceof IFile) {
+				try {
+					requestor.beginReporting();
+					if (VERBOSE) {
+						System.out.println("Searching for " + pattern + " in " + resource.getFullPath()); //$NON-NLS-1$//$NON-NLS-2$
+					}
+					SearchParticipant participant = getDefaultSearchParticipant();
+					SearchDocument[] documents = MatchLocator.addWorkingCopies(
+						pattern,
+						new SearchDocument[] {new JavaSearchDocument(enclosingElement.getPath().toString(), participant)},
+						getWorkingCopies(enclosingElement),
+						participant);
+					participant.locateMatches(
+						documents, 
+						pattern, 
+						scope, 
+						requestor, 
+						monitor);
+				} finally {
+					requestor.endReporting();
+				}
+			} else {
+				search(
+					pattern, 
+					new SearchParticipant[] {getDefaultSearchParticipant()}, 
+					scope, 
+					requestor, 
+					monitor);
+			}
+		} catch (CoreException e) {
+			if (e instanceof JavaModelException)
+				throw (JavaModelException) e;
+			throw new JavaModelException(e);
+		}
+	}
+
+	/**
+	 * Searches for all declarations of the fields accessed in the given element.
+	 * The element can be a compilation unit, a source type, or a source method.
+	 * Reports the field declarations using the given requestor.
+	 * <p>
+	 * Consider the following code:
+	 * <code>
+	 * <pre>
+	 *		class A {
+	 *			int field1;
+	 *		}
+	 *		class B extends A {
+	 *			String value;
+	 *		}
+	 *		class X {
+	 *			void test() {
+	 *				B b = new B();
+	 *				System.out.println(b.value + b.field1);
+	 *			};
+	 *		}
+	 * </pre>
+	 * </code>
+	 * then searching for declarations of accessed fields in method 
+	 * <code>X.test()</code> would collect the fields
+	 * <code>B.value</code> and <code>A.field1</code>.
+	 * </p>
+	 *
+	 * @param enclosingElement the method, type, or compilation unit to be searched in
+	 * @param requestor a callback object to which each match is reported
+	 * @param monitor the progress monitor used to report progress
+	 * @exception JavaModelException if the search failed. Reasons include:
+	 *	<ul>
+	 *		<li>the element doesn't exist</li>
+	 *		<li>the classpath is incorrectly set</li>
+	 *	</ul>
+	 * @since 3.0
+	 */	
+	public void searchDeclarationsOfAccessedFields(IJavaElement enclosingElement, SearchRequestor requestor, IProgressMonitor monitor) throws JavaModelException {
+		SearchPattern pattern = new DeclarationOfAccessedFieldsPattern(enclosingElement);
+		searchDeclarations(enclosingElement, requestor, pattern, monitor);
+	}
+	
+	/**
+	 * Searches for all declarations of the types referenced in the given element.
+	 * The element can be a compilation unit, a source type, or a source method.
+	 * Reports the type declarations using the given requestor.
+	 * <p>
+	 * Consider the following code:
+	 * <code>
+	 * <pre>
+	 *		class A {
+	 *		}
+	 *		class B extends A {
+	 *		}
+	 *		interface I {
+	 *		  int VALUE = 0;
+	 *		}
+	 *		class X {
+	 *			void test() {
+	 *				B b = new B();
+	 *				this.foo(b, I.VALUE);
+	 *			};
+	 *		}
+	 * </pre>
+	 * </code>
+	 * then searching for declarations of referenced types in method <code>X.test()</code>
+	 * would collect the class <code>B</code> and the interface <code>I</code>.
+	 * </p>
+	 *
+	 * @param enclosingElement the method, type, or compilation unit to be searched in
+	 * @param requestor a callback object to which each match is reported
+	 * @param monitor the progress monitor used to report progress
+	 * @exception JavaModelException if the search failed. Reasons include:
+	 *	<ul>
+	 *		<li>the element doesn't exist</li>
+	 *		<li>the classpath is incorrectly set</li>
+	 *	</ul>
+	 * @since 3.0
+	 */	
+	public void searchDeclarationsOfReferencedTypes(IJavaElement enclosingElement, SearchRequestor requestor, IProgressMonitor monitor) throws JavaModelException {
+		SearchPattern pattern = new DeclarationOfReferencedTypesPattern(enclosingElement);
+		searchDeclarations(enclosingElement, requestor, pattern, monitor);
+	}
+	
+	/**
+	 * Searches for all declarations of the methods invoked in the given element.
+	 * The element can be a compilation unit, a source type, or a source method.
+	 * Reports the method declarations using the given requestor.
+	 * <p>
+	 * Consider the following code:
+	 * <code>
+	 * <pre>
+	 *		class A {
+	 *			void foo() {};
+	 *			void bar() {};
+	 *		}
+	 *		class B extends A {
+	 *			void foo() {};
+	 *		}
+	 *		class X {
+	 *			void test() {
+	 *				A a = new B();
+	 *				a.foo();
+	 *				B b = (B)a;
+	 *				b.bar();
+	 *			};
+	 *		}
+	 * </pre>
+	 * </code>
+	 * then searching for declarations of sent messages in method 
+	 * <code>X.test()</code> would collect the methods
+	 * <code>A.foo()</code>, <code>B.foo()</code>, and <code>A.bar()</code>.
+	 * </p>
+	 *
+	 * @param enclosingElement the method, type, or compilation unit to be searched in
+	 * @param requestor a callback object to which each match is reported
+	 * @param monitor the progress monitor used to report progress
+	 * @exception JavaModelException if the search failed. Reasons include:
+	 *	<ul>
+	 *		<li>the element doesn't exist</li>
+	 *		<li>the classpath is incorrectly set</li>
+	 *	</ul>
+	 * @since 3.0
+	 */	
+	public void searchDeclarationsOfSentMessages(IJavaElement enclosingElement, SearchRequestor requestor, IProgressMonitor monitor) throws JavaModelException {
+		SearchPattern pattern = new DeclarationOfReferencedMethodsPattern(enclosingElement);
+		searchDeclarations(enclosingElement, requestor, pattern, monitor);
+	}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/SubTypeSearchJob.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/SubTypeSearchJob.java
index 695bef4..c42f911 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/SubTypeSearchJob.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/SubTypeSearchJob.java
@@ -10,8 +10,6 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search;
 
-import java.io.IOException;
-
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.search.*;
 import org.eclipse.jdt.internal.core.index.Index;
@@ -25,24 +23,16 @@
 	super(pattern, participant, scope, requestor);
 }
 public void finished() {
-	try {
-		Object[] values = this.indexes.values;
-		for (int i = 0, l = values.length; i < l; i++)
-			if (values[i] != null)
-				((Index) values[i]).stopQuery();
-	} catch(IOException e) {
-		// ignore
-	} 
+	Object[] values = this.indexes.values;
+	for (int i = 0, l = values.length; i < l; i++)
+		if (values[i] != null)
+			((Index) values[i]).stopQuery();
 }
 public boolean search(Index index, IProgressMonitor progressMonitor) {
 	if (index == null) return COMPLETE;
-	try {
-		if (!indexes.includes(index)) {
-			indexes.add(index);
-			index.startQuery();
-		}
-	} catch (IOException e) {
-		return FAILED;
+	if (!indexes.includes(index)) {
+		indexes.add(index);
+		index.startQuery();
 	}
 	return super.search(index, progressMonitor);
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/TypeNameRequestorWrapper.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/TypeNameRequestorWrapper.java
new file mode 100644
index 0000000..e974789
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/TypeNameRequestorWrapper.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.search;
+
+import org.eclipse.jdt.core.search.ITypeNameRequestor;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+
+/**
+ * Wrapper to link previous ITypeNameRequestor and IRestrictedAccessTypeRequestor interfaces.
+ * This wrapper is used by {@link org.eclipse.jdt.core.search.SearchEngine#searchAllTypeNames(char[],char[],int,int,org.eclipse.jdt.core.search.IJavaSearchScope,ITypeNameRequestor,int,org.eclipse.core.runtime.IProgressMonitor)}
+ * to call {@link SearchBasicEngine#searchAllTypeNames(char[],char[],int,int,org.eclipse.jdt.core.search.IJavaSearchScope,IRestrictedAccessTypeRequestor,int,org.eclipse.core.runtime.IProgressMonitor)}
+ * corresponding method.
+ */
+public class TypeNameRequestorWrapper implements IRestrictedAccessTypeRequestor {
+	ITypeNameRequestor requestor;
+	public TypeNameRequestorWrapper(ITypeNameRequestor requestor) {
+		this.requestor = requestor;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.core.search.IAccessedTypeNameRequestor#acceptAnnotation(char[], char[], char[][], java.lang.String, org.eclipse.jdt.internal.compiler.env.AccessRestriction)
+	 */
+	public void acceptAnnotation (	char[] packageName,
+									char[] simpleTypeName,
+									char[][] enclosingTypeNames,
+									String path,
+									AccessRestriction access) {
+		this.requestor.acceptInterface(packageName, simpleTypeName, enclosingTypeNames, path);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.core.search.IAccessedTypeNameRequestor#acceptClass(char[], char[], char[][], java.lang.String, org.eclipse.jdt.internal.compiler.env.AccessRestriction)
+	 */
+	public void acceptClass (	char[] packageName,
+								char[] simpleTypeName,
+								char[][] enclosingTypeNames,
+								String path,
+								AccessRestriction access) {
+		this.requestor.acceptClass(packageName, simpleTypeName, enclosingTypeNames, path);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.core.search.IAccessedTypeNameRequestor#acceptEnum(char[], char[], char[][], java.lang.String, org.eclipse.jdt.internal.compiler.env.AccessRestriction)
+	 */
+	public void acceptEnum (	char[] packageName,
+								char[] simpleTypeName,
+								char[][] enclosingTypeNames,
+								String path,
+								AccessRestriction access) {
+		this.requestor.acceptClass(packageName, simpleTypeName, enclosingTypeNames, path);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.core.search.IAccessedTypeNameRequestor#acceptInterface(char[], char[], char[][], java.lang.String, org.eclipse.jdt.internal.compiler.env.AccessRestriction)
+	 */
+	public void acceptInterface (	char[] packageName,
+									char[] simpleTypeName,
+									char[][] enclosingTypeNames,
+									String path,
+									AccessRestriction access) {
+		this.requestor.acceptInterface(packageName, simpleTypeName, enclosingTypeNames, path);
+	}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java
index b2bec59..208bb01 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java
@@ -10,8 +10,10 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.indexing;
 
+import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.search.SearchDocument;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.core.search.matching.*;
 
 public abstract class AbstractIndexer implements IIndexConstants {
@@ -21,25 +23,49 @@
 	public AbstractIndexer(SearchDocument document) {
 		this.document = document;
 	}
-	public void addClassDeclaration(int modifiers, char[] packageName,char[] name,  char[][] enclosingTypeNames, char[] superclass, char[][] superinterfaces) {
-		addIndexEntry(TYPE_DECL, TypeDeclarationPattern.createIndexKey(name, packageName, enclosingTypeNames, CLASS_SUFFIX));
-
-		if (superclass != null)
-			addTypeReference(superclass);
+	public void addAnnotationTypeDeclaration(int modifiers, char[] packageName, char[] name, char[][] enclosingTypeNames) {
+		addIndexEntry(TYPE_DECL, TypeDeclarationPattern.createIndexKey(name, packageName, enclosingTypeNames, ANNOTATION_TYPE_SUFFIX));
+		
 		addIndexEntry(
 			SUPER_REF, 
 			SuperTypeReferencePattern.createIndexKey(
-				modifiers, packageName, name, enclosingTypeNames, CLASS_SUFFIX, superclass, CLASS_SUFFIX));
+				modifiers, packageName, name, enclosingTypeNames, null, ANNOTATION_TYPE_SUFFIX, CharOperation.concatWith(TypeConstants.JAVA_LANG_ANNOTATION_ANNOTATION, '.'), ANNOTATION_TYPE_SUFFIX));
+	}	
+	public void addClassDeclaration(
+			int modifiers, 
+			char[] packageName,
+			char[] name, 
+			char[][] enclosingTypeNames, 
+			char[] superclass, 
+			char[][] superinterfaces,
+			char[][] typeParameterSignatures) {
+		addIndexEntry(TYPE_DECL, TypeDeclarationPattern.createIndexKey(name, packageName, enclosingTypeNames, CLASS_SUFFIX));
+
+		if (superclass != null) {
+			superclass = erasure(superclass);
+			addTypeReference(superclass);
+		}
+		addIndexEntry(
+			SUPER_REF, 
+			SuperTypeReferencePattern.createIndexKey(
+				modifiers, packageName, name, enclosingTypeNames, typeParameterSignatures, CLASS_SUFFIX, superclass, CLASS_SUFFIX));
 		if (superinterfaces != null) {
 			for (int i = 0, max = superinterfaces.length; i < max; i++) {
-				addTypeReference(superinterfaces[i]);
+				char[] superinterface = erasure(superinterfaces[i]);
+				addTypeReference(superinterface);
 				addIndexEntry(
 					SUPER_REF,
 					SuperTypeReferencePattern.createIndexKey(
-						modifiers, packageName, name, enclosingTypeNames, CLASS_SUFFIX, superinterfaces[i], INTERFACE_SUFFIX));
+						modifiers, packageName, name, enclosingTypeNames, typeParameterSignatures, CLASS_SUFFIX, superinterface, INTERFACE_SUFFIX));
 			}
 		}
 	}
+	private char[] erasure(char[] typeName) {
+		int genericStart = CharOperation.indexOf(Signature.C_GENERIC_START, typeName);
+		if (genericStart > -1) 
+			typeName = CharOperation.subarray(typeName, 0, genericStart);
+		return typeName;
+	}
 	public void addConstructorDeclaration(char[] typeName, char[][] parameterTypes, char[][] exceptionTypes) {
 		int argCount = parameterTypes == null ? 0 : parameterTypes.length;
 		addIndexEntry(CONSTRUCTOR_DECL, ConstructorPattern.createIndexKey(CharOperation.lastSegment(typeName,'.'), argCount));
@@ -55,6 +81,24 @@
 		addTypeReference(simpleTypeName);
 		addIndexEntry(CONSTRUCTOR_REF, ConstructorPattern.createIndexKey(simpleTypeName, argCount));
 	}
+	public void addEnumDeclaration(int modifiers, char[] packageName, char[] name, char[][] enclosingTypeNames, char[][] superinterfaces) {
+		addIndexEntry(TYPE_DECL, TypeDeclarationPattern.createIndexKey(name, packageName, enclosingTypeNames, ENUM_SUFFIX));
+		
+		addIndexEntry(
+			SUPER_REF, 
+			SuperTypeReferencePattern.createIndexKey(
+				modifiers, packageName, name, enclosingTypeNames, null, ENUM_SUFFIX, CharOperation.concatWith(TypeConstants.JAVA_LANG_ENUM, '.'), CLASS_SUFFIX));
+		if (superinterfaces != null) {
+			for (int i = 0, max = superinterfaces.length; i < max; i++) {
+				char[] superinterface = erasure(superinterfaces[i]);
+				addTypeReference(superinterface);
+				addIndexEntry(
+					SUPER_REF,
+					SuperTypeReferencePattern.createIndexKey(
+						modifiers, packageName, name, enclosingTypeNames, null, ENUM_SUFFIX, superinterface, INTERFACE_SUFFIX));
+			}
+		}
+	}	
 	public void addFieldDeclaration(char[] typeName, char[] fieldName) {
 		addIndexEntry(FIELD_DECL, FieldPattern.createIndexKey(fieldName));
 		addTypeReference(typeName);
@@ -65,16 +109,17 @@
 	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) {
+	public void addInterfaceDeclaration(int modifiers, char[] packageName, char[] name, char[][] enclosingTypeNames, char[][] superinterfaces, char[][] typeParameterSignatures) {
 		addIndexEntry(TYPE_DECL, TypeDeclarationPattern.createIndexKey(name, packageName, enclosingTypeNames, INTERFACE_SUFFIX));
 
 		if (superinterfaces != null) {
 			for (int i = 0, max = superinterfaces.length; i < max; i++) {
-				addTypeReference(superinterfaces[i]);
+				char[] superinterface = erasure(superinterfaces[i]);
+				addTypeReference(superinterface);
 				addIndexEntry(
 					SUPER_REF,
 					SuperTypeReferencePattern.createIndexKey(
-						modifiers, packageName, name, enclosingTypeNames, INTERFACE_SUFFIX, superinterfaces[i], INTERFACE_SUFFIX));
+						modifiers, packageName, name, enclosingTypeNames, typeParameterSignatures, INTERFACE_SUFFIX, superinterface, INTERFACE_SUFFIX));
 			}
 		}
 	}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddFolderToIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddFolderToIndex.java
index 4df92c9..bc74e7e 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddFolderToIndex.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddFolderToIndex.java
@@ -58,7 +58,7 @@
 					new IResourceProxyVisitor() {
 						public boolean visit(IResourceProxy proxy) /* throws CoreException */{
 							if (proxy.getType() == IResource.FILE) {
-								if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(proxy.getName()))
+								if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(proxy.getName()))
 									indexManager.addSource((IFile) proxy.requestResource(), container);
 								return false;
 							}
@@ -73,7 +73,7 @@
 						public boolean visit(IResourceProxy proxy) /* throws CoreException */{
 							switch(proxy.getType()) {
 								case IResource.FILE :
-									if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(proxy.getName())) {
+									if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(proxy.getName())) {
 										IResource resource = proxy.requestResource();
 										if (!Util.isExcluded(resource, inclusionPatterns, exclusionPatterns))
 											indexManager.addSource((IFile)resource, container);
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java
index e263d9e..062691a 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java
@@ -21,12 +21,12 @@
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jdt.core.search.SearchEngine;
 import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.compiler.util.Util;
 import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.index.Index;
 import org.eclipse.jdt.internal.core.search.JavaSearchDocument;
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
-import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
 
 class AddJarFileToIndex extends IndexRequest {
 	IFile resource;
@@ -158,6 +158,12 @@
 				// index already existed: recreate it so that we forget about previous entries
 				SearchParticipant participant = SearchEngine.getDefaultSearchParticipant();
 				index = manager.recreateIndex(this.containerPath);
+				if (index == null) {
+					// failed to recreate index, see 73330
+					manager.removeIndex(this.containerPath);
+					return false;
+				}
+
 				for (Enumeration e = zip.entries(); e.hasMoreElements();) {
 					if (this.isCancelled) {
 						if (JobManager.VERBOSE)
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/BinaryIndexer.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/BinaryIndexer.java
index 114402c..a751b69 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/BinaryIndexer.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/BinaryIndexer.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.indexing;
 
+import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.search.SearchDocument;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -17,6 +18,7 @@
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
 import org.eclipse.jdt.internal.compiler.classfmt.FieldInfo;
 import org.eclipse.jdt.internal.compiler.classfmt.MethodInfo;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 
 public class BinaryIndexer extends AbstractIndexer implements SuffixConstants {
@@ -54,11 +56,9 @@
 
 	 	// consider that A$B is a member type: so replace '$' with '.'
 	 	// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=40116)
-		if (CharOperation.indexOf('$', typeName) > 0) {
-			System.arraycopy(typeName, 0, typeName = new char[length], 0, length); // copy it so the original is not modified
-			CharOperation.replace(typeName, '$', '.');
-		}
-	 	super.addTypeReference(typeName);
+		typeName = CharOperation.replaceOnCopy(typeName, '$', '.'); // copy it so the original is not modified
+
+		super.addTypeReference(typeName);
 	}
 	/**
 	 * For example:
@@ -475,17 +475,34 @@
 					System.arraycopy(fullEnclosingName, packageNameIndex + 1, enclosingTypeName, 0, nameLength);
 				}
 			}
+			// type parameters
+			char[][] typeParameterSignatures = null;
+			char[] genericSignature = reader.getGenericSignature();
+			if (genericSignature != null) {
+				CharOperation.replace(genericSignature, '/', '.');
+				typeParameterSignatures = Signature.getTypeParameters(genericSignature);
+			}
+			
 			// eliminate invalid innerclasses (1G4KCF7)
 			if (name == null) return;
 			
 			char[][] superinterfaces = replace('/', '.', reader.getInterfaceNames());
 			char[][] enclosingTypeNames = enclosingTypeName == null ? null : new char[][] {enclosingTypeName};
-			if (reader.isInterface()) {
-				addInterfaceDeclaration(reader.getModifiers(), packageName, name, enclosingTypeNames, superinterfaces);
-			} else {
-				char[] superclass = replace('/', '.', reader.getSuperclassName());
-				addClassDeclaration(reader.getModifiers(), packageName, name, enclosingTypeNames, superclass, superinterfaces);
-			}
+			switch (reader.getKind()) {
+				case IGenericType.CLASS_DECL :
+					char[] superclass = replace('/', '.', reader.getSuperclassName());
+					addClassDeclaration(reader.getModifiers(), packageName, name, enclosingTypeNames, superclass, superinterfaces, typeParameterSignatures);
+					break;
+				case IGenericType.INTERFACE_DECL :
+					addInterfaceDeclaration(reader.getModifiers(), packageName, name, enclosingTypeNames, superinterfaces, typeParameterSignatures);
+					break;
+				case IGenericType.ENUM_DECL :
+					addEnumDeclaration(reader.getModifiers(), packageName, name, enclosingTypeNames, superinterfaces);
+					break;
+				case IGenericType.ANNOTATION_TYPE_DECL :
+					addAnnotationTypeDeclaration(reader.getModifiers(), packageName, name, enclosingTypeNames);
+					break;
+			}			
 	
 			// first reference all methods declarations and field declarations
 			MethodInfo[] methods = (MethodInfo[]) reader.getMethods();
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IIndexConstants.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IIndexConstants.java
index 4903047..c455329 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IIndexConstants.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IIndexConstants.java
@@ -28,6 +28,8 @@
 	};
 	char CLASS_SUFFIX = 'C';
 	char INTERFACE_SUFFIX = 'I';
+	char ENUM_SUFFIX = 'E';
+	char ANNOTATION_TYPE_SUFFIX = 'A';
 	char TYPE_SUFFIX = 0;
 	char SEPARATOR= '/';
 
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java
index 0c38803..f38c525 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java
@@ -24,11 +24,11 @@
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.core.ClasspathEntry;
 import org.eclipse.jdt.internal.core.JavaProject;
 import org.eclipse.jdt.internal.core.index.Index;
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
-import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.core.util.Util;
 
 public class IndexAllProject extends IndexRequest {
@@ -105,7 +105,7 @@
 										if (isCancelled) return false;
 										switch(proxy.getType()) {
 											case IResource.FILE :
-												if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(proxy.getName())) {
+												if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(proxy.getName())) {
 													IFile file = (IFile) proxy.requestResource();
 													if (file.getLocation() == null) return false;
 													if (exclusionPatterns != null || inclusionPatterns != null)
@@ -135,7 +135,7 @@
 										if (isCancelled) return false;
 										switch(proxy.getType()) {
 											case IResource.FILE :
-												if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(proxy.getName())) {
+												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;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java
index a110150..3085cc3 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java
@@ -20,9 +20,9 @@
 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;
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
-import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.core.util.Util;
 
 public class IndexBinaryFolder extends IndexRequest {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
index 5820b8d..30b05fa 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
@@ -21,13 +21,13 @@
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.search.*;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.index.Index;
 import org.eclipse.jdt.internal.core.search.JavaWorkspaceScope;
 import org.eclipse.jdt.internal.core.search.PatternSearchJob;
 import org.eclipse.jdt.internal.core.search.processing.IJob;
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
-import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.core.util.Util;
 
 public class IndexManager extends JobManager implements IIndexConstants {
@@ -244,10 +244,31 @@
 	char[] savedIndexNames = readIndexState();
 	if (savedIndexNames.length > 0) {
 		char[][] names = CharOperation.splitOn('\n', savedIndexNames);
-		for (int i = 0, l = names.length; i < l; i++) {
-			char[] name = names[i];
-			if (name.length > 0)
-				this.indexStates.put(new String(name), SAVED_STATE);
+		if (names.length > 0) {
+			// check to see if workspace has moved, if so then do not trust saved indexes
+			File indexesDirectory = new File(getJavaPluginWorkingLocation().toOSString());
+			char[] dirName = indexesDirectory.getAbsolutePath().toCharArray();
+			int delimiterPos = dirName.length;
+			if (CharOperation.match(names[0], 0, delimiterPos, dirName, 0, delimiterPos, true)) {
+				for (int i = 0, l = names.length; i < l; i++) {
+					char[] name = names[i];
+					if (name.length > 0)
+						this.indexStates.put(new String(name), SAVED_STATE);
+				}
+			} else {
+				savedIndexNamesFile.delete(); // forget saved indexes & delete each index file
+				File[] files = indexesDirectory.listFiles();
+				if (files != null) {
+					for (int i = 0, l = files.length; i < l; i++) {
+						String fileName = files[i].getAbsolutePath();
+						if (fileName.toLowerCase().endsWith(".index")) { //$NON-NLS-1$
+							if (VERBOSE)
+								Util.verbose("Deleting index file " + files[i]); //$NON-NLS-1$
+							files[i].delete();
+						}
+					}
+				}
+			}
 		}
 	}
 	return this.indexStates;
@@ -256,14 +277,9 @@
 	if (this.javaPluginLocation != null) return this.javaPluginLocation;
 
 	IPath stateLocation = JavaCore.getPlugin().getStateLocation();
-	
-	// TODO (jerome) workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=62267
-	String device = stateLocation.getDevice();
-	if (device != null && device.charAt(0) == '/') stateLocation = stateLocation.setDevice(device.substring(1));
-	
 	return this.javaPluginLocation = stateLocation;
 }
-public void indexDocument(SearchDocument searchDocument, SearchParticipant searchParticipant, Index index, IPath indexLocation) throws IOException {
+public void indexDocument(SearchDocument searchDocument, SearchParticipant searchParticipant, Index index, IPath indexLocation) {
 	try {
 		((InternalSearchDocument) searchDocument).index = index;
 		searchParticipant.indexDocument(searchDocument, indexLocation);
@@ -297,9 +313,8 @@
 
 	// check if the same request is not already in the queue
 	IndexRequest request = new IndexAllProject(project, this);
-	for (int i = this.jobEnd; i > this.jobStart; i--) // NB: don't check job at jobStart, as it may have already started (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32488)
-		if (request.equals(this.awaitingJobs[i])) return;
-	this.request(request);
+	if (!isJobWaiting(request))
+		this.request(request);
 }
 /**
  * Trigger addition of a library to an index
@@ -326,9 +341,8 @@
 	}
 
 	// check if the same request is not already in the queue
-	for (int i = this.jobEnd; i > this.jobStart; i--)  // NB: don't check job at jobStart, as it may have already started (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32488)
-		if (request.equals(this.awaitingJobs[i])) return;
-	this.request(request);
+	if (!isJobWaiting(request))
+		this.request(request);
 }
 /**
  * Index the content of the given source folder.
@@ -336,10 +350,9 @@
 public void indexSourceFolder(JavaProject javaProject, IPath sourceFolder, char[][] inclusionPatterns, char[][] exclusionPatterns) {
 	IProject project = javaProject.getProject();
 	if (this.jobEnd > this.jobStart) {
-		// check if a job to index the project is not already in the queue
+		// skip it if a job to index the project is already in the queue
 		IndexRequest request = new IndexAllProject(project, this);
-		for (int i = this.jobEnd; i > this.jobStart; i--) // NB: don't check job at jobStart, as it may have already started (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32488)
-			if (request.equals(this.awaitingJobs[i])) return;
+		if (isJobWaiting(request)) return;
 	}
 
 	this.request(new AddFolderToIndex(sourceFolder, project, inclusionPatterns, exclusionPatterns, this));
@@ -478,10 +491,9 @@
 public void removeSourceFolderFromIndex(JavaProject javaProject, IPath sourceFolder, char[][] inclusionPatterns, char[][] exclusionPatterns) {
 	IProject project = javaProject.getProject();
 	if (this.jobEnd > this.jobStart) {
-		// check if a job to index the project is not already in the queue
+		// skip it if a job to index the project is already in the queue
 		IndexRequest request = new IndexAllProject(project, this);
-		for (int i = this.jobEnd; i > this.jobStart; i--) // NB: don't check job at jobStart, as it may have already started (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32488)
-			if (request.equals(this.awaitingJobs[i])) return;
+		if (isJobWaiting(request)) return;
 	}
 
 	this.request(new RemoveFolderFromIndex(sourceFolder, inclusionPatterns, exclusionPatterns, project, this));
@@ -510,10 +522,12 @@
 	if (this.jobEnd > this.jobStart) {
 		Object containerPath = this.indexLocations.keyForValue(indexLocation);
 		if (containerPath != null) {
-			for (int i = this.jobEnd; i > this.jobStart; i--) { // skip the current job
-				IJob job = this.awaitingJobs[i];
-				if (job instanceof IndexRequest)
-					if (((IndexRequest) job).containerPath.equals(containerPath)) return;
+			synchronized(this) {
+				for (int i = this.jobEnd; i > this.jobStart; i--) { // skip the current job
+					IJob job = this.awaitingJobs[i];
+					if (job instanceof IndexRequest)
+						if (((IndexRequest) job).containerPath.equals(containerPath)) return;
+				}
 			}
 		}
 	}
@@ -565,13 +579,13 @@
 	}
 	this.needToSave = !allSaved;
 }
-public void scheduleDocumentIndexing(final SearchDocument searchDocument, IPath containerPath, final String indexLocation, final SearchParticipant searchParticipant) {
-	request(new IndexRequest(containerPath, this) {
+public void scheduleDocumentIndexing(final SearchDocument searchDocument, IPath container, final String indexLocation, final SearchParticipant searchParticipant) {
+	request(new IndexRequest(container, this) {
 		public boolean execute(IProgressMonitor progressMonitor) {
 			if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
 			
 			/* ensure no concurrent write access to index */
-			Index index = getIndex(containerPath, indexLocation, true, /*reuse index file*/ true /*create if none*/);
+			Index index = getIndex(this.containerPath, indexLocation, true, /*reuse index file*/ true /*create if none*/);
 			if (index == null) return true;
 			ReadWriteMonitor monitor = index.monitor;
 			if (monitor == null) return true; // index got deleted since acquired
@@ -579,12 +593,6 @@
 			try {
 				monitor.enterWrite(); // ask permission to write
 				indexDocument(searchDocument, searchParticipant, index, new Path(indexLocation));
-			} catch (IOException e) {
-				if (JobManager.VERBOSE) {
-					Util.verbose("-> failed to index " + searchDocument.getPath() + " because of the following exception:", System.err); //$NON-NLS-1$ //$NON-NLS-2$
-					e.printStackTrace();
-				}
-				return false;
 			} finally {
 				monitor.exitWrite(); // free write lock
 			}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java
index b6773b9..58f5911 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java
@@ -10,9 +10,11 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.indexing;
 
+import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.ISourceElementRequestor;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
 
 /**
@@ -126,21 +128,29 @@
 	System.arraycopy(this.enclosingTypeNames, 0, qualification, 0, this.depth);
 	return qualification;
 }
-/**
- * @see ISourceElementRequestor#enterClass(int, int, char[], int, int, char[], char[][])
- */
-public void enterClass(int declarationStart, int modifiers, char[] name, int nameSourceStart, int nameSourceEnd, char[] superclass, char[][] superinterfaces) {
+private void enterAnnotationType(TypeInfo typeInfo) {
+	char[][] typeNames;
+	if (this.methodDepth > 0) {
+		typeNames = ONE_ZERO_CHAR;
+	} else {
+		typeNames = this.enclosingTypeNames();
+	}
+	this.indexer.addAnnotationTypeDeclaration(typeInfo.modifiers, packageName, typeInfo.name, typeNames);
+	this.pushTypeName(typeInfo.name);	
+}
+
+private void enterClass(TypeInfo typeInfo) {
 
 	// eliminate possible qualifications, given they need to be fully resolved again
-	if (superclass != null){
-		superclass = CharOperation.lastSegment(superclass, '.');
+	if (typeInfo.superclass != null){
+		typeInfo.superclass = CharOperation.lastSegment(typeInfo.superclass, '.');
 		
 		// add implicit constructor reference to default constructor
-		this.indexer.addConstructorReference(superclass, 0);
+		this.indexer.addConstructorReference(typeInfo.superclass, 0);
 	}
-	if (superinterfaces != null){
-		for (int i = 0, length = superinterfaces.length; i < length; i++){
-			superinterfaces[i] = CharOperation.lastSegment(superinterfaces[i], '.');
+	if (typeInfo.superinterfaces != null){
+		for (int i = 0, length = typeInfo.superinterfaces.length; i < length; i++){
+			typeInfo.superinterfaces[i] = CharOperation.lastSegment(typeInfo.superinterfaces[i], '.');
 		}
 	}
 	char[][] typeNames;
@@ -149,8 +159,17 @@
 	} else {
 		typeNames = this.enclosingTypeNames();
 	}
-	this.indexer.addClassDeclaration(modifiers, this.packageName, name, typeNames, superclass, superinterfaces);
-	this.pushTypeName(name);
+	char[][] typeParameterSignatures = null;
+	if (typeInfo.typeParameters != null) {
+		int typeParametersLength = typeInfo.typeParameters.length;
+		typeParameterSignatures = new char[typeParametersLength][];
+		for (int i = 0; i < typeParametersLength; i++) {
+			ISourceElementRequestor.TypeParameterInfo typeParameterInfo = typeInfo.typeParameters[i];
+			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.pushTypeName(typeInfo.name);
 }
 /**
  * @see ISourceElementRequestor#enterCompilationUnit()
@@ -159,33 +178,17 @@
 	// implements interface method
 }
 /**
- * @see ISourceElementRequestor#enterConstructor(int, int, char[], int, int, char[][], char[][], char[][])
+ * @see ISourceElementRequestor#enterConstructor(MethodInfo)
  */
-public void enterConstructor(int declarationStart, int modifiers, char[] name, int nameSourceStart, int nameSourceEnd, char[][] parameterTypes, char[][] parameterNames, char[][] exceptionTypes) {
-	this.indexer.addConstructorDeclaration(name, parameterTypes, exceptionTypes);
+public void enterConstructor(MethodInfo methodInfo) {
+	this.indexer.addConstructorDeclaration(methodInfo.name, methodInfo.parameterTypes, methodInfo.exceptionTypes);
 	this.methodDepth++;
 }
-/**
- * @see ISourceElementRequestor#enterField(int, int, char[], char[], int, int)
- */
-public void enterField(int declarationStart, int modifiers, char[] type, char[] name, int nameSourceStart, int nameSourceEnd) {
-	this.indexer.addFieldDeclaration(type, name);
-	this.methodDepth++;
-}
-/**
- * @see ISourceElementRequestor#enterInitializer(int, int)
- */
-public void enterInitializer(int declarationSourceStart, int modifiers) {
-	this.methodDepth++;
-}
-/**
- * @see ISourceElementRequestor#enterInterface(int, int, char[], int, int, char[][])
- */
-public void enterInterface(int declarationStart, int modifiers, char[] name, int nameSourceStart, int nameSourceEnd, char[][] superinterfaces) {
+private void enterEnum(TypeInfo typeInfo) {
 	// eliminate possible qualifications, given they need to be fully resolved again
-	if (superinterfaces != null){
-		for (int i = 0, length = superinterfaces.length; i < length; i++){
-			superinterfaces[i] = CharOperation.lastSegment(superinterfaces[i], '.');
+	if (typeInfo.superinterfaces != null){
+		for (int i = 0, length = typeInfo.superinterfaces.length; i < length; i++){
+			typeInfo.superinterfaces[i] = CharOperation.lastSegment(typeInfo.superinterfaces[i], '.');
 		}
 	}	
 	char[][] typeNames;
@@ -194,22 +197,75 @@
 	} else {
 		typeNames = this.enclosingTypeNames();
 	}
-	this.indexer.addInterfaceDeclaration(modifiers, packageName, name, typeNames, superinterfaces);
-	this.pushTypeName(name);	
+	this.indexer.addEnumDeclaration(typeInfo.modifiers, packageName, typeInfo.name, typeNames, typeInfo.superinterfaces);
+	this.pushTypeName(typeInfo.name);	
 }
 /**
- * @see ISourceElementRequestor#enterMethod(int, int, char[], char[], int, int, char[][], char[][], char[][])
+ * @see ISourceElementRequestor#enterField(FieldInfo)
  */
-public void enterMethod(int declarationStart, int modifiers, char[] returnType, char[] name, int nameSourceStart, int nameSourceEnd, char[][] parameterTypes, char[][] parameterNames, char[][] exceptionTypes) {
-	this.indexer.addMethodDeclaration(name, parameterTypes, returnType, exceptionTypes);
+public void enterField(FieldInfo fieldInfo) {
+	this.indexer.addFieldDeclaration(fieldInfo.type, fieldInfo.name);
 	this.methodDepth++;
 }
 /**
- * @see ISourceElementRequestor#exitClass(int)
+ * @see ISourceElementRequestor#enterInitializer(int, int)
  */
-public void exitClass(int declarationEnd) {
-	popTypeName();
+public void enterInitializer(int declarationSourceStart, int modifiers) {
+	this.methodDepth++;
 }
+private void enterInterface(TypeInfo typeInfo) {
+	// eliminate possible qualifications, given they need to be fully resolved again
+	if (typeInfo.superinterfaces != null){
+		for (int i = 0, length = typeInfo.superinterfaces.length; i < length; i++){
+			typeInfo.superinterfaces[i] = CharOperation.lastSegment(typeInfo.superinterfaces[i], '.');
+		}
+	}	
+	char[][] typeNames;
+	if (this.methodDepth > 0) {
+		typeNames = ONE_ZERO_CHAR;
+	} else {
+		typeNames = this.enclosingTypeNames();
+	}
+	char[][] typeParameterSignatures = null;
+	if (typeInfo.typeParameters != null) {
+		int typeParametersLength = typeInfo.typeParameters.length;
+		typeParameterSignatures = new char[typeParametersLength][];
+		for (int i = 0; i < typeParametersLength; i++) {
+			ISourceElementRequestor.TypeParameterInfo typeParameterInfo = typeInfo.typeParameters[i];
+			typeParameterSignatures[i] = Signature.createTypeParameterSignature(typeParameterInfo.name, typeParameterInfo.bounds);
+		}
+	}
+	this.indexer.addInterfaceDeclaration(typeInfo.modifiers, packageName, typeInfo.name, typeNames, typeInfo.superinterfaces, typeParameterSignatures);
+	this.pushTypeName(typeInfo.name);	
+}
+/**
+ * @see ISourceElementRequestor#enterMethod(MethodInfo)
+ */
+public void enterMethod(MethodInfo methodInfo) {
+	this.indexer.addMethodDeclaration(methodInfo.name, methodInfo.parameterTypes, methodInfo.returnType, methodInfo.exceptionTypes);
+	this.methodDepth++;
+}
+/**
+ * @see ISourceElementRequestor#enterType(TypeInfo)
+ */
+public void enterType(TypeInfo typeInfo) {
+	// TODO (jerome) might want to merge the 4 methods
+	switch (typeInfo.kind) {
+		case IGenericType.CLASS_DECL:
+			enterClass(typeInfo);
+			break;
+		case IGenericType.ANNOTATION_TYPE_DECL: 
+			enterAnnotationType(typeInfo);
+			break;
+		case IGenericType.INTERFACE_DECL:
+			enterInterface(typeInfo);
+			break;
+		case IGenericType.ENUM_DECL: 
+			enterEnum(typeInfo);
+			break;
+	}
+}
+
 /**
  * @see ISourceElementRequestor#exitCompilationUnit(int)
  */
@@ -235,16 +291,16 @@
 	this.methodDepth--;
 }
 /**
- * @see ISourceElementRequestor#exitInterface(int)
+ * @see ISourceElementRequestor#exitMethod(int, int, int)
  */
-public void exitInterface(int declarationEnd) {
-	popTypeName();	
+public void exitMethod(int declarationEnd, int defaultValueStart, int defaultValueEnd) {
+	this.methodDepth--;
 }
 /**
- * @see ISourceElementRequestor#exitMethod(int)
+ * @see ISourceElementRequestor#exitType(int)
  */
-public void exitMethod(int declarationEnd) {
-	this.methodDepth--;
+public void exitType(int declarationEnd) {
+	popTypeName();
 }
 public void popTypeName() {
 	if (depth > 0) {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java
index f837a92..84390bb 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java
@@ -23,14 +23,7 @@
 public class ClassFileMatchLocator implements IIndexConstants {
 
 public static char[] convertClassFileFormat(char[] name) {
-	for (int i = 0, l = name.length; i < l; i++) {
-		if (name[i] == '/') {
-			char[] newName = (char[]) name.clone();
-			CharOperation.replace(newName, '/', '.');
-			return newName;
-		}
-	}
-	return name;
+	return CharOperation.replaceOnCopy(name, '/', '.');
 }
 
 boolean checkDeclaringType(IBinaryType enclosingBinaryType, char[] simpleName, char[] qualification, boolean isCaseSensitive) {
@@ -68,7 +61,7 @@
 	int accuracy = SearchMatch.A_ACCURATE;
 	if (((InternalSearchPattern)pattern).mustResolve) {
 		try {
-			BinaryTypeBinding binding = locator.cacheBinaryType(binaryType);
+			BinaryTypeBinding binding = locator.cacheBinaryType(binaryType, info);
 			if (binding != null) {
 				// filter out element not in hierarchy scope
 				if (!locator.typeInHierarchy(binding)) return;
@@ -107,8 +100,18 @@
 		for (int i = 0, l = methods.length; i < l; i++) {
 			IBinaryMethod method = methods[i];
 			if (matchBinary(pattern, method, info)) {
+				char[] name;
+				if (method.isConstructor()) {
+					name = info.getName();
+					int lastSlash = CharOperation.lastIndexOf('/', name);
+					if (lastSlash != -1) {
+						name = CharOperation.subarray(name, lastSlash+1, name.length);
+					}
+				} else {
+					name = method.getSelector();
+				}
 				IMethod methodHandle = binaryType.getMethod(
-					new String(method.isConstructor() ? info.getName() : method.getSelector()),
+					new String(name),
 					CharOperation.toStrings(Signature.getParameterTypes(convertClassFileFormat(method.getMethodDescriptor()))));
 				locator.reportBinaryMemberDeclaration(null, methodHandle, info, accuracy);
 			}
@@ -238,11 +241,15 @@
 		if (!checkTypeName(pattern.simpleName, patternString, fullyQualifiedTypeName, pattern.isCaseSensitive())) return false;
 	}
 
-	switch (pattern.classOrInterface) {
+	switch (pattern.typeSuffix) {
 		case CLASS_SUFFIX:
-			return !type.isInterface();
+			return type.getKind() == IGenericType.CLASS_DECL;
 		case INTERFACE_SUFFIX:
-			return type.isInterface();
+			return type.getKind() == IGenericType.INTERFACE_DECL;
+		case ENUM_SUFFIX:
+			return type.getKind() == IGenericType.ENUM_DECL;
+		case ANNOTATION_TYPE_SUFFIX:
+			return type.getKind() == IGenericType.ANNOTATION_TYPE_DECL;
 		case TYPE_SUFFIX: // nothing
 	}
 	return true;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClasspathSourceDirectory.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClasspathSourceDirectory.java
index 0b286d6..cf5e38b 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClasspathSourceDirectory.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClasspathSourceDirectory.java
@@ -18,8 +18,9 @@
 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.SimpleLookupTable;
+import org.eclipse.jdt.internal.core.util.Util;
 
 public class ClasspathSourceDirectory extends ClasspathLocation {
 
@@ -28,8 +29,10 @@
 	String encoding;
 	SimpleLookupTable directoryCache;
 	String[] missingPackageHolder = new String[1];
+	char[][] fullExclusionPatternChars;
+	char[][] fulInclusionPatternChars;
 
-ClasspathSourceDirectory(IContainer sourceFolder) {
+ClasspathSourceDirectory(IContainer sourceFolder, char[][] fullExclusionPatternChars, char[][] fulInclusionPatternChars) {
 	this.sourceFolder = sourceFolder;
 	IPath location = sourceFolder.getLocation();
 	this.sourceLocation = location != null ? location.addTrailingSeparator().toString() : ""; //$NON-NLS-1$
@@ -41,6 +44,8 @@
 		// let use no encoding by default
 	}
 	this.directoryCache = new SimpleLookupTable(5);
+	this.fullExclusionPatternChars = fullExclusionPatternChars;
+	this.fulInclusionPatternChars = fulInclusionPatternChars;
 }
 
 public void cleanup() {
@@ -61,7 +66,7 @@
 			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.compiler.util.Util.isJavaFileName(name = m.getName()))
+				if (m.getType() == IResource.FILE && org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(name = m.getName()))
 					dirList[index++] = name;
 			}
 			if (index < dirList.length)
@@ -93,20 +98,30 @@
 	return sourceFolder.equals(((ClasspathSourceDirectory) o).sourceFolder);
 } 
 
-public NameEnvironmentAnswer findClass(String sourceFileName, String qualifiedPackageName, String qualifiedSourceFileName) {
-	if (!doesFileExist(sourceFileName, qualifiedPackageName)) return null; // most common case
-
-	String fullSourcePath = this.sourceLocation + qualifiedSourceFileName;
-	IPath path = new Path(qualifiedSourceFileName);
-	IFile file = this.sourceFolder.getFile(path);
-	String fileEncoding = this.encoding;
-	try {
-		fileEncoding = file.getCharset();
+public NameEnvironmentAnswer findClass(String sourceFileWithoutExtension, String qualifiedPackageName, String qualifiedSourceFileWithoutExtension) {
+	
+	String sourceFolderPath = this.sourceFolder.getFullPath().toString() + IPath.SEPARATOR;
+	for (int i = 0, length = Util.JAVA_LIKE_EXTENSIONS.length; i < length; i++) {
+		String extension = new String(Util.JAVA_LIKE_EXTENSIONS[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();
+		}
+		catch (CoreException ce) {
+			// let use default encoding
+		}
+		return new NameEnvironmentAnswer(new CompilationUnit(null, fullSourcePath, fileEncoding), null /* no access restriction */);
 	}
-	catch (CoreException ce) {
-		// let use default encoding
-	}
-	return new NameEnvironmentAnswer(new CompilationUnit(null, fullSourcePath, fileEncoding));
+	return null;
 }
 
 public IPath getProjectRelativePath() {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java
index 96b266e..67efa1b 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.core.search.matching;
 
 import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.search.SearchMatch;
 import org.eclipse.jdt.internal.compiler.ast.*;
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
@@ -62,7 +63,26 @@
 
 	return nodeSet.addMatch(node, ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
 }
-//public int match(FieldDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+public int match(FieldDeclaration field, MatchingNodeSet nodeSet) {
+	if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH;
+	// look only for enum constant
+	if (field.type != null || !(field.initialization instanceof AllocationExpression)) return IMPOSSIBLE_MATCH;
+
+	AllocationExpression allocation = (AllocationExpression) field.initialization;
+	if (field.binding != null && field.binding.declaringClass != null) {
+		if (this.pattern.declaringSimpleName != null && !matchesName(this.pattern.declaringSimpleName, field.binding.declaringClass.sourceName()))
+			return IMPOSSIBLE_MATCH;
+	}
+
+	if (this.pattern.parameterSimpleNames != null) {
+		int length = this.pattern.parameterSimpleNames.length;
+		Expression[] args = allocation.arguments;
+		int argsLength = args == null ? 0 : args.length;
+		if (length != argsLength) return IMPOSSIBLE_MATCH;
+	}
+
+	return nodeSet.addMatch(field, ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
+}
 //public int match(MethodDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
 //public int match(MessageSend node, MatchingNodeSet nodeSet) - SKIP IT
 //public int match(Reference node, MatchingNodeSet nodeSet) - SKIP IT
@@ -115,6 +135,33 @@
 
 	return ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
 }
+public SearchMatch newDeclarationMatch(ASTNode reference, IJavaElement element, int accuracy, int length, MatchLocator locator) {
+	SearchMatch match = null;
+	int offset = reference.sourceStart;
+	if (this.pattern.findReferences) {
+		if (reference instanceof TypeDeclaration) {
+			TypeDeclaration type = (TypeDeclaration) reference;
+			AbstractMethodDeclaration[] methods = type.methods;
+			if (methods != null) {
+				for (int i = 0, max = methods.length; i < max; i++) {
+					AbstractMethodDeclaration method = methods[i];
+					boolean synthetic = method.isDefaultConstructor() && method.sourceStart < type.bodyStart;
+					match = locator.newMethodReferenceMatch(element, accuracy, offset, length, method.isConstructor(), synthetic, method);
+				}
+			}
+		} else if (reference instanceof ConstructorDeclaration) {
+			ConstructorDeclaration constructor = (ConstructorDeclaration) reference;
+			ExplicitConstructorCall call = constructor.constructorCall;
+			boolean synthetic = call != null && call.isImplicitSuper();
+			match = locator.newMethodReferenceMatch(element, accuracy, offset, length, constructor.isConstructor(), synthetic, constructor);
+		}
+	}
+	if (match != null) {
+		return match;
+	}
+	// super implementation...
+    return locator.newDeclarationMatch(element, accuracy, reference.sourceStart, length);
+}
 public int resolveLevel(ASTNode node) {
 	if (this.pattern.findReferences) {
 		if (node instanceof AllocationExpression)
@@ -123,6 +170,8 @@
 			return resolveLevel(((ExplicitConstructorCall) node).binding);
 		if (node instanceof TypeDeclaration)
 			return resolveLevel((TypeDeclaration) node);
+		if (node instanceof FieldDeclaration)
+			return resolveLevel((FieldDeclaration) node);
 	}
 	if (node instanceof ConstructorDeclaration)
 		return resolveLevel((ConstructorDeclaration) node, true);
@@ -139,11 +188,20 @@
 
 	return resolveLevel(allocation.binding);
 }
+protected int resolveLevel(FieldDeclaration field) {
+	// only accept enum constants
+	if (field.type != null || field.binding == null) return IMPOSSIBLE_MATCH;
+	if (this.pattern.declaringSimpleName != null && !matchesName(this.pattern.declaringSimpleName, field.binding.type.sourceName()))
+		return IMPOSSIBLE_MATCH;
+	if (!(field.initialization instanceof AllocationExpression) || field.initialization.resolvedType.isLocalType()) return IMPOSSIBLE_MATCH;
+
+	return resolveLevel(((AllocationExpression)field.initialization).binding);
+}
 public int resolveLevel(Binding binding) {
 	if (binding == null) return INACCURATE_MATCH;
 	if (!(binding instanceof MethodBinding)) return IMPOSSIBLE_MATCH;
 
-	MethodBinding method = (MethodBinding) binding;
+	MethodBinding method = ((MethodBinding) binding).original();
 	if (!method.isConstructor()) return IMPOSSIBLE_MATCH;
 
 	// declaring type, simple name has already been matched by matchIndexEntry()
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorPattern.java
index efce874..5d8f5c8 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorPattern.java
@@ -28,6 +28,7 @@
 public char[][] parameterQualifications;
 public char[][] parameterSimpleNames;
 public int parameterCount;
+public boolean varargs;
 
 protected static char[][] REF_CATEGORIES = { CONSTRUCTOR_REF };
 protected static char[][] REF_AND_DECL_CATEGORIES = { CONSTRUCTOR_REF, CONSTRUCTOR_DECL };
@@ -51,6 +52,7 @@
 	char[] declaringQualification,
 	char[][] parameterQualifications,
 	char[][] parameterSimpleNames,
+	boolean varargs,
 	int matchRule) {
 
 	this(matchRule);
@@ -71,7 +73,7 @@
 	} else {
 		this.parameterCount = -1;
 	}
-
+	this.varargs = varargs;
 	((InternalSearchPattern)this).mustResolve = mustResolve();
 }
 ConstructorPattern(int matchRule) {
@@ -97,7 +99,7 @@
 public boolean matchesDecodedKey(SearchPattern decodedPattern) {
 	ConstructorPattern pattern = (ConstructorPattern) decodedPattern;
 
-	return (this.parameterCount == pattern.parameterCount || this.parameterCount == -1)
+	return (this.parameterCount == pattern.parameterCount || this.parameterCount == -1 || this.varargs)
 		&& matchesName(this.declaringSimpleName, pattern.declaringSimpleName);
 }
 protected boolean mustResolve() {
@@ -115,7 +117,7 @@
 
 	switch(getMatchMode()) {
 		case R_EXACT_MATCH :
-			if (this.declaringSimpleName != null && this.parameterCount >= 0)
+			if (!this.varargs && this.declaringSimpleName != null && this.parameterCount >= 0)
 				key = createIndexKey(this.declaringSimpleName, this.parameterCount);
 			else // do a prefix query with the declaringSimpleName
 				matchRule = matchRule - R_EXACT_MATCH + R_PREFIX_MATCH;
@@ -124,7 +126,7 @@
 			// do a prefix query with the declaringSimpleName
 			break;
 		case R_PATTERN_MATCH :
-			if (this.parameterCount >= 0)
+			if (!this.varargs && this.parameterCount >= 0)
 				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);
@@ -134,46 +136,32 @@
 
 	return index.query(getIndexCategories(), key, matchRule); // match rule is irrelevant when the key is null
 }
-public String toString() {
-	StringBuffer buffer = new StringBuffer(20);
+protected StringBuffer print(StringBuffer output) {
 	if (this.findDeclarations) {
-		buffer.append(this.findReferences
+		output.append(this.findReferences
 			? "ConstructorCombinedPattern: " //$NON-NLS-1$
 			: "ConstructorDeclarationPattern: "); //$NON-NLS-1$
 	} else {
-		buffer.append("ConstructorReferencePattern: "); //$NON-NLS-1$
+		output.append("ConstructorReferencePattern: "); //$NON-NLS-1$
 	}
 	if (declaringQualification != null)
-		buffer.append(declaringQualification).append('.');
+		output.append(declaringQualification).append('.');
 	if (declaringSimpleName != null) 
-		buffer.append(declaringSimpleName);
+		output.append(declaringSimpleName);
 	else if (declaringQualification != null)
-		buffer.append("*"); //$NON-NLS-1$
+		output.append("*"); //$NON-NLS-1$
 
-	buffer.append('(');
+	output.append('(');
 	if (parameterSimpleNames == null) {
-		buffer.append("..."); //$NON-NLS-1$
+		output.append("..."); //$NON-NLS-1$
 	} else {
 		for (int i = 0, max = parameterSimpleNames.length; i < max; i++) {
-			if (i > 0) buffer.append(", "); //$NON-NLS-1$
-			if (parameterQualifications[i] != null) buffer.append(parameterQualifications[i]).append('.');
-			if (parameterSimpleNames[i] == null) buffer.append('*'); else buffer.append(parameterSimpleNames[i]);
+			if (i > 0) output.append(", "); //$NON-NLS-1$
+			if (parameterQualifications[i] != null) output.append(parameterQualifications[i]).append('.');
+			if (parameterSimpleNames[i] == null) output.append('*'); else output.append(parameterSimpleNames[i]);
 		}
 	}
-	buffer.append(')');
-	buffer.append(", "); //$NON-NLS-1$
-	switch(getMatchMode()) {
-		case R_EXACT_MATCH : 
-			buffer.append("exact match, "); //$NON-NLS-1$
-			break;
-		case R_PREFIX_MATCH :
-			buffer.append("prefix match, "); //$NON-NLS-1$
-			break;
-		case R_PATTERN_MATCH :
-			buffer.append("pattern match, "); //$NON-NLS-1$
-			break;
-	}
-	buffer.append(isCaseSensitive() ? "case sensitive" : "case insensitive"); //$NON-NLS-1$ //$NON-NLS-2$
-	return buffer.toString();
+	output.append(')');
+	return super.print(output);
 }
 }
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/DeclarationOfReferencedMethodsPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/DeclarationOfReferencedMethodsPattern.java
index 2828f21..5049416 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/DeclarationOfReferencedMethodsPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/DeclarationOfReferencedMethodsPattern.java
@@ -21,7 +21,7 @@
 protected SimpleSet knownMethods;
 
 public DeclarationOfReferencedMethodsPattern(IJavaElement enclosingElement) {
-	super(false, true, null, null, null, null, null, null, null, null, R_PATTERN_MATCH);
+	super(false, true, null, null, null, null, null, null, null, false, null, R_PATTERN_MATCH);
 
 	this.enclosingElement = enclosingElement;
 	this.knownMethods = new SimpleSet();
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java
index 65c51be..8896971 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java
@@ -30,7 +30,26 @@
 
 	this.isDeclarationOfAccessedFieldsPattern = this.pattern instanceof DeclarationOfAccessedFieldsPattern;
 }
-//public int match(ASTNode node, MatchingNodeSet nodeSet) - SKIP IT
+public int match(ASTNode node, MatchingNodeSet nodeSet) {
+	int declarationsLevel = IMPOSSIBLE_MATCH;
+	if (this.pattern.findReferences) {
+		if (node instanceof ImportReference) {
+			// With static import, we can have static field reference in import reference
+			ImportReference importRef = (ImportReference) node;
+			int length = importRef.tokens.length-1;
+			if (importRef.isStatic() && !importRef.onDemand && matchesName(this.pattern.name, importRef.tokens[length])) {
+				char[][] compoundName = new char[length][];
+				System.arraycopy(importRef.tokens, 0, compoundName, 0, length);
+				FieldPattern fieldPattern = (FieldPattern) this.pattern;
+				char[] declaringType = CharOperation.concat(fieldPattern.declaringQualification, fieldPattern.declaringSimpleName, '.');
+				if (matchesName(declaringType, CharOperation.concatWith(compoundName, '.'))) {
+					declarationsLevel = ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
+				}
+			}
+		}
+	}
+	return nodeSet.addMatch(node, declarationsLevel);
+}
 //public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
 public int match(FieldDeclaration node, MatchingNodeSet nodeSet) {
 	int referencesLevel = IMPOSSIBLE_MATCH;
@@ -41,12 +60,16 @@
 				referencesLevel = ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
 
 	int declarationsLevel = IMPOSSIBLE_MATCH;
-	if (this.pattern.findDeclarations)
-		if (node.isField()) // ignore field initializers
-			if (matchesName(this.pattern.name, node.name))
-				if (matchesTypeReference(((FieldPattern)this.pattern).typeSimpleName, node.type))
-					declarationsLevel = ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-
+	if (this.pattern.findDeclarations) {
+		switch (node.getKind()) {
+			case AbstractVariableDeclaration.FIELD :
+			case AbstractVariableDeclaration.ENUM_CONSTANT :
+				if (matchesName(this.pattern.name, node.name))
+					if (matchesTypeReference(((FieldPattern)this.pattern).typeSimpleName, node.type))
+						declarationsLevel = ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
+				break;
+		}
+	}
 	return nodeSet.addMatch(node, referencesLevel >= declarationsLevel ? referencesLevel : declarationsLevel); // use the stronger match
 }
 //public int match(MethodDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
@@ -56,8 +79,8 @@
 
 protected int matchContainer() {
 	if (this.pattern.findReferences) {
-		// need to look almost everywhere to find in javadocs
-		return CLASS_CONTAINER | METHOD_CONTAINER | FIELD_CONTAINER;
+		// need to look everywhere to find in javadocs and static import
+		return ALL_CONTAINER;
 	}
 	return CLASS_CONTAINER;
 }
@@ -84,9 +107,24 @@
 	// look at field type only if declaring type is not specified
 	if (fieldPattern.declaringSimpleName == null) return declaringLevel;
 
-	int typeLevel = resolveLevelForType(fieldPattern.typeSimpleName, fieldPattern.typeQualification, field.type);
+	// get real field binding
+	FieldBinding fieldBinding = field;
+	if (field instanceof ParameterizedFieldBinding) {
+		fieldBinding = ((ParameterizedFieldBinding) field).originalField;
+	}
+
+	int typeLevel = resolveLevelForType(fieldBinding.type);
 	return declaringLevel > typeLevel ? typeLevel : declaringLevel; // return the weaker match
 }
+/* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#matchLevelAndReportImportRef(org.eclipse.jdt.internal.compiler.ast.ImportReference, org.eclipse.jdt.internal.compiler.lookup.Binding, org.eclipse.jdt.internal.core.search.matching.MatchLocator)
+ * Accept to report match of static field on static import
+ */
+protected void matchLevelAndReportImportRef(ImportReference importRef, Binding binding, MatchLocator locator) throws CoreException {
+	if (importRef.isStatic() && binding instanceof FieldBinding) {
+		super.matchLevelAndReportImportRef(importRef, binding, locator);
+	}
+}
 protected int matchReference(Reference node, MatchingNodeSet nodeSet, boolean writeOnlyAccess) {
 	if (node instanceof FieldReference) {
 		if (matchesName(this.pattern.name, ((FieldReference) node).token))
@@ -119,6 +157,14 @@
 				reportDeclaration((FieldBinding)((SingleNameReference) reference).binding, locator, declPattern.knownFields);
 			}
 		}
+	} else if (reference instanceof ImportReference) {
+		ImportReference importRef = (ImportReference) reference;
+		long[] positions = importRef.sourcePositions;
+		int lastIndex = importRef.tokens.length - 1;
+		int start = (int) ((positions[lastIndex]) >>> 32);
+		int end = (int) positions[lastIndex];
+		SearchMatch match = locator.newFieldReferenceMatch(element, accuracy, start, end-start+1, importRef);
+		locator.report(match);
 	} else if (reference instanceof FieldReference) {
 		FieldReference fieldReference = (FieldReference) reference;
 		long position = fieldReference.nameSourcePosition;
@@ -149,7 +195,10 @@
 						accuracies[indexOfFirstFieldBinding] = SearchMatch.A_ACCURATE;
 						break;
 					case INACCURATE_MATCH:
-						accuracies[indexOfFirstFieldBinding] = SearchMatch.A_INACCURATE;
+						if (fieldBinding.type.isParameterizedType() && this.pattern.isParameterized())
+							accuracies[indexOfFirstFieldBinding] = refineAccuracy(SearchMatch.A_INACCURATE, (ParameterizedTypeBinding) fieldBinding.type, this.pattern.typeArguments, locator);
+						else
+							accuracies[indexOfFirstFieldBinding] = SearchMatch.A_INACCURATE;
 						break;
 					default:
 						accuracies[indexOfFirstFieldBinding] = -1;
@@ -171,8 +220,11 @@
 							accuracies[i] = SearchMatch.A_ACCURATE;
 							break;
 						case INACCURATE_MATCH:
-							accuracies[i] = SearchMatch.A_INACCURATE;
-							break;
+							if (otherBinding.type.isParameterizedType() && this.pattern.isParameterized())
+								accuracies[i] = refineAccuracy(SearchMatch.A_INACCURATE, (ParameterizedTypeBinding) otherBinding.type, this.pattern.typeArguments, locator);
+							else
+								accuracies[i] = SearchMatch.A_INACCURATE;
+								break;
 						default:
 							accuracies[i] = -1;
 					}
@@ -184,6 +236,18 @@
 		locator.reportAccurateFieldReference(qNameRef, element, accuracies);
 	}
 }
+	/* (non-Javadoc)
+	 * Overridden to filter rule values from refined accuracy.
+	 * @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#refineAccuracy(int, org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding, char[][][], org.eclipse.jdt.internal.core.search.matching.MatchLocator)
+	 */
+	protected int refineAccuracy(int accuracy, ParameterizedTypeBinding parameterizedBinding, char[][][] patternTypeArguments, MatchLocator locator) {
+		// We can only refine if locator has an unit scope.
+		if (locator.unitScope == null) return accuracy;
+		int refinedAccuracy = refineAccuracy(accuracy, parameterizedBinding, patternTypeArguments, false, 0, locator);
+		if (refinedAccuracy > SearchMatch.A_INACCURATE)
+			return -1; // canot accept neither erasure nor compatible match
+		return refinedAccuracy;
+	}
 protected void reportDeclaration(FieldBinding fieldBinding, MatchLocator locator, SimpleSet knownFields) throws CoreException {
 	// ignore length field
 	if (fieldBinding == ArrayBinding.ArrayLength) return;
@@ -206,6 +270,8 @@
 		info = locator.getBinaryInfo((org.eclipse.jdt.internal.core.ClassFile) type.getClassFile(), resource);
 		locator.reportBinaryMemberDeclaration(resource, field, info, SearchMatch.A_ACCURATE);
 	} else {
+		if (declaringClass instanceof ParameterizedTypeBinding)
+			declaringClass = ((ParameterizedTypeBinding) declaringClass).type;
 		ClassScope scope = ((SourceTypeBinding) declaringClass).scope;
 		if (scope != null) {
 			TypeDeclaration typeDecl = scope.referenceContext;
@@ -221,7 +287,6 @@
 				int offset = fieldDecl.sourceStart;
 				SearchMatch match = new FieldDeclarationMatch(field, SearchMatch.A_ACCURATE, offset, fieldDecl.sourceEnd-offset+1, locator.getParticipant(), resource);
 				locator.report(match);
-
 			}
 		}
 	}
@@ -275,4 +340,16 @@
 	}
 	return IMPOSSIBLE_MATCH;
 }
+/* (non-Javadoc)
+ * Resolve level for type with a given binding.
+ */
+protected int resolveLevelForType(TypeBinding typeBinding) {
+	FieldPattern fieldPattern = (FieldPattern) this.pattern;
+	return resolveLevelForType(
+			fieldPattern.typeSimpleName,
+			fieldPattern.typeQualification,
+			fieldPattern.typeArguments,
+			0,
+			typeBinding);
+}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldPattern.java
index 758e96f..3504cfb 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldPattern.java
@@ -52,6 +52,25 @@
 
 	((InternalSearchPattern)this).mustResolve = mustResolve();
 }
+/*
+ * Instanciate a field pattern with additional information for generics search
+ */
+public FieldPattern(
+	boolean findDeclarations,
+	boolean readAccess,
+	boolean writeAccess,
+	char[] name, 
+	char[] declaringQualification,
+	char[] declaringSimpleName,	
+	char[] typeQualification, 
+	char[] typeSimpleName,
+	String signature,
+	int matchRule) {
+
+	this(findDeclarations, readAccess, writeAccess, name, declaringQualification, declaringSimpleName, typeQualification, typeSimpleName, matchRule);
+
+	if (signature != null) computeSignature(signature);
+}
 public void decodeIndexKey(char[] key) {
 	this.name = key;
 }
@@ -77,43 +96,29 @@
 
 	return super.mustResolve();
 }
-public String toString() {
-	StringBuffer buffer = new StringBuffer(20);
+protected StringBuffer print(StringBuffer output) {
 	if (this.findDeclarations) {
-		buffer.append(this.findReferences
+		output.append(this.findReferences
 			? "FieldCombinedPattern: " //$NON-NLS-1$
 			: "FieldDeclarationPattern: "); //$NON-NLS-1$
 	} else {
-		buffer.append("FieldReferencePattern: "); //$NON-NLS-1$
+		output.append("FieldReferencePattern: "); //$NON-NLS-1$
 	}
-	if (declaringQualification != null) buffer.append(declaringQualification).append('.');
+	if (declaringQualification != null) output.append(declaringQualification).append('.');
 	if (declaringSimpleName != null) 
-		buffer.append(declaringSimpleName).append('.');
-	else if (declaringQualification != null) buffer.append("*."); //$NON-NLS-1$
+		output.append(declaringSimpleName).append('.');
+	else if (declaringQualification != null) output.append("*."); //$NON-NLS-1$
 	if (name == null) {
-		buffer.append("*"); //$NON-NLS-1$
+		output.append("*"); //$NON-NLS-1$
 	} else {
-		buffer.append(name);
+		output.append(name);
 	}
 	if (typeQualification != null) 
-		buffer.append(" --> ").append(typeQualification).append('.'); //$NON-NLS-1$
-	else if (typeSimpleName != null) buffer.append(" --> "); //$NON-NLS-1$
+		output.append(" --> ").append(typeQualification).append('.'); //$NON-NLS-1$
+	else if (typeSimpleName != null) output.append(" --> "); //$NON-NLS-1$
 	if (typeSimpleName != null) 
-		buffer.append(typeSimpleName);
-	else if (typeQualification != null) buffer.append("*"); //$NON-NLS-1$
-	buffer.append(", "); //$NON-NLS-1$
-	switch(getMatchMode()) {
-		case R_EXACT_MATCH : 
-			buffer.append("exact match, "); //$NON-NLS-1$
-			break;
-		case R_PREFIX_MATCH :
-			buffer.append("prefix match, "); //$NON-NLS-1$
-			break;
-		case R_PATTERN_MATCH :
-			buffer.append("pattern match, "); //$NON-NLS-1$
-			break;
-	}
-	buffer.append(isCaseSensitive() ? "case sensitive" : "case insensitive"); //$NON-NLS-1$ //$NON-NLS-2$
-	return buffer.toString();
+		output.append(typeSimpleName);
+	else if (typeQualification != null) output.append("*"); //$NON-NLS-1$
+	return super.print(output);
 }
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/InternalSearchPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/InternalSearchPattern.java
index 9bd3a96..b24ab4a 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/InternalSearchPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/InternalSearchPattern.java
@@ -15,6 +15,7 @@
 import org.eclipse.core.runtime.*;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.search.*;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.core.index.*;
 import org.eclipse.jdt.internal.core.search.*;
 
@@ -33,9 +34,20 @@
 	
 	void acceptMatch(String documentName, SearchPattern pattern, IndexQueryRequestor requestor, SearchParticipant participant, IJavaSearchScope scope) {
 		String documentPath = Index.convertPath(documentName);
-		if (scope.encloses(documentPath))
-			if (!requestor.acceptIndexMatch(documentPath, pattern, participant)) 
+
+		if (scope instanceof JavaSearchScope) {
+			JavaSearchScope javaSearchScope = (JavaSearchScope) scope;
+			// Get document path access restriction from java search scope
+			// Note that requestor has to verify if needed whether the document violates the access restriction or not
+			AccessRestriction access = javaSearchScope.getAccessRestriction(documentPath);
+			if (JavaSearchScope.UNINIT_RESTRICTION != access) { // scope encloses the document path
+				if (!requestor.acceptIndexMatch(documentPath, pattern, participant, access)) 
+					throw new OperationCanceledException();
+			}
+		} else if (scope.encloses(documentPath)) {
+			if (!requestor.acceptIndexMatch(documentPath, pattern, participant, null)) 
 				throw new OperationCanceledException();
+		}
 	}
 	SearchPattern currentPattern() {
 		return (SearchPattern) this;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
index abef123..9015229 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
@@ -28,11 +28,14 @@
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.ClasspathEntry;
 import org.eclipse.jdt.internal.core.JavaModel;
 import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.JavaProject;
+import org.eclipse.jdt.internal.core.PackageFragmentRoot;
 import org.eclipse.jdt.internal.core.builder.ClasspathJar;
 import org.eclipse.jdt.internal.core.builder.ClasspathLocation;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /*
  * A name environment based on the classpath of a Java project.
@@ -56,7 +59,7 @@
 			IPackageDeclaration[] pkgs = workingCopy.getPackageDeclarations();
 			String pkg = pkgs.length > 0 ? pkgs[0].getElementName() : ""; //$NON-NLS-1$
 			String cuName = workingCopy.getElementName();
-			String mainTypeName = cuName.substring(0, cuName.length() - SUFFIX_JAVA.length);
+			String mainTypeName = cuName.substring(0, Util.indexOfJavaLikeExtension(cuName));
 			String qualifiedMainTypeName = pkg.length() == 0 ? mainTypeName : pkg.replace('.', '/') + '/' + mainTypeName;
 			this.workingCopies.put(qualifiedMainTypeName, workingCopy);
 		}
@@ -86,18 +89,22 @@
 	int index = 0;
 	JavaModelManager manager = JavaModelManager.getJavaModelManager();
 	for (int i = 0; i < length; i++) {
-		IPackageFragmentRoot root = roots[i];
+		PackageFragmentRoot root = (PackageFragmentRoot) roots[i];
 		IPath path = root.getPath();
 		try {
 			if (root.isArchive()) {
 				ZipFile zipFile = manager.getZipFile(path);
-				cpLocations[index++] = new ClasspathJar(zipFile);
+				cpLocations[index++] = new ClasspathJar(zipFile, ((ClasspathEntry) root.getRawClasspathEntry()).getImportRestriction());
 			} else {
 				Object target = JavaModel.getTarget(workspaceRoot, path, false);
-				if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
-					cpLocations[index++] = new ClasspathSourceDirectory((IContainer)target);
+				if (target == null) {
+					// target doesn't exist any longer
+					// just resize cpLocations
+					System.arraycopy(cpLocations, 0, cpLocations = new ClasspathLocation[cpLocations.length-1], 0, index);
+				} else if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
+					cpLocations[index++] = new ClasspathSourceDirectory((IContainer)target, root.fullExclusionPatternChars(), root.fullInclusionPatternChars());
 				} else {
-					cpLocations[index++] = ClasspathLocation.forBinaryFolder((IContainer) target, false);
+					cpLocations[index++] = ClasspathLocation.forBinaryFolder((IContainer) target, false, ((ClasspathEntry) root.getRawClasspathEntry()).getImportRestriction());
 				}
 			}
 		} catch (CoreException e1) {
@@ -120,23 +127,23 @@
 		NameEnvironmentAnswer answer;
 		if (location instanceof ClasspathSourceDirectory) {
 			if (sourceFileName == null) {
-				qSourceFileName = qualifiedTypeName + SUFFIX_STRING_java;
+				qSourceFileName = qualifiedTypeName; // doesn't include the file extension
 				sourceFileName = qSourceFileName;
 				qPackageName =  ""; //$NON-NLS-1$
 				if (qualifiedTypeName.length() > typeName.length) {
-					int typeNameStart = qSourceFileName.length() - typeName.length - 5; // size of ".java"
+					int typeNameStart = qSourceFileName.length() - typeName.length;
 					qPackageName =  qSourceFileName.substring(0, typeNameStart - 1);
 					sourceFileName = qSourceFileName.substring(typeNameStart);
 				}
 			}
 			ICompilationUnit workingCopy = (ICompilationUnit) this.workingCopies.get(qualifiedTypeName);
 			if (workingCopy != null) {
-				answer = new NameEnvironmentAnswer(workingCopy);
+				answer = new NameEnvironmentAnswer(workingCopy, null /*no access restriction*/);
 			} else {
 				answer = location.findClass(
-					sourceFileName,
+					sourceFileName, // doesn't include the file extension
 					qPackageName,
-					qSourceFileName);
+					qSourceFileName);  // doesn't include the file extension
 			}
 		} else {
 			if (binaryFileName == null) {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java
index b83ed08..31bb7a1 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.matching;
 
+import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.search.SearchPattern;
 
@@ -22,15 +23,36 @@
 	boolean isCaseSensitive;
 	
 	/*
+	 * Whether this pattern is erasure match.
+	 */
+	boolean isErasureMatch;
+
+	/*
 	 * One of R_EXACT_MATCH, R_PREFIX_MATCH, R_PATTERN_MATCH, R_REGEXP_MATCH.
 	 */
 	int matchMode;
+
+	/**
+	 * Mask used on match rule for match mode.
+	 */
+	public static final int MATCH_MODE_MASK = R_EXACT_MATCH + R_PREFIX_MATCH + R_PATTERN_MATCH + R_REGEXP_MATCH;
+
+	/**
+	 * Mask used on match rule for indexing.
+	 */
+	public static final int MATCH_RULE_INDEX_MASK = MATCH_MODE_MASK + R_CASE_SENSITIVE;
+
 	
+	// Signatures and arguments for parameterized types search
+	char[][] typeSignatures;
+	char[][][] typeArguments;
+
 	protected JavaSearchPattern(int patternKind, int matchRule) {
 		super(matchRule);
 		((InternalSearchPattern)this).kind = patternKind;
 		this.isCaseSensitive = (matchRule & R_CASE_SENSITIVE) != 0;
-		this.matchMode = matchRule - (this.isCaseSensitive ? R_CASE_SENSITIVE : 0);
+		this.isErasureMatch = (matchRule & SearchPattern.R_ERASURE_MATCH) != 0;
+		this.matchMode = matchRule & MATCH_MODE_MASK;
 	}
 	
 	public SearchPattern getBlankPattern() {
@@ -45,6 +67,97 @@
 		return this.isCaseSensitive;
 	}
 
+	boolean isErasureMatch() {
+		return this.isErasureMatch;
+	}
+
+	/**
+	 * Returns whether the pattern includess type arguments information or not.
+	 * @return true if pattern has signature *and* type arguments
+	 */
+	public boolean isParameterized() {
+		return this.typeArguments != null && this.typeArguments.length > 0;
+	}
+
+	/* (non-Javadoc)
+	 * Compute a IJavaElement signature or a string pattern signature to store
+	 * its type arguments. Recurse when signature is qualified to store signatures and
+	 * type arguments also for of all enclosing types.
+	 */
+	void computeSignature(String signature) {
+		// In case of IJavaElement signature, replace '/' by '.'
+		char[] source = signature.replace('/','.').replace('$','.').toCharArray();
+
+		// Init counters and arrays
+		char[][] signatures = new char[10][];
+		int signaturesCount = 0;
+		int[] lengthes = new int [10];
+		int typeArgsCount = 0;
+		int paramOpening = 0;
+		boolean parameterized = false;
+		
+		// Scan each signature character
+		for (int idx=0, ln = source.length; idx < ln; idx++) {
+			switch (source[idx]) {
+				case '>':
+					paramOpening--;
+					if (paramOpening == 0)  {
+						if (signaturesCount == lengthes.length) {
+							System.arraycopy(signatures, 0, signatures = new char[signaturesCount+10][], 0, signaturesCount);
+							System.arraycopy(lengthes, 0, lengthes = new int[signaturesCount+10], 0, signaturesCount);
+						}
+						lengthes[signaturesCount] = typeArgsCount;
+						typeArgsCount = 0;
+					}
+					break;
+				case '<':
+					paramOpening++;
+					if (paramOpening == 1) {
+						typeArgsCount = 0;
+						parameterized = true;
+					}
+					break;
+				case '*':
+				case ';':
+					if (paramOpening == 1) typeArgsCount++;
+					break;
+				case '.':
+					if (paramOpening == 0)  {
+						if (signaturesCount == lengthes.length) {
+							System.arraycopy(signatures, 0, signatures = new char[signaturesCount+10][], 0, signaturesCount);
+							System.arraycopy(lengthes, 0, lengthes = new int[signaturesCount+10], 0, signaturesCount);
+						}
+						signatures[signaturesCount] = new char[idx+1];
+						System.arraycopy(source, 0, signatures[signaturesCount], 0, idx);
+						signatures[signaturesCount][idx] = Signature.C_SEMICOLON;
+						signaturesCount++;
+					}
+					break;
+			}
+		}
+		
+		// Store signatures and type arguments
+		this.typeSignatures = new char[signaturesCount+1][];
+		if (parameterized)
+			this.typeArguments = new char[signaturesCount+1][][];
+		this.typeSignatures[0] = source;
+		if (parameterized) {
+			this.typeArguments[0] = Signature.getTypeArguments(source);
+			if (lengthes[signaturesCount] != this.typeArguments[0].length) {
+				// TODO (frederic) abnormal signature => should raise an error
+			}
+		}
+		for (int i=1, j=signaturesCount-1; i<=signaturesCount; i++, j--){
+			this.typeSignatures[i] = signatures[j];
+			if (parameterized) {
+				this.typeArguments[i] = Signature.getTypeArguments(signatures[j]);
+				if (lengthes[j] != this.typeArguments[i].length) {
+					// TODO (frederic) abnormal signature => should raise an error
+				}
+			}
+		}
+	}
+
 	/*
 	 * Optimization of implementation above (uses cached matchMode and isCaseSenistive)
 	 */
@@ -61,10 +174,39 @@
 						pattern = CharOperation.toLowerCase(pattern);
 					return CharOperation.match(pattern, name, this.isCaseSensitive);
 				case R_REGEXP_MATCH :
-					// TODO (jerome) implement regular expression match
+					// TODO (frederic) implement regular expression match
 					return true;
 			}
 		}
 		return false;
 	}
+	protected StringBuffer print(StringBuffer output) {
+		output.append(", "); //$NON-NLS-1$
+		if (this.typeSignatures != null && this.typeSignatures.length > 0) {
+			output.append("signature:\""); //$NON-NLS-1$
+			output.append(this.typeSignatures[0]);
+			output.append("\", "); //$NON-NLS-1$
+		}
+		switch(getMatchMode()) {
+			case R_EXACT_MATCH : 
+				output.append("exact match,"); //$NON-NLS-1$
+				break;
+			case R_PREFIX_MATCH :
+				output.append("prefix match,"); //$NON-NLS-1$
+				break;
+			case R_PATTERN_MATCH :
+				output.append("pattern match,"); //$NON-NLS-1$
+				break;
+		}
+		if (isCaseSensitive())
+			output.append(" case sensitive"); //$NON-NLS-1$
+		else
+			output.append(" case insensitive"); //$NON-NLS-1$
+		if (isErasureMatch())
+			output.append(", erasure only"); //$NON-NLS-1$
+		return output;
+	}
+	public final String toString() {
+		return print(new StringBuffer(30)).toString();
+	}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/LocalVariablePattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/LocalVariablePattern.java
index c9834c8..94bce6c 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/LocalVariablePattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/LocalVariablePattern.java
@@ -14,10 +14,12 @@
 import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.search.*;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.LocalVariable;
 import org.eclipse.jdt.internal.core.index.Index;
 import org.eclipse.jdt.internal.core.search.IndexQueryRequestor;
+import org.eclipse.jdt.internal.core.search.JavaSearchScope;
 import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
 
 public class LocalVariablePattern extends VariablePattern implements IIndexConstants {
@@ -38,33 +40,30 @@
     } else {
         path = this.localVariable.getPath().toString();
     }
-	if (scope.encloses(path))
-		if (!requestor.acceptIndexMatch(path, this, participant)) 
+
+	if (scope instanceof JavaSearchScope) {
+		JavaSearchScope javaSearchScope = (JavaSearchScope) scope;
+		// Get document path access restriction from java search scope
+		// Note that requestor has to verify if needed whether the document violates the access restriction or not
+		AccessRestriction access = javaSearchScope.getAccessRestriction(path);
+		if (!JavaSearchScope.UNINIT_RESTRICTION.equals(access)) { // scope encloses the path
+			if (!requestor.acceptIndexMatch(path, this, participant, access)) 
+				throw new OperationCanceledException();
+		}
+	} else if (scope.encloses(path)) {
+		if (!requestor.acceptIndexMatch(path, this, participant, null)) 
 			throw new OperationCanceledException();
+	}
 }
-public String toString() {
-	StringBuffer buffer = new StringBuffer(20);
+protected StringBuffer print(StringBuffer output) {
 	if (this.findDeclarations) {
-		buffer.append(this.findReferences
+		output.append(this.findReferences
 			? "LocalVarCombinedPattern: " //$NON-NLS-1$
 			: "LocalVarDeclarationPattern: "); //$NON-NLS-1$
 	} else {
-		buffer.append("LocalVarReferencePattern: "); //$NON-NLS-1$
+		output.append("LocalVarReferencePattern: "); //$NON-NLS-1$
 	}
-	buffer.append(this.localVariable.toStringWithAncestors());
-	buffer.append(", "); //$NON-NLS-1$
-	switch(getMatchMode()) {
-		case R_EXACT_MATCH : 
-			buffer.append("exact match, "); //$NON-NLS-1$
-			break;
-		case R_PREFIX_MATCH :
-			buffer.append("prefix match, "); //$NON-NLS-1$
-			break;
-		case R_PATTERN_MATCH :
-			buffer.append("pattern match, "); //$NON-NLS-1$
-			break;
-	}
-	buffer.append(isCaseSensitive() ? "case sensitive" : "case insensitive"); //$NON-NLS-1$ //$NON-NLS-2$
-	return buffer.toString();
+	output.append(this.localVariable.toStringWithAncestors());
+	return super.print(output);
 }
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
index 004c579..7126ff7 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
@@ -18,7 +18,19 @@
 
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.*;
-import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.IClassFile;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaModelStatusConstants;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.ISourceRange;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.core.search.*;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
@@ -28,21 +40,31 @@
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
 import org.eclipse.jdt.internal.compiler.env.*;
-import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.parser.*;
 import org.eclipse.jdt.internal.compiler.problem.*;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfIntValues;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
-import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.hierarchy.HierarchyResolver;
+import org.eclipse.jdt.internal.core.BinaryType;
+import org.eclipse.jdt.internal.core.ClassFile;
+import org.eclipse.jdt.internal.core.CompilationUnit;
+import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
+import org.eclipse.jdt.internal.core.JavaElement;
+import org.eclipse.jdt.internal.core.JavaModelManager;
+import org.eclipse.jdt.internal.core.JavaProject;
+import org.eclipse.jdt.internal.core.NameLookup;
+import org.eclipse.jdt.internal.core.Openable;
+import org.eclipse.jdt.internal.core.PackageFragment;
+import org.eclipse.jdt.internal.core.PackageFragmentRoot;
+import org.eclipse.jdt.internal.core.SearchableEnvironment;
+import org.eclipse.jdt.internal.core.SourceMapper;
+import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
 import org.eclipse.jdt.internal.core.index.Index;
 import org.eclipse.jdt.internal.core.search.*;
-import org.eclipse.jdt.internal.core.search.HierarchyScope;
-import org.eclipse.jdt.internal.core.search.IndexSelector;
-import org.eclipse.jdt.internal.core.search.JavaSearchDocument;
 import org.eclipse.jdt.internal.core.util.HandleFactory;
 import org.eclipse.jdt.internal.core.util.SimpleSet;
 import org.eclipse.jdt.internal.core.util.Util;
@@ -85,6 +107,14 @@
  */
 public long resultCollectorTime = 0;
 
+// Progress information
+int progressStep;
+int progressWorked;
+
+// Binding resolution and cache
+CompilationUnitScope unitScope;
+SimpleLookupTable bindings;
+
 /**
  * An ast visitor that visits local type declarations.
  */
@@ -111,11 +141,21 @@
 				occurrenceCount = occurrenceCount + 1;
 			}
 			occurrencesCounts.put(simpleName, occurrenceCount);
-			if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {				
-				reportMatching(typeDeclaration, enclosingElement, -1, nodeSet, occurrenceCount);
+			if (typeDeclaration.allocation == null || typeDeclaration.allocation.enumConstant == null) {
+				if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {				
+					reportMatching(typeDeclaration, enclosingElement, -1, nodeSet, occurrenceCount);
+				} else {
+					Integer level = (Integer) nodeSet.matchingNodes.removeKey(typeDeclaration);
+					reportMatching(typeDeclaration, enclosingElement, level != null ? level.intValue() : -1, nodeSet, occurrenceCount);
+				}
 			} else {
 				Integer level = (Integer) nodeSet.matchingNodes.removeKey(typeDeclaration);
-				reportMatching(typeDeclaration, enclosingElement, level != null ? level.intValue() : -1, nodeSet, occurrenceCount);
+				if (level != null) {
+					FieldDeclaration enumConstant = typeDeclaration.allocation.enumConstant;
+					int offset = enumConstant.sourceStart;
+					SearchMatch match = newDeclarationMatch(enclosingElement, level.intValue(), offset, enumConstant.sourceEnd-offset+1);
+					report(match);
+				}
 			}
 			return false; // don't visit members as this was done during reportMatching(...)
 		} catch (CoreException e) {
@@ -124,6 +164,7 @@
 	}
 }
 
+
 public static class WorkingCopyDocument extends JavaSearchDocument {
 	public org.eclipse.jdt.core.ICompilationUnit workingCopy;
 	WorkingCopyDocument(org.eclipse.jdt.core.ICompilationUnit workingCopy, SearchParticipant participant) {
@@ -137,6 +178,7 @@
 }
 	
 public class WrappedCoreException extends RuntimeException {
+	private static final long serialVersionUID = 8354329870126121212L; // backward compatible
 	public CoreException coreException;
 	public WrappedCoreException(CoreException coreException) {
 		this.coreException = coreException;
@@ -209,7 +251,7 @@
 	if (classFile.isOpen())
 		return (ClassFileReader) manager.getInfo(type);
 
-	IPackageFragment pkg = type.getPackageFragment();
+	PackageFragment pkg = (PackageFragment) type.getPackageFragment();
 	IPackageFragmentRoot root = (IPackageFragmentRoot) pkg.getParent();
 	try {
 		if (!root.isArchive())
@@ -222,11 +264,9 @@
 			if (JavaModelManager.ZIP_ACCESS_VERBOSE)
 				System.out.println("(" + Thread.currentThread() + ") [MatchLocator.classFileReader()] Creating ZipFile on " + zipPath); //$NON-NLS-1$	//$NON-NLS-2$
 			zipFile = manager.getZipFile(zipPath);
-			char[] pkgPath = pkg.getElementName().toCharArray();
-			CharOperation.replace(pkgPath, '.', '/');
-			char[] classFileName = classFile.getElementName().toCharArray();
-			char[] path = pkgPath.length == 0 ? classFileName : CharOperation.concat(pkgPath, classFileName, '/');
-			return ClassFileReader.read(zipFile, new String(path));
+			String classFileName = classFile.getElementName();
+			String path = Util.concatWith(pkg.names, classFileName, '/');
+			return ClassFileReader.read(zipFile, path);
 		} finally {
 			manager.closeZipFile(zipFile);
 		}
@@ -244,17 +284,17 @@
 	return new AndPattern(0/*no kind*/, 0/*no rule*/) {
 		SearchPattern current = leftPattern;
 		public SearchPattern currentPattern() {
-			return current;
+			return this.current;
 		}
 		protected boolean hasNextQuery() {
-			if (current == leftPattern) {
-				current = rightPattern;
+			if (this.current == leftPattern) {
+				this.current = rightPattern;
 				return true;
 			}
 			return false; 
 		}
 		protected void resetQuery() {
-			current = leftPattern;
+			this.current = leftPattern;
 		}
 	};
 }
@@ -297,20 +337,20 @@
 /**
  * Add an additional binary type
  */
-public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
-	this.lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
+public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+	this.lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
 }
 /**
  * Add an additional compilation unit into the loop
  *  ->  build compilation unit declarations, their bindings and record their results.
  */
-public void accept(ICompilationUnit sourceUnit) {
+public void accept(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
 	// Switch the current policy and compilation result for this unit to the requested one.
 	CompilationResult unitResult = new CompilationResult(sourceUnit, 1, 1, this.options.maxProblemsPerUnit);
 	try {
 		CompilationUnitDeclaration parsedUnit = basicParser().dietParse(sourceUnit, unitResult);
-		lookupEnvironment.buildTypeBindings(parsedUnit);
-		lookupEnvironment.completeTypeBindings(parsedUnit, true);
+		this.lookupEnvironment.buildTypeBindings(parsedUnit, accessRestriction);
+		this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
 	} catch (AbortCompilationUnit e) {
 		// at this point, currentCompilationUnitResult may not be sourceUnit, but some other
 		// one requested further along to resolve sourceUnit.
@@ -324,7 +364,7 @@
 /**
  * Add additional source types
  */
-public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
+public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
 	// case of SearchableEnvironment of an IJavaProject is used
 	ISourceType sourceType = sourceTypes[0];
 	while (sourceType.getEnclosingType() != null)
@@ -334,7 +374,7 @@
 		SourceTypeElementInfo elementInfo = (SourceTypeElementInfo) sourceType;
 		IType type = elementInfo.getHandle();
 		ICompilationUnit sourceUnit = (ICompilationUnit) type.getCompilationUnit();
-		accept(sourceUnit);
+		accept(sourceUnit, accessRestriction);
 	} else {
 		CompilationResult result = new CompilationResult(sourceType.getFileName(), 1, 1, 0);
 		CompilationUnitDeclaration unit =
@@ -343,9 +383,9 @@
 				SourceTypeConverter.FIELD_AND_METHOD // need field and methods
 				| SourceTypeConverter.MEMBER_TYPE, // need member types
 				// no need for field initialization
-				lookupEnvironment.problemReporter,
+				this.lookupEnvironment.problemReporter,
 				result);
-		this.lookupEnvironment.buildTypeBindings(unit);
+		this.lookupEnvironment.buildTypeBindings(unit, accessRestriction);
 		this.lookupEnvironment.completeTypeBindings(unit, true);
 	}
 }	
@@ -370,7 +410,7 @@
 		throw new OperationCanceledException();
 
 	try {
-		if (SearchEngine.VERBOSE)
+		if (SearchBasicEngine.VERBOSE)
 			System.out.println("Parsing " + possibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$
 
 		this.parser.nodeSet = possibleMatch.nodeSet;
@@ -378,7 +418,7 @@
 		CompilationUnitDeclaration parsedUnit = this.parser.dietParse(possibleMatch, unitResult);
 		if (parsedUnit != null) {
 			if (mustResolve && !parsedUnit.isEmpty())
-				this.lookupEnvironment.buildTypeBindings(parsedUnit);
+				this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
 
 			// add the possibleMatch with its parsedUnit to matchesToProcess
 			possibleMatch.parsedUnit = parsedUnit;
@@ -396,12 +436,23 @@
  * Returns the existing one if already cached.
  * Returns null if source type binding was cached.
  */
-protected BinaryTypeBinding cacheBinaryType(IType type) throws JavaModelException {
+protected BinaryTypeBinding cacheBinaryType(IType type, IBinaryType binaryType) throws JavaModelException {
 	IType enclosingType = type.getDeclaringType();
 	if (enclosingType != null)
-		cacheBinaryType(enclosingType); // cache enclosing types first, so that binary type can be found in lookup enviroment
-	IBinaryType binaryType = (IBinaryType) ((BinaryType) type).getElementInfo();
-	BinaryTypeBinding binding = this.lookupEnvironment.cacheBinaryType(binaryType);
+		cacheBinaryType(enclosingType, null); // cache enclosing types first, so that binary type can be found in lookup enviroment
+	if (binaryType == null) {
+		ClassFile classFile = (ClassFile) type.getClassFile();
+		try {
+			binaryType = getBinaryInfo(classFile, classFile.getResource());
+		} catch (CoreException e) {
+			if (e instanceof JavaModelException) {
+				throw (JavaModelException) e;
+			} else {
+				throw new JavaModelException(e);
+			}
+		}
+	}
+	BinaryTypeBinding binding = this.lookupEnvironment.cacheBinaryType(binaryType, null /*no access restriction*/);
 	if (binding == null) { // it was already cached as a result of a previous query
 		char[][] compoundName = CharOperation.splitOn('.', type.getFullyQualifiedName().toCharArray());
 		ReferenceBinding referenceBinding = this.lookupEnvironment.getCachedType(compoundName);
@@ -487,9 +538,9 @@
 	String[] parameterTypeSignatures = new String[argCount];
 	for (int i = 0; i < argCount; i++) {
 		TypeReference typeRef = arguments[i].type;
-		char[] typeName = CharOperation.concatWith(typeRef.getTypeName(), '.');
-		for (int j = 0, dim = typeRef.dimensions(); j < dim; j++)
-			typeName = CharOperation.concat(typeName, new char[] {'[', ']'});
+		char[] typeName = CharOperation.concatWith(typeRef.getParameterizedTypeName(), '.');
+//		for (int j = 0, dim = typeRef.dimensions(); j < dim; j++)
+//			typeName = CharOperation.concat(typeName, new char[] {'[', ']'});
 		parameterTypeSignatures[i] = Signature.createTypeSignature(typeName, false);
 	}
 	return type.getMethod(new String(method.selector), parameterTypeSignatures);
@@ -500,14 +551,16 @@
 protected IJavaElement createHandle(FieldDeclaration fieldDeclaration, TypeDeclaration typeDeclaration, IJavaElement parent) {
 	if (!(parent instanceof IType)) return parent;
 
-	if (fieldDeclaration.isField())
-		return ((IType) parent).getField(new String(fieldDeclaration.name));
-
+	switch (fieldDeclaration.getKind()) {
+		case AbstractVariableDeclaration.FIELD :
+		case AbstractVariableDeclaration.ENUM_CONSTANT :
+			return ((IType) parent).getField(new String(fieldDeclaration.name));
+	}
 	// find occurence count of the given initializer in its type declaration
 	int occurrenceCount = 0;
 	FieldDeclaration[] fields = typeDeclaration.fields;
 	for (int i = 0, length = fields.length; i < length; i++) {
-		if (!fields[i].isField()) {
+		if (fields[i].getKind() == AbstractVariableDeclaration.INITIALIZER) {
 			occurrenceCount++;
 			if (fields[i].equals(fieldDeclaration)) break;
 		}
@@ -531,13 +584,13 @@
 	if (!isPossibleMatch) {
 		if (focusType.isBinary()) {
 			try {
-				cacheBinaryType(focusType);
+				cacheBinaryType(focusType, null);
 			} catch (JavaModelException e) {
 				return false;
 			}
 		} else {
 			// cache all types in the focus' compilation unit (even secondary types)
-			accept((ICompilationUnit) focusType.getCompilationUnit());
+			accept((ICompilationUnit) focusType.getCompilationUnit(), null /*TODO no access restriction*/);
 		}
 	}
 
@@ -595,14 +648,12 @@
 	// create a temporary info
 	IBinaryType info;
 	try {
-		IJavaElement pkg = classFile.getParent();
+		PackageFragment pkg = (PackageFragment) classFile.getParent();
 		PackageFragmentRoot root = (PackageFragmentRoot) pkg.getParent();
 		if (root.isArchive()) {
 			// class file in a jar
-			String pkgPath = pkg.getElementName().replace('.', '/');
-			String classFilePath = pkgPath.length() > 0
-				? pkgPath + "/" + classFile.getElementName() //$NON-NLS-1$
-				: classFile.getElementName();
+			String classFileName = classFile.getElementName();
+			String classFilePath = Util.concatWith(pkg.names, classFileName, '/');
 			ZipFile zipFile = null;
 			try {
 				zipFile = ((JarPackageFragmentRoot) root).getJar();
@@ -615,6 +666,7 @@
 			String osPath = resource.getLocation().toOSString();
 			info = ClassFileReader.read(osPath);
 		}
+		if (info == null) throw binaryType.newNotPresentException();
 		return info;
 	} catch (ClassFormatException e) {
 		//e.printStackTrace();
@@ -638,15 +690,11 @@
 	int oldLinePtr = this.parser.scanner.linePtr;
 	
 	try {
-		char[] contents = unit.compilationResult.compilationUnit.getContents();
-		this.parser.scanner.setSource(contents);
-
-		// inline old setLineEnds
-		final int[] lineSeparatorPositions = unit.compilationResult.lineSeparatorPositions;
-		this.parser.scanner.lineEnds = lineSeparatorPositions;
-		this.parser.scanner.linePtr = lineSeparatorPositions.length - 1;
+		CompilationResult compilationResult = unit.compilationResult;
+		this.parser.scanner.setSource(compilationResult);
 
 		if (this.parser.javadocParser.checkDocComment) {
+			char[] contents = compilationResult.compilationUnit.getContents();
 			this.parser.javadocParser.scanner.setSource(contents);
 		}
 		this.parser.nodeSet = this.currentPossibleMatch.nodeSet;
@@ -659,6 +707,54 @@
 		this.parser.scanner.linePtr = oldLinePtr;
 	}
 }
+protected TypeBinding getType(Object typeKey, char[] typeName) {
+	if (this.unitScope == null || typeName == null || typeName.length == 0) return null;
+	// Try to get binding from cache
+	Binding binding = (Binding) this.bindings.get(typeKey);
+	if (binding != null) {
+		if (binding instanceof TypeBinding && binding.isValidBinding())
+			return (TypeBinding) binding;
+		return null;
+	}
+	// Get binding from unit scope
+	char[][] compoundName = CharOperation.splitOn('.', typeName);
+	TypeBinding typeBinding = this.unitScope.getType(compoundName, compoundName.length);
+	this.bindings.put(typeKey, typeBinding);
+	return typeBinding.isValidBinding() ? typeBinding : null;
+}
+public MethodBinding getMethodBinding(IMethod method) {
+	if (this.unitScope == null) return null;
+	// Try to get binding from cache
+	Binding binding = (Binding) this.bindings.get(method);
+	if (binding != null) {
+		if (binding instanceof MethodBinding && binding.isValidBinding())
+			return (MethodBinding) binding;
+		return null;
+	}
+	//	Get binding from unit scope
+	MethodBinding methodBinding = null;
+	String typeName = method.getDeclaringType().getElementName();
+	TypeBinding declaringTypeBinding = getType(typeName, typeName.toCharArray());
+	if (declaringTypeBinding != null) {
+		if (declaringTypeBinding.isArrayType()) {
+			declaringTypeBinding = declaringTypeBinding.leafComponentType();
+		}
+		if (!declaringTypeBinding.isBaseType()) {
+			String[] parameterTypes = method.getParameterTypes();
+			int length = parameterTypes.length;
+			TypeBinding[] parameters = new TypeBinding[length];
+			for (int i=0;  i<length; i++) {
+				parameters[i] = this.unitScope.getType(Signature.toCharArray(parameterTypes[i].toCharArray()));
+			}
+			ReferenceBinding referenceBinding = (ReferenceBinding) declaringTypeBinding;
+			methodBinding = referenceBinding.getExactMethod(method.getElementName().toCharArray(), parameters);
+			this.bindings.put(method, methodBinding);
+			return methodBinding;
+		}
+	}
+	this.bindings.put(method, new ProblemMethodBinding(method.getElementName().toCharArray(), null, ProblemReasons.NotFound));
+	return null;
+}
 protected boolean hasAlreadyDefinedType(CompilationUnitDeclaration parsedUnit) {
 	CompilationResult result = parsedUnit.compilationResult;
 	if (result == null) return false;
@@ -671,10 +767,12 @@
  * Create a new parser for the given project, as well as a lookup environment.
  */
 public void initialize(JavaProject project, int possibleMatchSize) throws JavaModelException {
-	if (this.nameEnvironment != null)
+	// clean up name environment only if there are several possible match as it is reused
+	// when only one possible match (bug 58581)
+	if (this.nameEnvironment != null && possibleMatchSize != 1)
 		this.nameEnvironment.cleanup();
 
-	SearchableEnvironment searchableEnvironment = (SearchableEnvironment) project.newSearchableNameEnvironment(this.workingCopies);
+	SearchableEnvironment searchableEnvironment = project.newSearchableNameEnvironment(this.workingCopies);
 	
 	// if only one possible match, a file name environment costs too much,
 	// so use the existing searchable  environment which will populate the java model
@@ -712,15 +810,20 @@
 			PossibleMatch possibleMatch = possibleMatches[i];
 			try {
 				parseAndBuildBindings(possibleMatch, mustResolve);
-				if (!mustResolve)
+				if (!mustResolve) {
+					if (this.progressMonitor != null) {
+						this.progressWorked++;
+						if ((this.progressWorked%this.progressStep)==0) this.progressMonitor.worked(this.progressStep);
+					}
 					process(possibleMatch, bindingsWereCreated);
+				}
 			} finally {
 				if (!mustResolve)
 					possibleMatch.cleanUp();
 			}
 		}
 		if (mustResolve)
-			lookupEnvironment.completeTypeBindings();
+			this.lookupEnvironment.completeTypeBindings();
 
 		// create hierarchy resolver if needed
 		IType focusType = getFocusType();
@@ -755,11 +858,15 @@
 			// continue and try next matching openable reporting innacurate matches (since bindings will be null)
 			bindingsWereCreated = false;
 		} finally {
+			if (this.progressMonitor != null) {
+				this.progressWorked++;
+				if ((this.progressWorked%this.progressStep)==0) this.progressMonitor.worked(this.progressStep);
+			}
 			if (this.options.verbose)
 				System.out.println(Util.bind("compilation.done", //$NON-NLS-1$
 					new String[] {
 						String.valueOf(i + 1),
-						String.valueOf(numberOfMatches),
+						String.valueOf(this.numberOfMatches),
 						new String(possibleMatch.parsedUnit.getFileName())}));
 			// cleanup compilation unit result
 			possibleMatch.cleanUp();
@@ -769,30 +876,41 @@
 /**
  * Locate the matches amongst the possible matches.
  */
-protected void locateMatches(JavaProject javaProject, PossibleMatchSet matchSet) throws CoreException {
+protected void locateMatches(JavaProject javaProject, PossibleMatchSet matchSet, int expected) throws CoreException {
 	PossibleMatch[] possibleMatches = matchSet.getPossibleMatches(javaProject.getPackageFragmentRoots());
-	for (int index = 0, length = possibleMatches.length; index < length;) {
+	int length = possibleMatches.length;
+	// increase progress from duplicate matches not stored in matchSet while adding...
+	if (this.progressMonitor != null && expected>length) {
+		this.progressWorked += expected-length;
+		this.progressMonitor.worked( expected-length);
+	}
+	// locate matches (processed matches are limited to avoid problem while using VM default memory heap size)
+	for (int index = 0; index < length;) {
 		int max = Math.min(MAX_AT_ONCE, length - index);
 		locateMatches(javaProject, possibleMatches, index, max);
 		index += max;
-		if (this.progressMonitor != null)
-			this.progressMonitor.worked(max);
 	}
 }
 /**
  * Locate the matches in the given files and report them using the search requestor. 
  */
 public void locateMatches(SearchDocument[] searchDocuments) throws CoreException {
-	if (SearchEngine.VERBOSE) {
+	int docsLength = searchDocuments.length;
+	if (SearchBasicEngine.VERBOSE) {
 		System.out.println("Locating matches in documents ["); //$NON-NLS-1$
-		for (int i = 0, length = searchDocuments.length; i < length; i++)
+		for (int i = 0; i < docsLength; i++)
 			System.out.println("\t" + searchDocuments[i]); //$NON-NLS-1$
 		System.out.println("]"); //$NON-NLS-1$
 	}
-	
+
+	// init infos for progress increasing
+	int n = docsLength<1000 ? Math.min(Math.max(docsLength/200+1, 2),4) : 5 *(docsLength/1000);
+	this.progressStep = docsLength < n ? 1 : docsLength / n; // step should not be 0
+	this.progressWorked = 0;
+
 	// extract working copies
 	ArrayList copies = new ArrayList();
-	for (int i = 0, length = searchDocuments.length; i < length; i++) {
+	for (int i = 0; i < docsLength; i++) {
 		SearchDocument document = searchDocuments[i];
 		if (document instanceof WorkingCopyDocument) {
 			copies.add(((WorkingCopyDocument)document).workingCopy);
@@ -803,6 +921,7 @@
 	copies.toArray(this.workingCopies);
 
 	JavaModelManager manager = JavaModelManager.getJavaModelManager();
+	this.bindings = new SimpleLookupTable();
 	try {
 		// optimize access to zip files during search operation
 		manager.cacheZipFiles();
@@ -819,22 +938,27 @@
 		this.patternLocator.initializePolymorphicSearch(this);
 
 		JavaProject previousJavaProject = null;
-		int skipped = 0;
 		PossibleMatchSet matchSet = new PossibleMatchSet();
 		Util.sort(searchDocuments, new Util.Comparer() {
 			public int compare(Object a, Object b) {
 				return ((SearchDocument)a).getPath().compareTo(((SearchDocument)b).getPath());
 			}
 		}); 
-		for (int i = 0, l = searchDocuments.length; i < l; i++) {
-			if (this.progressMonitor != null && this.progressMonitor.isCanceled())
+		int displayed = 0; // progress worked displayed
+		for (int i = 0; i < docsLength; i++) {
+			if (this.progressMonitor != null && this.progressMonitor.isCanceled()) {
 				throw new OperationCanceledException();
+			}
 
 			// skip duplicate paths
 			SearchDocument searchDocument = searchDocuments[i];
 			String pathString = searchDocument.getPath();
 			if (i > 0 && pathString.equals(searchDocuments[i - 1].getPath())) {
-				skipped++;
+				if (this.progressMonitor != null) {
+					this.progressWorked++;
+					if ((this.progressWorked%this.progressStep)==0) this.progressMonitor.worked(this.progressStep);
+				}
+				displayed++;
 				continue;
 			}
 
@@ -845,7 +969,14 @@
 				openable = (Openable) workingCopy;
 			} else {
 				openable = this.handleFactory.createOpenable(pathString, this.scope);
-				if (openable == null) continue; // match is outside classpath
+				if (openable == null) {
+					if (this.progressMonitor != null) {
+						this.progressWorked++;
+						if ((this.progressWorked%this.progressStep)==0) this.progressMonitor.worked(this.progressStep);
+					}
+					displayed++;
+					continue; // match is outside classpath
+				}
 			}
 
 			// create new parser and lookup environment if this is a new project
@@ -858,30 +989,25 @@
 				// locate matches in previous project
 				if (previousJavaProject != null) {
 					try {
-						locateMatches(previousJavaProject, matchSet);
+						locateMatches(previousJavaProject, matchSet, i-displayed);
+						displayed = i;
 					} catch (JavaModelException e) {
 						// problem with classpath in this project -> skip it
 					}
-					if (this.progressMonitor != null)
-						this.progressMonitor.worked(skipped);
 					matchSet.reset();
 				}
 				previousJavaProject = javaProject;
-				skipped = 0;
 			}
 			matchSet.add(new PossibleMatch(this, resource, openable, searchDocument));
-			skipped++;
 		}
 
 		// last project
 		if (previousJavaProject != null) {
 			try {
-				locateMatches(previousJavaProject, matchSet);
+				locateMatches(previousJavaProject, matchSet, docsLength-displayed);
 			} catch (JavaModelException e) {
 				// problem with classpath in last project -> ignore
 			}
-			if (this.progressMonitor != null)
-				this.progressMonitor.worked(skipped);
 		} 
 
 		if (this.progressMonitor != null)
@@ -890,7 +1016,8 @@
 		if (this.nameEnvironment != null)
 			this.nameEnvironment.cleanup();
 		manager.flushZipFiles();
-	}	
+		this.bindings = null;
+	}
 }
 /**
  * Locates the package declarations corresponding to this locator's pattern. 
@@ -921,12 +1048,31 @@
 		IJavaProject[] projects = JavaModelManager.getJavaModelManager().getJavaModel().getJavaProjects();
 		for (int i = 0, length = projects.length; i < length; i++) {
 			IJavaProject javaProject = projects[i];
-			IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
+			IPackageFragmentRoot[] roots = null;
+			try {
+				roots = javaProject.getPackageFragmentRoots();
+			} catch (JavaModelException e) {
+				// java project doesn't exist -> continue with next project (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=75561)
+				continue;
+			}
 			for (int j = 0, rootsLength = roots.length; j < rootsLength; j++) {
-				IJavaElement[] pkgs = roots[j].getChildren();
+				IJavaElement[] pkgs = null;
+				try {
+					pkgs = roots[j].getChildren();
+				} catch (JavaModelException e) {
+					// pkg fragment root doesn't exist -> continue with next root (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=75561)
+					continue;
+				}
 				for (int k = 0, pksLength = pkgs.length; k < pksLength; k++) {
 					IPackageFragment pkg = (IPackageFragment) pkgs[k];
-					if (pkg.getChildren().length > 0 
+					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())) {
 						IResource resource = pkg.getResource();
 						if (resource == null) // case of a file in an external jar
@@ -967,7 +1113,7 @@
 			typeName,
 			pkgs[i], 
 			false, 
-			typeBinding.isClass() ? NameLookup.ACCEPT_CLASSES : NameLookup.ACCEPT_INTERFACES);
+			typeBinding.isClass() ? NameLookup.ACCEPT_CLASSES : NameLookup.ACCEPT_INTERFACES); // TODO (frederic) should distinguish ENUMS and ANNOTATIONS
 		if (type != null) return type;
 	}
 
@@ -1014,6 +1160,8 @@
 			return new MethodDeclarationMatch(element, accuracy, offset, length, participant, resource);
 		case IJavaElement.LOCAL_VARIABLE:
 			return new LocalVariableDeclarationMatch(element, accuracy, offset, length, participant, resource);
+		case IJavaElement.PACKAGE_DECLARATION:
+			return new PackageDeclarationMatch(element, accuracy, offset, length, participant, resource);
 		default:
 			return null;
 	}
@@ -1056,11 +1204,13 @@
 		int accuracy,
 		int offset,  
 		int length,
+		boolean isConstructor,
+		boolean isSynthetic,
 		ASTNode reference) {
 	SearchParticipant participant = getParticipant(); 
 	IResource resource = this.currentPossibleMatch.resource;
 	boolean insideDocComment = (reference.bits & ASTNode.InsideJavadoc) != 0;
-	return new MethodReferenceMatch(enclosingElement, accuracy, offset, length, insideDocComment, participant, resource);
+	return new MethodReferenceMatch(enclosingElement, accuracy, offset, length, isConstructor, isSynthetic, insideDocComment, participant, resource);
 }
 
 public SearchMatch newPackageReferenceMatch(
@@ -1087,6 +1237,18 @@
 	return new TypeReferenceMatch(enclosingElement, accuracy, offset, length, insideDocComment, participant, resource);
 }
 
+public SearchMatch newTypeReferenceMatch(
+		IJavaElement enclosingElement,
+		int accuracy,
+		int offset,  
+		int length,
+		int rule,
+		ASTNode reference) {
+	SearchMatch match = newTypeReferenceMatch(enclosingElement, accuracy, offset, length, reference);
+	match.setMatchRule(rule);
+	return match;
+}
+
 /*
  * Process a compilation unit already parsed and build.
  */
@@ -1108,13 +1270,17 @@
 		getMethodBodies(unit);
 
 		if (bindingsWereCreated && ((InternalSearchPattern)this.pattern).mustResolve && unit.types != null) {
-			if (SearchEngine.VERBOSE)
+			if (SearchBasicEngine.VERBOSE)
 				System.out.println("Resolving " + this.currentPossibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$
 
 			reduceParseTree(unit);
 
-			if (unit.scope != null)
-				unit.scope.faultInTypes(); // fault in fields & methods
+			if (unit.scope != null) {
+				// fault in fields & methods
+				unit.scope.faultInTypes();
+				// verify inherited methods
+				unit.scope.verifyMethods(this.lookupEnvironment.methodVerifier());
+			}
 			unit.resolve();
 
 			reportMatching(unit, true);
@@ -1173,7 +1339,7 @@
 
 protected void report(SearchMatch match) throws CoreException {
 	long start = -1;
-	if (SearchEngine.VERBOSE) {
+	if (SearchBasicEngine.VERBOSE) {
 		start = System.currentTimeMillis();
 		System.out.println("Reporting match"); //$NON-NLS-1$
 		System.out.println("\tResource: " + match.getResource()); //$NON-NLS-2$//$NON-NLS-1$
@@ -1182,9 +1348,21 @@
 		System.out.println(match.getAccuracy() == SearchMatch.A_ACCURATE
 			? "\tAccuracy: EXACT_MATCH" //$NON-NLS-1$
 			: "\tAccuracy: POTENTIAL_MATCH"); //$NON-NLS-1$
+		System.out.print("\tMatch rule: "); //$NON-NLS-1$
+		if ((match.getMatchRule() & SearchPattern.R_EQUIVALENT_MATCH) != 0) {
+			if ((match.getMatchRule() & SearchPattern.R_ERASURE_MATCH) != 0) {
+				System.out.println("EQUIVALENT + ERASURE"); //$NON-NLS-1$
+			} else {
+				System.out.println("EQUIVALENT"); //$NON-NLS-1$
+			}
+		} else if ((match.getMatchRule() & SearchPattern.R_ERASURE_MATCH) != 0) {
+			System.out.println("ERASURE"); //$NON-NLS-1$
+		} else {
+			System.out.println("PERFECT"); //$NON-NLS-1$
+		}
 	}
 	this.requestor.acceptSearchMatch(match);
-	if (SearchEngine.VERBOSE)
+	if (SearchBasicEngine.VERBOSE)
 		this.resultCollectorTime += System.currentTimeMillis()-start;
 }
 /**
@@ -1193,6 +1371,9 @@
  * to the search requestor.
  */
 protected void reportAccurateTypeReference(ASTNode typeRef, char[] name, IJavaElement element, int accuracy) throws CoreException {
+	reportAccurateTypeReference(typeRef, name, element, accuracy, SearchPattern.R_EXACT_MATCH);
+}
+protected void reportAccurateTypeReference(ASTNode typeRef, char[] name, IJavaElement element, int accuracy, int rule) throws CoreException {
 	if (accuracy == -1) return;
 	if (!encloses(element)) return;
 
@@ -1215,14 +1396,114 @@
 		}
 		if (token == TerminalTokens.TokenNameIdentifier && this.pattern.matchesName(name, scanner.getCurrentTokenSource())) {
 			int length = scanner.currentPosition-currentPosition;
-			SearchMatch match = newTypeReferenceMatch(element, accuracy, currentPosition, length, typeRef);
+			SearchMatch match = newTypeReferenceMatch(element, accuracy, currentPosition, length, rule, typeRef);
 			report(match);
 			return;
 		}
 	} while (token != TerminalTokens.TokenNameEOF);
-	SearchMatch match = newTypeReferenceMatch(element, accuracy, sourceStart, sourceEnd-sourceStart+1, typeRef);
+	SearchMatch match = newTypeReferenceMatch(element, accuracy, sourceStart, sourceEnd-sourceStart+1, rule, typeRef);
 	report(match);
 }
+
+/**
+ * @since 3.1
+ * Finds the accurate positions of the sequence of tokens given by qualifiedName
+ * in the source and reports a reference to this parameterized type name
+ * to the search requestor.
+ */
+protected void reportAccurateParameterizedTypeReference(TypeReference typeRef, int start, int index, TypeReference[] typeArguments, IJavaElement element, int accuracy, int rule) throws CoreException {
+	if (accuracy == -1) return;
+	if (!encloses(element)) return;
+
+	// If there's type arguments, look for end (ie. char '>') of last one.
+	int end = typeRef.sourceEnd;
+	if (typeArguments != null) {
+		// Initialize scanner
+		Scanner scanner = this.parser.scanner;
+		char[] source = this.currentPossibleMatch.getContents();
+		scanner.setSource(source);
+
+		
+		JavaSearchPattern javaSearchPattern = (JavaSearchPattern)this.pattern;
+		if (javaSearchPattern.isErasureMatch || javaSearchPattern.typeSignatures == null) {
+			// if pattern is erasure only, then select the end of the reference
+			if (typeRef instanceof QualifiedTypeReference && index >= 0) {
+				long[] positions = ((QualifiedTypeReference) typeRef).sourcePositions;
+				end = (int) positions[index];
+			} else if (typeRef instanceof ArrayTypeReference) {
+				end = ((ArrayTypeReference) typeRef).originalSourceEnd;
+			}
+		}  else {
+			// Set scanner position at end of last type argument
+			scanner.resetTo(end, source.length-1);
+			int depth = 0;
+			for (int i=typeArguments.length-1; i>=0; i--) {
+				if (typeArguments[i] != null) {
+					depth = resetScannerAfterLastTypeArgumentEnd(typeArguments[i], scanner, depth)+1;
+					break;
+				}
+			}
+	
+			// Now, scan to search next closing '>'
+			while (depth-- > 0) {
+				while (!scanner.atEnd()) {
+					if (scanner.getNextChar() == '>') {
+						end = scanner.currentPosition - 1;
+						break;
+					}
+				}
+			}
+	 	}
+	}
+	
+	// Report match
+	SearchMatch match = newTypeReferenceMatch(element, accuracy, start, end-start+1, rule, typeRef);
+	report(match);
+}
+/* (non-Javadoc)
+ * Reset scanner after last type argument end. This may be called recursively for nested parameterized
+ * type arguments.
+ * Returns depth of nesting for the last argument.
+ */
+private int resetScannerAfterLastTypeArgumentEnd(TypeReference typeRef, Scanner scanner, int depth) {
+	// Default end is current type argument end
+	int end = typeRef.sourceEnd;
+	// Get last list of type arguments for parameterized qualified type reference
+	TypeReference[] typeArguments = null;
+	if (typeRef instanceof ParameterizedQualifiedTypeReference) {
+		ParameterizedQualifiedTypeReference pqtRef = (ParameterizedQualifiedTypeReference) typeRef;
+		TypeReference[] last = null;
+		for (int i=pqtRef.typeArguments.length-1; i>=0 && last==null; i--) {
+			last = pqtRef.typeArguments[i];
+		}
+		// If no children arguments then current type reference is the last type argument
+		if (last == null) {
+			scanner.resetTo(end+1, scanner.eofPosition-1);
+			return depth;
+		}
+		typeArguments = last;
+	}
+	// Get last type argument for single type reference of last list of argument of parameterized qualified type reference
+	if (typeRef instanceof ParameterizedSingleTypeReference || typeArguments != null) {
+		if (typeArguments == null) {
+			typeArguments = ((ParameterizedSingleTypeReference)typeRef).typeArguments;
+		}
+		TypeReference last = null;
+		for (int i=typeArguments.length-1; i>=0 && last==null; i++) {
+			last = typeArguments[i];
+		}
+		// If no child argument then current type reference is the last type argument
+		if (last == null) {
+			scanner.resetTo(end+1, scanner.eofPosition-1);
+			return depth;
+		}
+		// Loop on last type argument to find its last type argument...
+		return resetScannerAfterLastTypeArgumentEnd(last, scanner, depth+1);
+	}
+	// Current type reference is not parameterized. So, it is the last type argument
+	scanner.resetTo(end+1, scanner.eofPosition-1);
+	return depth;
+}
 /**
  * Finds the accurate positions of each valid token in the source and
  * reports a reference to this token to the search requestor.
@@ -1297,11 +1578,11 @@
 	ClassFile classFile = (ClassFile) binaryMember.getClassFile();
 	ISourceRange range = classFile.isOpen() ? binaryMember.getNameRange() : SourceMapper.fgUnknownRange;
 	if (range.getOffset() == -1) {
-		SourceMapper mapper = classFile.getSourceMapper();
-		if (mapper != null) {
-			IType type = classFile.getType();
-			String sourceFileName = mapper.findSourceFileName(type, info);
-			if (sourceFileName != null) {
+		BinaryType type = (BinaryType) classFile.getType();
+		String sourceFileName = type.sourceFileName(info);
+		if (sourceFileName != null) {
+			SourceMapper mapper = classFile.getSourceMapper();
+			if (mapper != null) {
 				char[] contents = mapper.findSource(type, sourceFileName);
 				if (contents != null)
 					range = mapper.mapSource(type, contents, binaryMember);
@@ -1334,7 +1615,7 @@
 			}
 			if (encloses(enclosingElement)) {
 				int length = scanner.currentPosition - nameSourceStart;
-				SearchMatch match = newDeclarationMatch(enclosingElement, accuracy, nameSourceStart, length);
+				SearchMatch match = this.patternLocator.newDeclarationMatch(method, enclosingElement, accuracy, length, this);
 				report(match);
 			}
 		}
@@ -1352,6 +1633,19 @@
 		}
 	}
 
+	// report annotations
+	if (method.annotations != null) {
+		for (int i=0, al=method.annotations.length; i<al; i++) {
+			TypeReference typeRef = method.annotations[i].type;
+			Integer level = (Integer) nodeSet.matchingNodes.removeKey(typeRef);
+			if (level != null) {
+				if (enclosingElement == null)
+					enclosingElement = createHandle(method, parent);
+				this.patternLocator.matchReportReference(typeRef, enclosingElement, level.intValue(), this);
+			}
+		}
+	}
+
 	// references in this method
 	if (typeInHierarchy) {
 		ASTNode[] nodes = nodeSet.matchingNodes(method.declarationSourceStart, method.declarationSourceEnd);
@@ -1379,6 +1673,7 @@
 protected void reportMatching(CompilationUnitDeclaration unit, boolean mustResolve) throws CoreException {
 	MatchingNodeSet nodeSet = this.currentPossibleMatch.nodeSet;
 	if (mustResolve) {
+		this.unitScope= unit.scope.compilationUnitScope();
 		// move the possible matching nodes that exactly match the search pattern to the matching nodes set
 		Object[] nodes = nodeSet.possibleMatchingNodesSet.values;
 		for (int i = 0, l = nodes.length; i < l; i++) {
@@ -1386,44 +1681,20 @@
 			if (node == null) continue;
 			if (node instanceof ImportReference) {
 				// special case for import refs: they don't know their binding
-				// import ref cannot be in the hirarchy of a type
+				// import ref cannot be in the hierarchy of a type
 				if (this.hierarchyResolver != null) continue;
 
 				ImportReference importRef = (ImportReference) node;
 				Binding binding = importRef.onDemand
-					? unit.scope.getTypeOrPackage(CharOperation.subarray(importRef.tokens, 0, importRef.tokens.length))
-					: unit.scope.getTypeOrPackage(importRef.tokens);
+					? unitScope.getImport(CharOperation.subarray(importRef.tokens, 0, importRef.tokens.length), true, importRef.isStatic())
+					: unitScope.getImport(importRef.tokens, false, importRef.isStatic());
 				this.patternLocator.matchLevelAndReportImportRef(importRef, binding, this);
-			} else {
-				if (node instanceof JavadocSingleTypeReference) {
-					// special case for javadoc single type reference
-					JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) node;
-					if (singleRef.packageBinding != null) {
-						char[][] tokens = new char[][] { singleRef.token };
-						long[] positions = new long[] { (((long) singleRef.sourceStart) << 32) + singleRef.sourceEnd };
-						int tagStart = singleRef.tagSourceStart;
-						int tagEnd = singleRef.tagSourceEnd;
-						JavadocImportReference importRef = new JavadocImportReference(tokens, positions, tagStart, tagEnd);
-						this.patternLocator.matchLevelAndReportImportRef(importRef, singleRef.packageBinding, this);
-						continue;
-					}
-				} else if (node instanceof JavadocQualifiedTypeReference) {
-					// special case for javadoc qualified type reference
-					JavadocQualifiedTypeReference qualifRef = (JavadocQualifiedTypeReference) node;
-					if (qualifRef.packageBinding != null) {
-						char[][] tokens = qualifRef.tokens;
-						long[] positions = qualifRef.sourcePositions;
-						int tagStart = qualifRef.tagSourceStart;
-						int tagEnd = qualifRef.tagSourceEnd;
-						JavadocImportReference importRef = new JavadocImportReference(tokens, positions, tagStart, tagEnd);
-						this.patternLocator.matchLevelAndReportImportRef(importRef, qualifRef.packageBinding, this);
-						continue;
-					}
-				}
 			}
 			nodeSet.addMatch(node, this.patternLocator.resolveLevel(node));
 		}
 		nodeSet.possibleMatchingNodesSet = new SimpleSet(3);
+	} else {
+		this.unitScope = null;
 	}
 
 	if (nodeSet.matchingNodes.elementSize == 0) return; // no matching nodes were found
@@ -1484,8 +1755,23 @@
 		}
 	}
 
+	// report annotations
+	if (field.annotations != null) {
+		for (int i=0, al=field.annotations.length; i<al; i++) {
+			TypeReference typeRef = field.annotations[i].type;
+			Integer level = (Integer) nodeSet.matchingNodes.removeKey(typeRef);
+			if (level != null) {
+				if (enclosingElement == null)
+					enclosingElement = createHandle(field, type, parent);
+				this.patternLocator.matchReportReference(typeRef, enclosingElement, level.intValue(), this);
+			}
+		}
+	}
+
 	if (typeInHierarchy) {
-		ASTNode[] nodes = nodeSet.matchingNodes(field.declarationSourceStart, field.declarationSourceEnd);
+		// 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);
 		if (nodes != null) {
 			if ((this.matchContainer & PatternLocator.FIELD_CONTAINER) == 0) {
 				for (int i = 0, l = nodes.length; i < l; i++)
@@ -1526,13 +1812,47 @@
 	// report the type declaration
 	if (accuracy > -1 && encloses(enclosingElement)) {
 		int offset = type.sourceStart;
-		SearchMatch match = newDeclarationMatch(enclosingElement, accuracy, offset, type.sourceEnd-offset+1);
+		SearchMatch match = this.patternLocator.newDeclarationMatch(type, enclosingElement, accuracy, type.sourceEnd-offset+1, this);
 		report(match);
 	}
 
 	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) {
+				if (typeParameter.type != null) {
+					Integer level = (Integer) nodeSet.matchingNodes.removeKey(typeParameter.type);
+					if (level != null && matchedClassContainer) {
+						this.patternLocator.matchReportReference(typeParameter.type, enclosingElement, level.intValue(), this);
+					}
+				}
+				if (typeParameter.bounds != null) {
+					for (int j=0, b=typeParameter.bounds.length; j<b; j++) {
+						Integer level = (Integer) nodeSet.matchingNodes.removeKey(typeParameter.bounds[j]);
+						if (level != null && matchedClassContainer) {
+							this.patternLocator.matchReportReference(typeParameter.bounds[j], enclosingElement, level.intValue(), this);
+						}
+					}
+				}
+			}
+		}
+	}
 
-	// javadoc
+	// report annotations
+	if (type.annotations != null) {
+		for (int i=0, al=type.annotations.length; i<al; i++) {
+			TypeReference typeRef = type.annotations[i].type;
+			Integer level = (Integer) nodeSet.matchingNodes.removeKey(typeRef);
+			if (level != null && matchedClassContainer) {
+				this.patternLocator.matchReportReference(typeRef, enclosingElement, level.intValue(), this);
+			}
+		}
+	}
+
+	// report references in javadoc
 	if (type.javadoc != null) {
 		ASTNode[] nodes = nodeSet.matchingNodes(type.declarationSourceStart, type.sourceStart);
 		if (nodes != null) {
@@ -1561,17 +1881,12 @@
 	} else {
 		TypeReference superClass = type.superclass;
 		if (superClass != null) {
-			Integer level = (Integer) nodeSet.matchingNodes.removeKey(superClass);
-			if (level != null && matchedClassContainer)
-				this.patternLocator.matchReportReference(superClass, enclosingElement, level.intValue(), this);
+			reportMatchingSuper(superClass, enclosingElement, nodeSet, matchedClassContainer);
 		}
 		TypeReference[] superInterfaces = type.superInterfaces;
 		if (superInterfaces != null) {
 			for (int i = 0, l = superInterfaces.length; i < l; i++) {
-				TypeReference superInterface = superInterfaces[i];
-				Integer level = (Integer) nodeSet.matchingNodes.removeKey(superInterface);
-				if (level != null && matchedClassContainer)
-					this.patternLocator.matchReportReference(superInterface, enclosingElement, level.intValue(), this);
+				reportMatchingSuper(superInterfaces[i], enclosingElement, nodeSet, matchedClassContainer);
 			}
 		}
 	}
@@ -1613,6 +1928,42 @@
 		}
 	}
 }
+protected void reportMatchingSuper(TypeReference superReference, IJavaElement enclosingElement, MatchingNodeSet nodeSet, boolean matchedClassContainer) throws CoreException {
+	ASTNode[] nodes = null;
+	if (superReference instanceof ParameterizedSingleTypeReference) {
+		TypeReference[] typeArguments = ((ParameterizedSingleTypeReference)superReference).typeArguments;
+		if (typeArguments != null && typeArguments.length > 0) {
+			nodes = nodeSet.matchingNodes(superReference.sourceStart, typeArguments[typeArguments.length-1].sourceEnd);
+		}
+	} else if (superReference instanceof ParameterizedQualifiedTypeReference) {
+		TypeReference[][] typeArguments = ((ParameterizedQualifiedTypeReference)superReference).typeArguments;
+		if (typeArguments != null && typeArguments.length > 0) {
+			TypeReference[] lastTypeArgs = typeArguments[typeArguments.length-1];
+			int end = superReference.sourceEnd;
+			if (lastTypeArgs != null && lastTypeArgs.length > 0 && lastTypeArgs[lastTypeArgs.length-1].sourceEnd > end) {
+				end = lastTypeArgs[lastTypeArgs.length-1].sourceEnd;
+			}
+			nodes = nodeSet.matchingNodes(superReference.sourceStart, end);
+		}
+	}
+	if (nodes != null) {
+		if ((this.matchContainer & PatternLocator.CLASS_CONTAINER) == 0) {
+			for (int i = 0, l = nodes.length; i < l; i++)
+				nodeSet.matchingNodes.removeKey(nodes[i]);
+		} else {
+			if (encloses(enclosingElement))
+				for (int i = 0, l = nodes.length; i < l; i++) {
+					ASTNode node = nodes[i];
+					Integer level = (Integer) nodeSet.matchingNodes.removeKey(node);
+					this.patternLocator.matchReportReference(node, enclosingElement, level.intValue(), this);
+				}
+		}
+	} else {
+		Integer level = (Integer) nodeSet.matchingNodes.removeKey(superReference);
+		if (level != null && matchedClassContainer)
+			this.patternLocator.matchReportReference(superReference, enclosingElement, level.intValue(), this);
+	}
+}
 protected boolean typeInHierarchy(ReferenceBinding binding) {
 	if (this.hierarchyResolver == null) return true; // not a hierarchy scope
 	if (this.hierarchyResolver.subOrSuperOfFocus(binding)) return true;
@@ -1625,5 +1976,4 @@
 	}
 	return false;
 }
-
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
index ed74b1d..c696ec3 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
@@ -101,7 +101,7 @@
 	super.checkComment();
 	if (this.javadocParser.checkDocComment && this.javadoc != null) {
 		// Search for pattern locator matches in javadoc comment @throws/@exception tags
-		TypeReference[] thrownExceptions = this.javadoc.thrownExceptions;
+		TypeReference[] thrownExceptions = this.javadoc.exceptionReferences;
 		int throwsTagsLength = thrownExceptions == null ? 0 : thrownExceptions.length;
 		for (int i = 0; i < throwsTagsLength; i++) {
 			TypeReference typeRef = thrownExceptions[i];
@@ -109,7 +109,7 @@
 		}
 
 		// Search for pattern locator matches in javadoc comment @see tags
-		Expression[] references = this.javadoc.references;
+		Expression[] references = this.javadoc.seeReferences;
 		int seeTagsLength = references == null ? 0 : references.length;
 		for (int i = 0; i < seeTagsLength; i++) {
 			Expression reference = references[i];
@@ -130,12 +130,29 @@
 					TypeReference typeRef = (TypeReference) messageSend.receiver;
 					this.patternLocator.match(typeRef, this.nodeSet);
 				}
+				if (messageSend.arguments != null) {
+					for (int a=0,al=messageSend.arguments.length; a<al; a++) {
+						JavadocArgumentExpression argument = (JavadocArgumentExpression) messageSend.arguments[a];
+						if (argument.argument != null && argument.argument.type != null) {
+							this.patternLocator.match(argument.argument.type, this.nodeSet);
+						}
+					}
+				}
 			} else if (reference instanceof JavadocAllocationExpression) {
 				JavadocAllocationExpression constructor = (JavadocAllocationExpression) reference;
 				this.patternLocator.match(constructor, this.nodeSet);
 				if (constructor.type != null && !constructor.type.isThis()) {
 					this.patternLocator.match(constructor.type, this.nodeSet);
 				}
+				if (constructor.arguments != null) {
+					for (int a=0,al=constructor.arguments.length; a<al; a++) {
+						this.patternLocator.match(constructor.arguments[a], this.nodeSet);
+						JavadocArgumentExpression argument = (JavadocArgumentExpression) constructor.arguments[a];
+						if (argument.argument != null && argument.argument.type != null) {
+							this.patternLocator.match(argument.argument.type, this.nodeSet);
+						}
+					}
+				}
 			}
 		}
 	}
@@ -144,6 +161,13 @@
 	super.classInstanceCreation(alwaysQualified);
 	this.patternLocator.match(this.expressionStack[this.expressionPtr], this.nodeSet);
 }
+protected void consumeAnnotationAsModifier() {
+	super.consumeAnnotationAsModifier();
+	Expression expression = this.expressionStack[this.expressionPtr];
+	if (expression instanceof Annotation) {
+		this.patternLocator.match(((Annotation)expression).type, this.nodeSet);
+	}
+}
 protected void consumeAssignment() {
 	super.consumeAssignment();
 	this.patternLocator.match(this.expressionStack[this.expressionPtr], this.nodeSet);
@@ -152,6 +176,10 @@
 	super.consumeExplicitConstructorInvocation(flag, recFlag);
 	this.patternLocator.match(this.astStack[this.astPtr], this.nodeSet);
 }
+protected void consumeExplicitConstructorInvocationWithTypeArguments(int flag, int recFlag) {
+	super.consumeExplicitConstructorInvocationWithTypeArguments(flag, recFlag);
+	this.patternLocator.match(this.astStack[this.astPtr], this.nodeSet);
+}
 protected void consumeFieldAccess(boolean isSuperAccess) {
 	super.consumeFieldAccess(isSuperAccess);
 
@@ -170,24 +198,51 @@
 	// this is always a MessageSend
 	this.patternLocator.match((MessageSend) this.expressionStack[this.expressionPtr], this.nodeSet);
 }
+protected void consumeMethodInvocationNameWithTypeArguments() {
+	super.consumeMethodInvocationNameWithTypeArguments();
+
+	// this is always a MessageSend
+	this.patternLocator.match((MessageSend) this.expressionStack[this.expressionPtr], this.nodeSet);
+}
 protected void consumeMethodInvocationPrimary() {
 	super.consumeMethodInvocationPrimary(); 
 
 	// this is always a MessageSend
 	this.patternLocator.match((MessageSend) this.expressionStack[this.expressionPtr], this.nodeSet);
 }
+protected void consumeMethodInvocationPrimaryWithTypeArguments() {
+	super.consumeMethodInvocationPrimaryWithTypeArguments();
+
+	// this is always a MessageSend
+	this.patternLocator.match((MessageSend) this.expressionStack[this.expressionPtr], this.nodeSet);
+}
 protected void consumeMethodInvocationSuper() {
 	super.consumeMethodInvocationSuper();
 
 	// this is always a MessageSend
 	this.patternLocator.match((MessageSend) this.expressionStack[this.expressionPtr], this.nodeSet);
 }
+protected void consumeMethodInvocationSuperWithTypeArguments() {
+	super.consumeMethodInvocationSuperWithTypeArguments();
+
+	// this is always a MessageSend
+	this.patternLocator.match((MessageSend) this.expressionStack[this.expressionPtr], this.nodeSet);
+}
 protected void consumePrimaryNoNewArray() {
 	// pop parenthesis positions (and don't update expression positions
 	// (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=23329)
 	intPtr--;
 	intPtr--;
 }
+
+protected void consumePrimaryNoNewArrayWithName() {
+	// PrimaryNoNewArray ::=  PushLPAREN Expression PushRPAREN 
+	pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+	// pop parenthesis positions (and don't update expression positions
+	// (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=23329)
+	intPtr--;
+	intPtr--;
+}
 protected void consumeUnaryExpression(int op, boolean post) {
 	super.consumeUnaryExpression(op, post);
 	this.patternLocator.match(this.expressionStack[this.expressionPtr], this.nodeSet);
@@ -281,6 +336,14 @@
 protected ImportMatchLocatorParser(ProblemReporter problemReporter, MatchLocator locator) {
 	super(problemReporter, locator);
 }
+protected void consumeStaticImportOnDemandDeclarationName() {
+	super.consumeStaticImportOnDemandDeclarationName();
+	this.patternLocator.match(this.astStack[this.astPtr], this.nodeSet);
+}
+protected void consumeSingleStaticImportDeclarationName() {
+	super.consumeSingleStaticImportDeclarationName();
+	this.patternLocator.match(this.astStack[this.astPtr], this.nodeSet);
+}
 protected void consumeSingleTypeImportDeclarationName() {
 	super.consumeSingleTypeImportDeclarationName();
 	this.patternLocator.match(this.astStack[this.astPtr], this.nodeSet);
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchingNodeSet.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchingNodeSet.java
index 37decce..7f4f4e0 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchingNodeSet.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchingNodeSet.java
@@ -13,9 +13,10 @@
 import java.util.ArrayList;
 
 import org.eclipse.jdt.core.search.SearchMatch;
+import org.eclipse.jdt.core.search.SearchPattern;
 import org.eclipse.jdt.internal.compiler.ast.*;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfLong;
-import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.core.util.SimpleSet;
 import org.eclipse.jdt.internal.core.util.Util;
 
@@ -32,6 +33,7 @@
 private HashtableOfLong matchingNodesKeys = new HashtableOfLong(3); // sourceRange -> node
 static Integer EXACT_MATCH = new Integer(SearchMatch.A_ACCURATE);
 static Integer POTENTIAL_MATCH = new Integer(SearchMatch.A_INACCURATE);
+static Integer ERASURE_MATCH = new Integer(SearchPattern.R_ERASURE_MATCH);
 
 /**
  * Set of possible matching ast nodes. They need to be resolved
@@ -43,13 +45,16 @@
 public int addMatch(ASTNode node, int matchLevel) {
 	switch (matchLevel) {
 		case PatternLocator.INACCURATE_MATCH:
-			addTrustedMatch(node, false);
+			addTrustedMatch(node, POTENTIAL_MATCH);
 			break;
 		case PatternLocator.POSSIBLE_MATCH:
 			addPossibleMatch(node);
 			break;
+		case PatternLocator.ERASURE_MATCH:
+			addTrustedMatch(node, ERASURE_MATCH);
+			break;
 		case PatternLocator.ACCURATE_MATCH:
-			addTrustedMatch(node, true);
+			addTrustedMatch(node, EXACT_MATCH);
 	}
 	return matchLevel;
 }
@@ -67,6 +72,10 @@
 	this.possibleMatchingNodesKeys.put(key, node);
 }
 public void addTrustedMatch(ASTNode node, boolean isExact) {
+	addTrustedMatch(node, isExact ? EXACT_MATCH : POTENTIAL_MATCH);
+	
+}
+void addTrustedMatch(ASTNode node, Integer level) {
 	// remove existing node at same position from set
 	// (case of recovery that created the same node several time
 	// see http://bugs.eclipse.org/bugs/show_bug.cgi?id=29366)
@@ -76,7 +85,7 @@
 		this.matchingNodes.removeKey(existing);
 	
 	// map node to its accuracy level
-	this.matchingNodes.put(node, isExact ? EXACT_MATCH : POTENTIAL_MATCH);
+	this.matchingNodes.put(node, level);
 	this.matchingNodesKeys.put(key, node);
 }
 protected boolean hasPossibleNodes(int start, int end) {
@@ -147,9 +156,17 @@
 		ASTNode node = (ASTNode) keyTable[i];
 		if (node == null) continue;
 		result.append("\n\t"); //$NON-NLS-1$
-		result.append(valueTable[i] == EXACT_MATCH
-			? "ACCURATE_MATCH: " //$NON-NLS-1$
-			: "INACCURATE_MATCH: "); //$NON-NLS-1$
+		switch (((Integer)valueTable[i]).intValue()) {
+			case SearchMatch.A_ACCURATE:
+				result.append("ACCURATE_MATCH: "); //$NON-NLS-1$
+				break;
+			case SearchMatch.A_INACCURATE:
+				result.append("INACCURATE_MATCH: "); //$NON-NLS-1$
+				break;
+			case SearchPattern.R_ERASURE_MATCH:
+				result.append("ERASURE_MATCH: "); //$NON-NLS-1$
+				break;
+		}
 		node.print(0, result);
 	}
 
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
index 78952df..4b4bee8 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
@@ -81,7 +81,7 @@
 	if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH;
 
 	if (!matchesName(this.pattern.selector, node.selector)) return IMPOSSIBLE_MATCH;
-	if (this.pattern.parameterSimpleNames != null) {
+	if (this.pattern.parameterSimpleNames != null && !this.pattern.varargs) {
 		int length = this.pattern.parameterSimpleNames.length;
 		ASTNode[] args = node.arguments;
 		int argsLength = args == null ? 0 : args.length;
@@ -119,14 +119,27 @@
 	if (parameterCount > -1) {
 		if (method.parameters == null) return INACCURATE_MATCH;
 		if (parameterCount != method.parameters.length) return IMPOSSIBLE_MATCH;
+		if (!method.isValidBinding() && ((ProblemMethodBinding)method).problemId() == ProblemReasons.Ambiguous)
+			// return inaccurate match for ambiguous call (bug 80890)
+			return INACCURATE_MATCH;
 		for (int i = 0; i < parameterCount; i++) {
-			int newLevel = resolveLevelForType(this.pattern.parameterSimpleNames[i], this.pattern.parameterQualifications[i], method.parameters[i]);
+			TypeBinding argType = method.parameters[i];
+			int newLevel = IMPOSSIBLE_MATCH;
+			if (argType.isMemberType()) {
+				// only compare source name for member type (bug 41018)
+				newLevel = CharOperation.match(this.pattern.parameterSimpleNames[i], argType.sourceName(), this.isCaseSensitive)
+					? ACCURATE_MATCH
+					: IMPOSSIBLE_MATCH;
+			} else {
+				newLevel = resolveLevelForType(this.pattern.parameterSimpleNames[i], this.pattern.parameterQualifications[i], method.parameters[i]);
+			}
 			if (level > newLevel) {
 				if (newLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
 				level = newLevel; // can only be downgraded
 			}
 		}
 	}
+
 	return level;
 }
 /**
@@ -144,12 +157,26 @@
 		if (element != null)
 			reportDeclaration(((MessageSend) reference).binding, locator, declPattern.knownMethods);
 	} else if (this.pattern.findReferences && reference instanceof MessageSend) {
+		IJavaElement focus = ((InternalSearchPattern) this.pattern).focus;
+		// verify closest match if pattern was bound
+		// (see bug 70827)
+		if (focus != null && focus.getElementType() == IJavaElement.METHOD) {
+			MethodBinding patternMethodBinding = locator.getMethodBinding((IMethod) focus);
+			if (patternMethodBinding != null && patternMethodBinding.isValidBinding()) {
+				MethodBinding method = ((MessageSend)reference).binding;
+				if (method != null) {
+					method = method.original();
+					if (method != null && patternMethodBinding.isPrivate() && patternMethodBinding.declaringClass != method.declaringClass)
+						return; // finally the match was not possible
+				}
+			}
+		}
 		int offset = (int) (((MessageSend) reference).nameSourcePosition >>> 32);
-		SearchMatch match = locator.newMethodReferenceMatch(element, accuracy, offset, reference.sourceEnd-offset+1, reference);
+		SearchMatch match = locator.newMethodReferenceMatch(element, accuracy, offset, reference.sourceEnd-offset+1, false /*not constructor*/, false/*not synthetic*/, reference);
 		locator.report(match);
 	} else {
 		int offset = reference.sourceStart;
-		SearchMatch match = locator.newMethodReferenceMatch(element, accuracy, offset, reference.sourceEnd-offset+1, reference);
+		SearchMatch match = locator.newMethodReferenceMatch(element, accuracy, offset, reference.sourceEnd-offset+1, false /*not constructor*/, false/*not synthetic*/, reference);
 		locator.report(match);
 	}
 }
@@ -180,6 +207,8 @@
 		info = locator.getBinaryInfo((org.eclipse.jdt.internal.core.ClassFile)type.getClassFile(), resource);
 		locator.reportBinaryMemberDeclaration(resource, method, info, SearchMatch.A_ACCURATE);
 	} else {
+		if (declaringClass instanceof ParameterizedTypeBinding)
+			declaringClass = ((ParameterizedTypeBinding) declaringClass).type;
 		ClassScope scope = ((SourceTypeBinding) declaringClass).scope;
 		if (scope != null) {
 			TypeDeclaration typeDecl = scope.referenceContext;
@@ -210,7 +239,7 @@
 	if (binding == null) return INACCURATE_MATCH;
 	if (!(binding instanceof MethodBinding)) return IMPOSSIBLE_MATCH;
 
-	MethodBinding method = (MethodBinding) binding;
+	MethodBinding method = ((MethodBinding) binding).original();
 	int methodLevel = matchMethod(method);
 	if (methodLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
 
@@ -218,15 +247,20 @@
 	char[] qualifiedPattern = qualifiedPattern(this.pattern.declaringSimpleName, this.pattern.declaringQualification);
 	if (qualifiedPattern == null) return methodLevel; // since any declaring class will do
 
-	int declaringLevel = !method.isStatic() && !method.isPrivate()
+	boolean subType = !method.isStatic() && !method.isPrivate();
+	if (subType && this.pattern.declaringQualification != null && method.declaringClass != null && method.declaringClass.fPackage != null) {
+		subType = CharOperation.compareWith(this.pattern.declaringQualification, method.declaringClass.fPackage.shortReadableName()) == 0;
+	}
+	int declaringLevel = subType
 		? resolveLevelAsSubtype(qualifiedPattern, method.declaringClass)
 		: resolveLevelForType(qualifiedPattern, method.declaringClass);
 	return methodLevel > declaringLevel ? declaringLevel : methodLevel; // return the weaker match
 }
 protected int resolveLevel(MessageSend messageSend) {
 	MethodBinding method = messageSend.binding;
+	if (method != null) method = method.original();
 	if (method == null) return INACCURATE_MATCH;
-
+	
 	int methodLevel = matchMethod(method);
 	if (methodLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
 
@@ -235,7 +269,7 @@
 	if (qualifiedPattern == null) return methodLevel; // since any declaring class will do
 
 	int declaringLevel;
-	if (isVirtualInvoke(method, messageSend) && !(messageSend.receiverType instanceof ArrayBinding)) {
+	if (isVirtualInvoke(method, messageSend) && !(messageSend.actualReceiverType instanceof ArrayBinding)) {
 		declaringLevel = resolveLevelAsSubtype(qualifiedPattern, method.declaringClass);
 		if (declaringLevel == IMPOSSIBLE_MATCH) {
 			if (method.declaringClass == null || this.allSuperDeclaringTypeNames == null) {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java
index 0f3f802..1696060 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java
@@ -34,6 +34,7 @@
 public char[][] parameterQualifications;
 public char[][] parameterSimpleNames;
 public int parameterCount;
+public boolean varargs;
 
 // extra reference info
 protected IType declaringType;
@@ -63,6 +64,7 @@
 	char[] returnSimpleName,
 	char[][] parameterQualifications, 
 	char[][] parameterSimpleNames,
+	boolean varargs,
 	IType declaringType,
 	int matchRule) {
 
@@ -87,7 +89,7 @@
 	} else {
 		this.parameterCount = -1;
 	}
-
+	this.varargs = varargs;
 	this.declaringType = declaringType;
 	((InternalSearchPattern)this).mustResolve = mustResolve();
 }
@@ -117,7 +119,7 @@
 public boolean matchesDecodedKey(SearchPattern decodedPattern) {
 	MethodPattern pattern = (MethodPattern) decodedPattern;
 
-	return (this.parameterCount == pattern.parameterCount || this.parameterCount == -1)
+	return (this.parameterCount == pattern.parameterCount || this.parameterCount == -1 || this.varargs)
 		&& matchesName(this.selector, pattern.selector);
 }
 /**
@@ -145,7 +147,7 @@
 
 	switch(getMatchMode()) {
 		case R_EXACT_MATCH :
-			if (this.selector != null && this.parameterCount >= 0)
+			if (!this.varargs && this.selector != null && this.parameterCount >= 0)
 				key = createIndexKey(this.selector, this.parameterCount);
 			else // do a prefix query with the selector
 				matchRule = matchRule - R_EXACT_MATCH + R_PREFIX_MATCH;
@@ -154,7 +156,7 @@
 			// do a prefix query with the selector
 			break;
 		case R_PATTERN_MATCH :
-			if (this.parameterCount >= 0)
+			if (!this.varargs && this.parameterCount >= 0)
 				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);
@@ -164,58 +166,44 @@
 
 	return index.query(getIndexCategories(), key, matchRule); // match rule is irrelevant when the key is null
 }
-public String toString() {
-	StringBuffer buffer = new StringBuffer(20);
+protected StringBuffer print(StringBuffer output) {
 	if (this.findDeclarations) {
-		buffer.append(this.findReferences
+		output.append(this.findReferences
 			? "MethodCombinedPattern: " //$NON-NLS-1$
 			: "MethodDeclarationPattern: "); //$NON-NLS-1$
 	} else {
-		buffer.append("MethodReferencePattern: "); //$NON-NLS-1$
+		output.append("MethodReferencePattern: "); //$NON-NLS-1$
 	}
 	if (declaringQualification != null)
-		buffer.append(declaringQualification).append('.');
+		output.append(declaringQualification).append('.');
 	if (declaringSimpleName != null) 
-		buffer.append(declaringSimpleName).append('.');
+		output.append(declaringSimpleName).append('.');
 	else if (declaringQualification != null)
-		buffer.append("*."); //$NON-NLS-1$
+		output.append("*."); //$NON-NLS-1$
 
 	if (selector != null)
-		buffer.append(selector);
+		output.append(selector);
 	else
-		buffer.append("*"); //$NON-NLS-1$
-	buffer.append('(');
+		output.append("*"); //$NON-NLS-1$
+	output.append('(');
 	if (parameterSimpleNames == null) {
-		buffer.append("..."); //$NON-NLS-1$
+		output.append("..."); //$NON-NLS-1$
 	} else {
 		for (int i = 0, max = parameterSimpleNames.length; i < max; i++) {
-			if (i > 0) buffer.append(", "); //$NON-NLS-1$
-			if (parameterQualifications[i] != null) buffer.append(parameterQualifications[i]).append('.');
-			if (parameterSimpleNames[i] == null) buffer.append('*'); else buffer.append(parameterSimpleNames[i]);
+			if (i > 0) output.append(", "); //$NON-NLS-1$
+			if (parameterQualifications[i] != null) output.append(parameterQualifications[i]).append('.');
+			if (parameterSimpleNames[i] == null) output.append('*'); else output.append(parameterSimpleNames[i]);
 		}
 	}
-	buffer.append(')');
+	output.append(')');
 	if (returnQualification != null) 
-		buffer.append(" --> ").append(returnQualification).append('.'); //$NON-NLS-1$
+		output.append(" --> ").append(returnQualification).append('.'); //$NON-NLS-1$
 	else if (returnSimpleName != null)
-		buffer.append(" --> "); //$NON-NLS-1$
+		output.append(" --> "); //$NON-NLS-1$
 	if (returnSimpleName != null) 
-		buffer.append(returnSimpleName);
+		output.append(returnSimpleName);
 	else if (returnQualification != null)
-		buffer.append("*"); //$NON-NLS-1$
-	buffer.append(", "); //$NON-NLS-1$
-	switch(getMatchMode()) {
-		case R_EXACT_MATCH : 
-			buffer.append("exact match, "); //$NON-NLS-1$
-			break;
-		case R_PREFIX_MATCH :
-			buffer.append("prefix match, "); //$NON-NLS-1$
-			break;
-		case R_PATTERN_MATCH :
-			buffer.append("pattern match, "); //$NON-NLS-1$
-			break;
-	}
-	buffer.append(isCaseSensitive() ? "case sensitive" : "case insensitive"); //$NON-NLS-1$ //$NON-NLS-2$
-	return buffer.toString();
+		output.append("*"); //$NON-NLS-1$
+	return super.print(output);
 }
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrLocator.java
index 95daf71..b7b12b8 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrLocator.java
@@ -193,6 +193,24 @@
 	if (closestPattern != null)
 		closestPattern.matchReportReference(reference, element, accuracy, locator);
 }
+public SearchMatch newDeclarationMatch(ASTNode reference, IJavaElement element, int accuracy, int length, MatchLocator locator) {
+	PatternLocator closestPattern = null;
+	int level = IMPOSSIBLE_MATCH;
+	for (int i = 0, pl = this.patternLocators.length; i < pl; i++) {
+		PatternLocator patternLocator = this.patternLocators[i];
+		int newLevel = patternLocator.referenceType() == 0 ? IMPOSSIBLE_MATCH : patternLocator.resolveLevel(reference);
+		if (newLevel > level) {
+			closestPattern = patternLocator;
+			if (newLevel == ACCURATE_MATCH) break;
+			level = newLevel;
+		}
+	}
+	if (closestPattern != null) {
+	    return closestPattern.newDeclarationMatch(reference, element, accuracy, length, locator);
+	}
+	// super implementation...
+    return locator.newDeclarationMatch(element, accuracy, reference.sourceStart, length);
+}
 public int resolveLevel(ASTNode node) {
 	int level = IMPOSSIBLE_MATCH;
 	for (int i = 0, length = this.patternLocators.length; i < length; i++) {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageDeclarationPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageDeclarationPattern.java
index 2f2a5c9..4275a38 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageDeclarationPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageDeclarationPattern.java
@@ -25,29 +25,13 @@
 	// package declarations are not indexed
 	return null;
 }
-public String toString() {
-	StringBuffer buffer = new StringBuffer(20);
-	buffer.append("PackageDeclarationPattern: <"); //$NON-NLS-1$
+protected StringBuffer print(StringBuffer output) {
+	output.append("PackageDeclarationPattern: <"); //$NON-NLS-1$
 	if (this.pkgName != null) 
-		buffer.append(this.pkgName);
+		output.append(this.pkgName);
 	else
-		buffer.append("*"); //$NON-NLS-1$
-	buffer.append(">, "); //$NON-NLS-1$
-	switch(getMatchMode()) {
-		case R_EXACT_MATCH : 
-			buffer.append("exact match, "); //$NON-NLS-1$
-			break;
-		case R_PREFIX_MATCH :
-			buffer.append("prefix match, "); //$NON-NLS-1$
-			break;
-		case R_PATTERN_MATCH :
-			buffer.append("pattern match, "); //$NON-NLS-1$
-			break;
-	}
-	if (isCaseSensitive())
-		buffer.append("case sensitive"); //$NON-NLS-1$
-	else
-		buffer.append("case insensitive"); //$NON-NLS-1$
-	return buffer.toString();
+		output.append("*"); //$NON-NLS-1$
+	output.append(">"); //$NON-NLS-1$
+	return super.print(output);
 }
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferenceLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferenceLocator.java
index 77d76a9..0001f5a 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferenceLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferenceLocator.java
@@ -38,7 +38,7 @@
 		try { 
 			switch (packageFragment.getKind()) {
 				case IPackageFragmentRoot.K_SOURCE :
-					if (!Util.isJavaFileName(fileName) || !packageFragment.getCompilationUnit(new String(fileName)).exists()) {
+					if (!org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(fileName) || !packageFragment.getCompilationUnit(new String(fileName)).exists()) {
 						return false; // unit doesn't live in selected package
 					}
 					break;
@@ -91,7 +91,8 @@
 }
 
 protected int matchLevel(ImportReference importRef) {
-	if (!importRef.onDemand)
+	// Compare prefix also for static import
+	if (!importRef.onDemand || importRef.isStatic())
 		return matchLevelForTokens(importRef.tokens);
 
 	return matchesName(this.pattern.pkgName, CharOperation.concatWith(importRef.tokens, '.'))
@@ -117,6 +118,25 @@
 	}
 	return IMPOSSIBLE_MATCH;
 }
+/* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#matchLevelAndReportImportRef(org.eclipse.jdt.internal.compiler.ast.ImportReference, org.eclipse.jdt.internal.compiler.lookup.Binding, org.eclipse.jdt.internal.core.search.matching.MatchLocator)
+ */
+protected void matchLevelAndReportImportRef(ImportReference importRef, Binding binding, MatchLocator locator) throws CoreException {
+	Binding refBinding = binding;
+	if (importRef.isStatic()) {
+		// for static import, binding can be a field binding or a member type binding
+		// verify that in this case binding is static and use declaring class for fields
+		if (binding instanceof FieldBinding) {
+			FieldBinding fieldBinding = (FieldBinding) binding;
+			if (!fieldBinding.isStatic()) return;
+			refBinding = fieldBinding.declaringClass;
+		} else if (binding instanceof MemberTypeBinding) {
+			MemberTypeBinding memberBinding = (MemberTypeBinding) binding;
+			if (!memberBinding.isStatic()) return;
+		}
+	}
+	super.matchLevelAndReportImportRef(importRef, refBinding, locator);
+}
 protected void matchReportImportRef(ImportReference importRef, Binding binding, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
 	if (binding == null) {
 		this.matchReportReference(importRef, element, accuracy, locator);
@@ -153,15 +173,15 @@
 			QualifiedNameReference qNameRef = (QualifiedNameReference) reference;
 			positions = qNameRef.sourcePositions;
 			switch (qNameRef.bits & ASTNode.RestrictiveFlagMASK) {
-				case BindingIds.FIELD : // reading a field
+				case Binding.FIELD : // reading a field
 					typeBinding = qNameRef.actualReceiverType;
 					break;
-				case BindingIds.TYPE : //=============only type ==============
+				case Binding.TYPE : //=============only type ==============
 					if (qNameRef.binding instanceof TypeBinding)
 						typeBinding = (TypeBinding) qNameRef.binding;
 					break;
-				case BindingIds.VARIABLE : //============unbound cases===========
-				case BindingIds.TYPE | BindingIds.VARIABLE :
+				case Binding.VARIABLE : //============unbound cases===========
+				case Binding.TYPE | Binding.VARIABLE :
 					Binding binding = qNameRef.binding; 
 					if (binding instanceof TypeBinding) {
 						typeBinding = (TypeBinding) binding;
@@ -179,6 +199,11 @@
 			QualifiedTypeReference qTypeRef = (QualifiedTypeReference) reference;
 			positions = qTypeRef.sourcePositions;
 			typeBinding = qTypeRef.resolvedType;
+		} else if (reference instanceof JavadocSingleTypeReference) {
+			JavadocSingleTypeReference jsTypeRef = (JavadocSingleTypeReference) reference;
+			positions = new long[1];
+			positions[0] = (((long)jsTypeRef.sourceStart) << 32) + jsTypeRef.sourceEnd;
+			typeBinding = jsTypeRef.resolvedType;
 		}
 		if (typeBinding instanceof ArrayBinding)
 			typeBinding = ((ArrayBinding) typeBinding).leafComponentType;
@@ -204,6 +229,18 @@
 	return IJavaElement.PACKAGE_FRAGMENT;
 }
 public int resolveLevel(ASTNode node) {
+	if (node instanceof JavadocQualifiedTypeReference) {
+		JavadocQualifiedTypeReference qualifRef = (JavadocQualifiedTypeReference) node;
+		if (qualifRef.packageBinding != null)
+			return resolveLevel(qualifRef.packageBinding);
+		return resolveLevel(qualifRef.resolvedType);
+	}
+	if (node instanceof JavadocSingleTypeReference) {
+		JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) node;
+		if (singleRef.packageBinding != null)
+			return resolveLevel(singleRef.packageBinding);
+		return IMPOSSIBLE_MATCH;
+	}
 	if (node instanceof QualifiedTypeReference)
 		return resolveLevel(((QualifiedTypeReference) node).resolvedType);
 	if (node instanceof QualifiedNameReference)
@@ -235,7 +272,8 @@
 	if (compoundName != null && matchesName(this.pattern.pkgName, CharOperation.concatWith(compoundName, '.'))) {
 		if (((InternalSearchPattern) this.pattern).focus instanceof IPackageFragment && binding instanceof ReferenceBinding) {
 			// check that type is located inside this instance of a package fragment
-			if (!isDeclaringPackageFragment((IPackageFragment)((InternalSearchPattern) this.pattern).focus, (ReferenceBinding)binding)) return IMPOSSIBLE_MATCH;
+			if (!isDeclaringPackageFragment((IPackageFragment)((InternalSearchPattern) this.pattern).focus, (ReferenceBinding)binding))
+				return IMPOSSIBLE_MATCH;
 		}				
 		return ACCURATE_MATCH;
 	} else {
@@ -245,14 +283,14 @@
 protected int resolveLevel(QualifiedNameReference qNameRef) {
 	TypeBinding typeBinding = null;
 	switch (qNameRef.bits & ASTNode.RestrictiveFlagMASK) {
-		case BindingIds.FIELD : // reading a field
+		case Binding.FIELD : // reading a field
 			if (qNameRef.tokens.length < (qNameRef.otherBindings == null ? 3 : qNameRef.otherBindings.length + 3))
 				return IMPOSSIBLE_MATCH; // must be at least p1.A.x
 			typeBinding = qNameRef.actualReceiverType;
 			break;
-		case BindingIds.LOCAL : // reading a local variable
+		case Binding.LOCAL : // reading a local variable
 			return IMPOSSIBLE_MATCH; // no package match in it
-		case BindingIds.TYPE : //=============only type ==============
+		case Binding.TYPE : //=============only type ==============
 			if (qNameRef.binding instanceof TypeBinding)
 				typeBinding = (TypeBinding) qNameRef.binding;
 			break;
@@ -260,8 +298,8 @@
 		 * Handling of unbound qualified name references. The match may reside in the resolved fragment,
 		 * which is recorded inside the problem binding, along with the portion of the name until it became a problem.
 		 */
-		case BindingIds.VARIABLE : //============unbound cases===========
-		case BindingIds.TYPE | BindingIds.VARIABLE :
+		case Binding.VARIABLE : //============unbound cases===========
+		case Binding.TYPE | Binding.VARIABLE :
 			Binding binding = qNameRef.binding; 
 			if (binding instanceof ProblemReferenceBinding) {
 				typeBinding = (TypeBinding) binding;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferencePattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferencePattern.java
index ad10331..01f8615 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferencePattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferencePattern.java
@@ -67,31 +67,13 @@
 	/* walk the segments from end to start as it will find less potential references using 'lang' than 'java' */
 	this.currentSegment = this.segments.length - 1;
 }
-public String toString() {
-	StringBuffer buffer = new StringBuffer(20);
-	buffer.append("PackageReferencePattern: <"); //$NON-NLS-1$
+protected StringBuffer print(StringBuffer output) {
+	output.append("PackageReferencePattern: <"); //$NON-NLS-1$
 	if (this.pkgName != null) 
-		buffer.append(this.pkgName);
+		output.append(this.pkgName);
 	else
-		buffer.append("*"); //$NON-NLS-1$
-	buffer.append(">, "); //$NON-NLS-1$
-	switch(getMatchMode()) {
-		case R_EXACT_MATCH : 
-			buffer.append("exact match, "); //$NON-NLS-1$
-			break;
-		case R_PREFIX_MATCH :
-			buffer.append("prefix match, "); //$NON-NLS-1$
-			break;
-		case R_PATTERN_MATCH :
-			buffer.append("pattern match, "); //$NON-NLS-1$
-			break;
-		case R_REGEXP_MATCH :
-			buffer.append("regexp match, "); //$NON-NLS-1$
-	}
-	if (isCaseSensitive())
-		buffer.append("case sensitive"); //$NON-NLS-1$
-	else
-		buffer.append("case insensitive"); //$NON-NLS-1$
-	return buffer.toString();
+		output.append("*"); //$NON-NLS-1$
+	output.append(">"); //$NON-NLS-1$
+	return super.print(output);
 }
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java
index da3da17..8b0cc69 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java
@@ -20,14 +20,19 @@
 
 public abstract class PatternLocator implements IIndexConstants {
 
+// store pattern info
 protected int matchMode;
 protected boolean isCaseSensitive;
+protected boolean isEquivalentMatch;
+protected boolean isErasureMatch;
+protected boolean mustResolve;
 
 /* match levels */
 public static final int IMPOSSIBLE_MATCH = 0;
 public static final int INACCURATE_MATCH = 1;
 public static final int POSSIBLE_MATCH = 2;
 public static final int ACCURATE_MATCH = 3;
+public static final int ERASURE_MATCH = 4;
 
 /* match container */
 public static final int COMPILATION_UNIT_CONTAINER = 1;
@@ -37,6 +42,10 @@
 public static final int ALL_CONTAINER =
 	COMPILATION_UNIT_CONTAINER | CLASS_CONTAINER | METHOD_CONTAINER | FIELD_CONTAINER;
 
+/* match rule */
+public static final int RAW_MASK = SearchPattern.R_EQUIVALENT_MATCH + SearchPattern.R_ERASURE_MATCH;
+public static final int RULE_MASK = RAW_MASK; // no other values for the while...
+
 public static PatternLocator patternLocator(SearchPattern pattern) {
 	switch (((InternalSearchPattern)pattern).kind) {
 		case IIndexConstants.PKG_REF_PATTERN :
@@ -84,11 +93,52 @@
 	return binding != null ? binding.qualifiedSourceName() : null;
 }
 
-
 public PatternLocator(SearchPattern pattern) {
 	int matchRule = pattern.getMatchRule();
 	this.isCaseSensitive = (matchRule & SearchPattern.R_CASE_SENSITIVE) != 0;
-	this.matchMode = matchRule - (this.isCaseSensitive ? SearchPattern.R_CASE_SENSITIVE : 0);
+	this.isErasureMatch = (matchRule & SearchPattern.R_ERASURE_MATCH) != 0;
+	this.isEquivalentMatch = (matchRule & SearchPattern.R_EQUIVALENT_MATCH) != 0;
+	this.matchMode = matchRule & JavaSearchPattern.MATCH_MODE_MASK;
+	this.mustResolve = ((InternalSearchPattern)pattern).mustResolve;
+}
+/* (non-Javadoc)
+ * Modify PatternLocator.qualifiedPattern behavior:
+ * do not add star before simple name pattern when qualification pattern is null.
+ * This avoid to match p.X when pattern is only X...
+ */
+protected char[] getQualifiedPattern(char[] simpleNamePattern, char[] qualificationPattern) {
+	// NOTE: if case insensitive search then simpleNamePattern & qualificationPattern are assumed to be lowercase
+	if (simpleNamePattern == null) {
+		if (qualificationPattern == null) return null;
+		return CharOperation.concat(qualificationPattern, ONE_STAR, '.');
+	} else if (qualificationPattern == null) {
+		return simpleNamePattern;
+	} else {
+		return CharOperation.concat(qualificationPattern, simpleNamePattern, '.');
+	}
+}
+/* (non-Javadoc)
+ * Modify PatternLocator.qualifiedSourceName behavior:
+ * also concatene enclosing type name when type is a only a member type.
+ */
+protected char[] getQualifiedSourceName(TypeBinding binding) {
+	TypeBinding type = binding instanceof ArrayBinding ? ((ArrayBinding)binding).leafComponentType : binding;
+	if (type instanceof ReferenceBinding) {
+		if (type.isLocalType()) {
+			return CharOperation.concat(qualifiedSourceName(type.enclosingType()), new char[] {'.', '1', '.'}, binding.sourceName());
+		} else if (type.isMemberType()) {
+			return CharOperation.concat(qualifiedSourceName(type.enclosingType()), binding.sourceName(), '.');
+		}
+	}
+	return binding != null ? binding.qualifiedSourceName() : null;
+}
+/*
+ * Get binding of type argument from a class unit scope and its index position.
+ * Cache is lazy initialized and if no binding is found, then store a problem binding
+ * to avoid making research twice...
+ */
+protected TypeBinding getTypeNameBinding(int index) {
+	return null;
 }
 /**
  * Initializes this search pattern so that polymorphic search can be performed.
@@ -241,7 +291,9 @@
 			match = locator.newFieldReferenceMatch(element, accuracy, offset, reference.sourceEnd-offset+1, reference);
 			break;
 		case IJavaElement.METHOD:
-			match = locator.newMethodReferenceMatch(element, accuracy, offset, reference.sourceEnd-offset+1, reference);
+			boolean isConstructor = reference instanceof ExplicitConstructorCall;
+			boolean isSynthetic = isConstructor ? ((ExplicitConstructorCall) reference).isImplicitSuper() : false;
+			match = locator.newMethodReferenceMatch(element, accuracy, offset, reference.sourceEnd-offset+1, isConstructor, isSynthetic, reference);
 			break;
 		case IJavaElement.LOCAL_VARIABLE:
 			match = locator.newLocalVariableReferenceMatch(element, accuracy, offset, reference.sourceEnd-offset+1, reference);
@@ -251,6 +303,9 @@
 		locator.report(match);
 	}
 }
+public SearchMatch newDeclarationMatch(ASTNode reference, IJavaElement element, int accuracy, int length, MatchLocator locator) {
+    return locator.newDeclarationMatch(element, accuracy, reference.sourceStart, length);
+}
 protected int referenceType() {
 	return 0; // defaults to unknown (a generic JavaSearchMatch will be created)
 }
@@ -267,6 +322,205 @@
 	// need to do instance of checks to find out exact type of ASTNode
 	return IMPOSSIBLE_MATCH;
 }
+/*
+ * Refine accuracy for a match.
+ * Typically this happens while search references to parameterized type.
+ * In this case we need locator to be able to resolve type arguments and verify
+ * if binding is compatible with pattern...
+ * Look also for enclosing type
+ */
+protected int refineAccuracy(int accuracy, ParameterizedTypeBinding parameterizedBinding, char[][][] patternTypeArguments, MatchLocator locator) {
+	// We can only refine if locator has an unit scope.
+	if (locator.unitScope == null) return accuracy;
+	return refineAccuracy(accuracy, parameterizedBinding, patternTypeArguments, false, 0, locator);
+}
+int refineAccuracy(int accuracy, ParameterizedTypeBinding parameterizedBinding, char[][][] patternTypeArguments, boolean isPatternSourceType, int depth, MatchLocator locator) {
+
+	// First compare lengthes
+	int patternTypeArgsLength = (patternTypeArguments==null || depth>=patternTypeArguments.length || patternTypeArguments[depth] == null) ? 0 : patternTypeArguments[depth].length;
+	TypeBinding[] argumentsBinding = parameterizedBinding.arguments;
+	int typeArgumentsLength = argumentsBinding == null ? 0 : argumentsBinding.length;
+	int refinedAccuracy =  accuracy;
+	if (patternTypeArgsLength == typeArgumentsLength) {
+		if (patternTypeArgsLength == 0) {
+			if (isPatternSourceType) { // raw source type pattern is always compatible erasure...
+				if (refinedAccuracy <= SearchMatch.A_INACCURATE) // ...except if accuracy has been already refined
+					refinedAccuracy |= RAW_MASK;
+			}
+		} else {
+			if (isPatternSourceType) {
+				// parameterized source type pattern is always an incompatible erasure match
+				refinedAccuracy |= SearchPattern.R_ERASURE_MATCH;
+				refinedAccuracy &= ~SearchPattern.R_EQUIVALENT_MATCH;
+			}
+		}
+	} else {
+		if (patternTypeArgsLength==0) { // raw pattern
+			if (patternTypeArguments == null || depth < patternTypeArguments.length) {
+				// if valid type arguments, then it is always compatible erasure except if accuracy has been already refined
+				if (refinedAccuracy <= SearchMatch.A_INACCURATE)
+					refinedAccuracy |= RAW_MASK;
+			}
+			return refinedAccuracy;
+		} else  if (typeArgumentsLength==0) { // raw binding
+			// then it is always compatible erasure except if accuracy has been already refined
+			if (refinedAccuracy <= SearchMatch.A_INACCURATE)
+				refinedAccuracy |= RAW_MASK;
+			return refinedAccuracy;
+		}
+		return -1;
+	}
+
+	// Compare binding for each type argument only if pattern is not erasure only and at first level
+//	int refinedAccuracy = SearchMatch.A_ACCURATE;
+	if (!isPatternSourceType) {
+		for (int i=0; i<typeArgumentsLength; i++) {
+			// Get parameterized type argument binding
+			TypeBinding argumentBinding = argumentsBinding[i];
+
+			// Get binding for pattern argument
+			char[] patternTypeArgument = patternTypeArguments[depth][i];
+			char patternWildcard = patternTypeArgument[0];
+			char[] patternTypeName = patternTypeArgument;
+			int patternWildcardKind = -1;
+			switch (patternWildcard) {
+				case Signature.C_STAR:
+					if (argumentBinding.isWildcard()) {
+						WildcardBinding wildcardBinding = (WildcardBinding) argumentBinding;
+						if (wildcardBinding.kind == Wildcard.UNBOUND) continue;
+					}
+					if (refinedAccuracy < SearchPattern.R_ERASURE_MATCH) refinedAccuracy |= SearchPattern.R_EQUIVALENT_MATCH;
+					continue; // unbound parameter always match
+				case Signature.C_EXTENDS :
+					patternWildcardKind = Wildcard.EXTENDS;
+					patternTypeName = CharOperation.subarray(patternTypeArgument, 1, patternTypeArgument.length);
+					break;
+				case Signature.C_SUPER :
+					patternWildcardKind = Wildcard.SUPER;
+					patternTypeName = CharOperation.subarray(patternTypeArgument, 1, patternTypeArgument.length);
+				default :
+					break;
+			}
+			patternTypeName = Signature.toCharArray(patternTypeName);
+			TypeBinding patternBinding = locator.getType(patternTypeArgument, patternTypeName);
+			
+			// If have no binding for pattern arg, then we won't be able to refine accuracy
+			if (patternBinding == null) {
+				if (argumentBinding.isWildcard()) {
+					WildcardBinding wildcardBinding = (WildcardBinding) argumentBinding;
+					if (wildcardBinding.kind == Wildcard.UNBOUND) {
+						if (refinedAccuracy < SearchPattern.R_ERASURE_MATCH) refinedAccuracy |= SearchPattern.R_EQUIVALENT_MATCH;
+					} else {
+						refinedAccuracy |= SearchPattern.R_ERASURE_MATCH;
+					}
+				}
+				continue;
+			}
+				
+			// Verify tha pattern binding is compatible with match type argument binding
+			switch (patternWildcard) {
+				case Signature.C_STAR : // UNBOUND pattern
+					// unbound always match => skip to next argument
+					if (refinedAccuracy < SearchPattern.R_ERASURE_MATCH) refinedAccuracy |= SearchPattern.R_EQUIVALENT_MATCH;
+					continue;
+				case Signature.C_EXTENDS : // EXTENDS pattern
+					if (argumentBinding.isWildcard()) { // argument is a wildcard
+						WildcardBinding wildcardBinding = (WildcardBinding) argumentBinding;
+						// It's ok if wildcards are identical
+						if (wildcardBinding.kind == patternWildcardKind && wildcardBinding.bound == patternBinding) {
+							continue;
+						}
+						// Look for wildcard compatibility
+						switch (wildcardBinding.kind) {
+							case Wildcard.EXTENDS:
+								if (wildcardBinding.bound== null || wildcardBinding.bound.isCompatibleWith(patternBinding)) {
+									// valid when arg extends a subclass of pattern
+									if (refinedAccuracy < SearchPattern.R_ERASURE_MATCH) refinedAccuracy |= SearchPattern.R_EQUIVALENT_MATCH;
+									continue;
+								}
+								break;
+							case Wildcard.SUPER:
+								break;
+							case Wildcard.UNBOUND:
+								if (refinedAccuracy < SearchPattern.R_ERASURE_MATCH) refinedAccuracy |= SearchPattern.R_EQUIVALENT_MATCH;
+								continue;
+						}
+					} else if (argumentBinding.isCompatibleWith(patternBinding)) {
+						// valid when arg is a subclass of pattern 
+						if (refinedAccuracy < SearchPattern.R_ERASURE_MATCH) refinedAccuracy |= SearchPattern.R_EQUIVALENT_MATCH;
+						continue;
+					}
+					break;
+				case Signature.C_SUPER : // SUPER pattern
+					if (argumentBinding.isWildcard()) { // argument is a wildcard
+						WildcardBinding wildcardBinding = (WildcardBinding) argumentBinding;
+						// It's ok if wildcards are identical
+						if (wildcardBinding.kind == patternWildcardKind && wildcardBinding.bound == patternBinding) {
+							continue;
+						}
+						// Look for wildcard compatibility
+						switch (wildcardBinding.kind) {
+							case Wildcard.EXTENDS:
+								break;
+							case Wildcard.SUPER:
+								if (wildcardBinding.bound== null || patternBinding.isCompatibleWith(wildcardBinding.bound)) {
+									// valid only when arg super a superclass of pattern
+									if (refinedAccuracy < SearchPattern.R_ERASURE_MATCH) refinedAccuracy |= SearchPattern.R_EQUIVALENT_MATCH;
+									continue;
+								}
+								break;
+							case Wildcard.UNBOUND:
+								if (refinedAccuracy < SearchPattern.R_ERASURE_MATCH) refinedAccuracy |= SearchPattern.R_EQUIVALENT_MATCH;
+								continue;
+						}
+					} else if (patternBinding.isCompatibleWith(argumentBinding)) {
+						// valid only when arg is a superclass of pattern
+						if (refinedAccuracy < SearchPattern.R_ERASURE_MATCH) refinedAccuracy |= SearchPattern.R_EQUIVALENT_MATCH;
+						continue;
+					}
+					break;
+				default:
+					if (argumentBinding.isWildcard()) {
+						WildcardBinding wildcardBinding = (WildcardBinding) argumentBinding;
+						switch (wildcardBinding.kind) {
+							case Wildcard.EXTENDS:
+								if (wildcardBinding.bound== null || patternBinding.isCompatibleWith(wildcardBinding.bound)) {
+									// valid only when arg extends a superclass of pattern
+									if (refinedAccuracy < SearchPattern.R_ERASURE_MATCH) refinedAccuracy |= SearchPattern.R_EQUIVALENT_MATCH;
+									continue;
+								}
+								break;
+							case Wildcard.SUPER:
+								if (wildcardBinding.bound== null || wildcardBinding.bound.isCompatibleWith(patternBinding)) {
+									// valid only when arg super a subclass of pattern
+									if (refinedAccuracy < SearchPattern.R_ERASURE_MATCH) refinedAccuracy |= SearchPattern.R_EQUIVALENT_MATCH;
+									continue;
+								}
+								break;
+							case Wildcard.UNBOUND:
+								if (refinedAccuracy < SearchPattern.R_ERASURE_MATCH) refinedAccuracy |= SearchPattern.R_EQUIVALENT_MATCH;
+								continue;
+						}
+					} else if (argumentBinding == patternBinding)
+						// valid only when arg is equals to pattern
+						continue;
+					break;
+			}
+			
+			// Argument does not match => erasure match will be the only possible one
+			return SearchPattern.R_ERASURE_MATCH;
+		}
+	}
+
+	// Recurse refining on enclosing types if any
+	TypeBinding enclosingType = parameterizedBinding.enclosingType();
+	if (enclosingType != null && (enclosingType.isParameterizedType() || enclosingType.isRawType())) {
+		return refineAccuracy(refinedAccuracy, (ParameterizedTypeBinding)enclosingType, patternTypeArguments, isPatternSourceType, depth+1, locator);
+	}
+	
+	// Refine the accuracy to accurate
+	return refinedAccuracy;
+}
 /**
  * Finds out whether the given binding matches this search pattern.
  * Returns ACCURATE_MATCH if it does.
@@ -281,13 +535,32 @@
 /**
  * Returns whether the given type binding matches the given simple name pattern 
  * and qualification pattern.
+ * Note that from since 3.1, this method resolve to accurate member or local types
+ * even if they are not fully qualified (ie. X.Member instead of p.X.Member).
  * Returns ACCURATE_MATCH if it does.
  * Returns INACCURATE_MATCH if resolve failed.
  * Returns IMPOSSIBLE_MATCH if it doesn't.
  */
-protected int resolveLevelForType(char[] simpleNamePattern, char[] qualificationPattern, TypeBinding type) {
-	return resolveLevelForType(qualifiedPattern(simpleNamePattern, qualificationPattern), type);
+protected int resolveLevelForType(char[] simpleNamePattern, char[] qualificationPattern, TypeBinding binding) {
+//	return resolveLevelForType(qualifiedPattern(simpleNamePattern, qualificationPattern), type);
+	char[] qualifiedPattern = getQualifiedPattern(simpleNamePattern, qualificationPattern);
+	int level = resolveLevelForType(qualifiedPattern, binding);
+	if (level == ACCURATE_MATCH || binding == null) return level;
+	boolean match = false;
+	TypeBinding type = binding instanceof ArrayBinding ? ((ArrayBinding)binding).leafComponentType : binding;
+	if (type.isMemberType() || type.isLocalType()) {
+		if (qualificationPattern != null) {
+			match = CharOperation.match(qualifiedPattern, getQualifiedSourceName(binding), this.isCaseSensitive);
+		} else {
+			match = CharOperation.match(qualifiedPattern, binding.sourceName(), this.isCaseSensitive); // need to keep binding to get source name
+		}
+	} else if (qualificationPattern == null) {
+		match = CharOperation.match(qualifiedPattern, getQualifiedSourceName(binding), this.isCaseSensitive);
+	}
+	return match ? ACCURATE_MATCH : IMPOSSIBLE_MATCH;
+
 }
+
 /**
  * Returns whether the given type binding matches the given qualified pattern.
  * Returns ACCURATE_MATCH if it does.
@@ -298,6 +571,9 @@
 	if (qualifiedPattern == null) return ACCURATE_MATCH;
 	if (type == null) return INACCURATE_MATCH;
 
+	// Type variable cannot be specified through pattern => this kind of binding cannot match it (see bug 79803)
+	if (type.isTypeVariable()) return IMPOSSIBLE_MATCH;
+
 	// NOTE: if case insensitive search then qualifiedPattern is assumed to be lowercase
 
 	char[] qualifiedPackageName = type.qualifiedPackageName();
@@ -309,6 +585,176 @@
 		? ACCURATE_MATCH
 		: IMPOSSIBLE_MATCH;
 }
+/* (non-Javadoc)
+ * Resolve level for type with a given binding with all pattern information.
+ */
+protected int resolveLevelForType (char[] simpleNamePattern,
+									char[] qualificationPattern,
+									char[][][] patternTypeArguments,
+									int depth,
+									TypeBinding type) {
+	// standard search with no generic additional information must succeed
+	int level = resolveLevelForType(simpleNamePattern, qualificationPattern, type);
+	if (level == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
+	if (type == null || patternTypeArguments == null|| patternTypeArguments.length == 0 || depth>=patternTypeArguments.length || patternTypeArguments[depth] == null) return level;
+	
+	// if pattern is erasure match (see bug 79790), commute impossible to erasure
+	int impossible = this.isErasureMatch ? ERASURE_MATCH : IMPOSSIBLE_MATCH;
+
+	// pattern has type parameter(s) or type argument(s)
+	boolean isRawType = type.isRawType();
+	if (type.isGenericType()) {
+		// Binding is generic, get its type variable(s)
+		TypeVariableBinding[] typeVariables = null;
+		if (type instanceof SourceTypeBinding) {
+			SourceTypeBinding sourceTypeBinding = (SourceTypeBinding) type;
+			typeVariables = sourceTypeBinding.typeVariables;
+		} else if (type instanceof BinaryTypeBinding) {
+			BinaryTypeBinding binaryTypeBinding = (BinaryTypeBinding) type;
+			if (this.mustResolve)
+				typeVariables = binaryTypeBinding.typeVariables(); // TODO (frederic) verify performance
+		}
+		// type variables length must match at least specified type names length
+		if (typeVariables == null || typeVariables.length == 0) {
+			return IMPOSSIBLE_MATCH;
+		}
+		int length = patternTypeArguments[depth].length;
+		if (typeVariables.length != length) return IMPOSSIBLE_MATCH;
+		// TODO (frederic) do we need to verify each parameter?
+		return level; // we can't do better
+	} else if (isRawType) {
+		return level; // raw type always match
+	} else if (!type.isParameterizedType()) {
+		// Standard types (ie. neither generic nor parameterized nor raw types)
+		// cannot match pattern with type parameters or arguments
+		return IMPOSSIBLE_MATCH;
+	} else {
+		ParameterizedTypeBinding paramTypeBinding = (ParameterizedTypeBinding) type;
+		// When there's no type argument, no verification is necessary 
+		if (paramTypeBinding.arguments != null) {
+
+			// type parameters length must match at least specified type names length
+			int length = patternTypeArguments[depth].length;
+			if (paramTypeBinding.arguments.length != length) return IMPOSSIBLE_MATCH;
+	
+			// verify each pattern type parameter
+			nextTypeArgument: for (int i= 0; i<length; i++) {
+				char[] patternTypeArgument = patternTypeArguments[depth][i];
+				TypeBinding argTypeBinding = paramTypeBinding.arguments[i];
+				// get corresponding pattern wildcard
+				switch (patternTypeArgument[0]) {
+					case Signature.C_STAR : // unbound parameter always match
+					case Signature.C_SUPER : // needs pattern type parameter binding
+						// skip to next type argument as it will be resolved later
+						continue nextTypeArgument;
+					case Signature.C_EXTENDS :
+						// remove wildcard from patter type argument
+						patternTypeArgument = CharOperation.subarray(patternTypeArgument, 1, patternTypeArgument.length);
+					default :
+						// no wildcard
+						break;
+				}
+				// get pattern type argument from its signature
+				patternTypeArgument = Signature.toCharArray(patternTypeArgument);
+				if (!this.isCaseSensitive) patternTypeArgument = CharOperation.toLowerCase(patternTypeArgument);
+				boolean patternTypeArgHasAnyChars = CharOperation.contains(new char[] {'*', '?'}, patternTypeArgument);
+	
+				// Verify that names match...
+				// ...special case for wildcard
+				if (argTypeBinding.isWildcard()) {
+					WildcardBinding wildcardBinding = (WildcardBinding) argTypeBinding;
+					switch (wildcardBinding.kind) {
+						case Wildcard.EXTENDS:
+							// Invalid if type argument is not exact
+							if (patternTypeArgHasAnyChars) return impossible;
+						case Wildcard.UNBOUND:
+							// there's no bound name to match => valid
+							continue nextTypeArgument;
+					}
+					// Look if bound name match pattern type argument
+					ReferenceBinding boundBinding = (ReferenceBinding) wildcardBinding.bound;
+					if (CharOperation.match(patternTypeArgument, boundBinding.shortReadableName(), this.isCaseSensitive) ||
+						CharOperation.match(patternTypeArgument, boundBinding.readableName(), this.isCaseSensitive)) {
+						// found name in hierarchy => match
+						continue nextTypeArgument;
+					}
+
+					// If pattern is not exact then match fails
+					if (patternTypeArgHasAnyChars) return impossible;
+						
+					// Look for bound name in type argument superclasses
+					boundBinding = boundBinding.superclass();
+					while (boundBinding != null) {
+						if (CharOperation.equals(patternTypeArgument, boundBinding.shortReadableName(), this.isCaseSensitive) ||
+							CharOperation.equals(patternTypeArgument, boundBinding.readableName(), this.isCaseSensitive)) {
+							// found name in hierarchy => match
+							continue nextTypeArgument;
+						} else if (boundBinding.isLocalType() || boundBinding.isMemberType()) {
+							// for local or member type, verify also source name (bug 81084)
+							if (CharOperation.match(patternTypeArgument, boundBinding.sourceName(), this.isCaseSensitive))
+								continue nextTypeArgument;
+						}
+						boundBinding = boundBinding.superclass();
+					}
+					return impossible;
+				}
+				
+				// See if names match
+				if (CharOperation.match(patternTypeArgument, argTypeBinding.shortReadableName(), this.isCaseSensitive) ||
+					CharOperation.match(patternTypeArgument, argTypeBinding.readableName(), this.isCaseSensitive)) {
+					continue nextTypeArgument;
+				} else if (argTypeBinding.isLocalType() || argTypeBinding.isMemberType()) {
+					// for local or member type, verify also source name (bug 81084)
+					if (CharOperation.match(patternTypeArgument, argTypeBinding.sourceName(), this.isCaseSensitive))
+						continue nextTypeArgument;
+				}
+
+				// If pattern is not exact then match fails
+				if (patternTypeArgHasAnyChars) return impossible;
+
+				// Get reference binding
+				ReferenceBinding refBinding = null;
+				if (argTypeBinding.isArrayType()) {
+					TypeBinding leafBinding = ((ArrayBinding) argTypeBinding).leafComponentType;
+					if (!leafBinding.isBaseType()) {
+						refBinding = (ReferenceBinding) leafBinding;
+					}
+				} else if (!argTypeBinding.isBaseType()) {
+					refBinding = (ReferenceBinding) argTypeBinding;
+				}
+				// Scan hierarchy
+				if (refBinding != null) {
+					refBinding = refBinding.superclass();
+					while (refBinding != null) {
+						if (CharOperation.equals(patternTypeArgument, refBinding.shortReadableName(), this.isCaseSensitive) ||
+							CharOperation.equals(patternTypeArgument, refBinding.readableName(), this.isCaseSensitive)) {
+							// found name in hierarchy => match
+							continue nextTypeArgument;
+						} else if (refBinding.isLocalType() || refBinding.isMemberType()) {
+							// for local or member type, verify also source name (bug 81084)
+							if (CharOperation.match(patternTypeArgument, refBinding.sourceName(), this.isCaseSensitive))
+								continue nextTypeArgument;
+						}
+						refBinding = refBinding.superclass();
+					}
+				}
+				return impossible;
+			}
+		}
+		
+		// Recurse on enclosing type
+		TypeBinding enclosingType = paramTypeBinding.enclosingType();
+		if (enclosingType != null && enclosingType.isParameterizedType() && depth < patternTypeArguments.length && qualificationPattern != null) {
+			int lastDot = CharOperation.lastIndexOf('.', qualificationPattern);
+			char[] enclosingQualificationPattern = lastDot==-1 ? null : CharOperation.subarray(qualificationPattern, 0, lastDot);
+			char[] enclosingSimpleNamePattern = lastDot==-1 ? qualificationPattern : CharOperation.subarray(qualificationPattern, lastDot+1, qualificationPattern.length);
+			int enclosingLevel = resolveLevelForType(enclosingSimpleNamePattern, enclosingQualificationPattern, patternTypeArguments, depth+1, enclosingType);
+			if (enclosingLevel == impossible) return impossible;
+			if (enclosingLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
+		}
+		return level;
+	}
+}
 public String toString(){
 	return "SearchPattern"; //$NON-NLS-1$
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java
index 009ddc8..ba0eea2 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java
@@ -18,6 +18,7 @@
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.core.*;
+import org.eclipse.jdt.internal.core.util.Util;
 
 public class PossibleMatch implements ICompilationUnit {
 
@@ -73,6 +74,7 @@
 /**
  * The exact openable file name. In particular, will be the originating .class file for binary openable with attached
  * source.
+ * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
  * @see PackageReferenceLocator#isDeclaringPackageFragment(IPackageFragment, org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding)
  */
 public char[] getFileName() {
@@ -104,11 +106,11 @@
 		if (fileName == NO_SOURCE_FILE_NAME)
 			return ((ClassFile) this.openable).getType().getFullyQualifiedName('.').toCharArray();
 
-		String simpleName = fileName.substring(0, fileName.length() - 5); // length-".java".length()
-		String pkgName = this.openable.getParent().getElementName();
-		if (pkgName.length() == 0)
-			return simpleName.toCharArray();
-		return (pkgName + '.' + simpleName).toCharArray();
+		// Class file may have a source file name with ".java" extension (see bug 73784)
+		int index = Util.indexOfJavaLikeExtension(fileName);
+		String simpleName = index==-1 ? fileName : fileName.substring(0, index);
+		PackageFragment pkg = (PackageFragment) this.openable.getParent();
+		return Util.concatWith(pkg.names, simpleName, '.').toCharArray();
 	}
 	return null;
 }
@@ -120,12 +122,11 @@
 	if (this.sourceFileName != null) return this.sourceFileName;
 
 	this.sourceFileName = NO_SOURCE_FILE_NAME; 
-	SourceMapper sourceMapper = this.openable.getSourceMapper();
-	if (sourceMapper != null) {
-		IType type = ((ClassFile) this.openable).getType();
+	if (this.openable.getSourceMapper() != null) {
+		BinaryType type = (BinaryType) ((ClassFile) this.openable).getType();
 		ClassFileReader reader = MatchLocator.classFileReader(type);
 		if (reader != null)
-			this.sourceFileName = sourceMapper.findSourceFileName(type, reader);
+			this.sourceFileName = type.sourceFileName(reader);
 	}
 	return this.sourceFileName;
 }	
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatchSet.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatchSet.java
index 358b32d..f50e658 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatchSet.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatchSet.java
@@ -13,7 +13,7 @@
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
-import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 
 /**
  * A set of PossibleMatches that is sorted by package fragment roots.
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/QualifiedTypeDeclarationPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/QualifiedTypeDeclarationPattern.java
index c807f27..0166611 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/QualifiedTypeDeclarationPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/QualifiedTypeDeclarationPattern.java
@@ -18,12 +18,12 @@
 
 protected char[] qualification;
 
-public QualifiedTypeDeclarationPattern(char[] qualification, char[] simpleName, char classOrInterface, int matchRule) {
+public QualifiedTypeDeclarationPattern(char[] qualification, char[] simpleName, char typeSuffix, int matchRule) {
 	this(matchRule);
 
 	this.qualification = isCaseSensitive() ? qualification : CharOperation.toLowerCase(qualification);
 	this.simpleName = isCaseSensitive() ? simpleName : CharOperation.toLowerCase(simpleName);
-	this.classOrInterface = classOrInterface;
+	this.typeSuffix = typeSuffix;
 
 	((InternalSearchPattern)this).mustResolve = this.qualification != null;
 }
@@ -46,59 +46,50 @@
 		this.qualification[slash - start] = '.';
 	}
 
-	this.classOrInterface = key[key.length - 1];
+	this.typeSuffix = key[key.length - 1];
 }
 public SearchPattern getBlankPattern() {
 	return new QualifiedTypeDeclarationPattern(R_EXACT_MATCH | R_CASE_SENSITIVE);
 }
 public boolean matchesDecodedKey(SearchPattern decodedPattern) {
 	QualifiedTypeDeclarationPattern pattern = (QualifiedTypeDeclarationPattern) decodedPattern;
-	switch(this.classOrInterface) {
+	switch(this.typeSuffix) {
 		case CLASS_SUFFIX :
 		case INTERFACE_SUFFIX :
-			if (this.classOrInterface != pattern.classOrInterface) return false;
+		case ENUM_SUFFIX :
+		case ANNOTATION_TYPE_SUFFIX :
+			if (this.typeSuffix != pattern.typeSuffix) return false;
 	}
 
 	return matchesName(this.simpleName, pattern.simpleName) && matchesName(this.qualification, pattern.qualification);
 }
-public String toString() {
-	StringBuffer buffer = new StringBuffer(20);
-	switch (classOrInterface){
+protected StringBuffer print(StringBuffer output) {
+	switch (this.typeSuffix){
 		case CLASS_SUFFIX :
-			buffer.append("ClassDeclarationPattern: qualification<"); //$NON-NLS-1$
+			output.append("ClassDeclarationPattern: qualification<"); //$NON-NLS-1$
 			break;
 		case INTERFACE_SUFFIX :
-			buffer.append("InterfaceDeclarationPattern: qualification<"); //$NON-NLS-1$
+			output.append("InterfaceDeclarationPattern: qualification<"); //$NON-NLS-1$
+			break;
+		case ENUM_SUFFIX :
+			output.append("EnumDeclarationPattern: qualification<"); //$NON-NLS-1$
+			break;
+		case ANNOTATION_TYPE_SUFFIX :
+			output.append("AnnotationTypeDeclarationPattern: qualification<"); //$NON-NLS-1$
 			break;
 		default :
-			buffer.append("TypeDeclarationPattern: qualification<"); //$NON-NLS-1$
+			output.append("TypeDeclarationPattern: qualification<"); //$NON-NLS-1$
 			break;
 	}
 	if (this.qualification != null) 
-		buffer.append(this.qualification);
+		output.append(this.qualification);
 	else
-		buffer.append("*"); //$NON-NLS-1$
-	buffer.append(">, type<"); //$NON-NLS-1$
+		output.append("*"); //$NON-NLS-1$
+	output.append(">, type<"); //$NON-NLS-1$
 	if (simpleName != null) 
-		buffer.append(simpleName);
+		output.append(simpleName);
 	else
-		buffer.append("*"); //$NON-NLS-1$
-	buffer.append(">, "); //$NON-NLS-1$
-	switch(getMatchMode()) {
-		case R_EXACT_MATCH : 
-			buffer.append("exact match, "); //$NON-NLS-1$
-			break;
-		case R_PREFIX_MATCH :
-			buffer.append("prefix match, "); //$NON-NLS-1$
-			break;
-		case R_PATTERN_MATCH :
-			buffer.append("pattern match, "); //$NON-NLS-1$
-			break;
-	}
-	if (isCaseSensitive())
-		buffer.append("case sensitive"); //$NON-NLS-1$
-	else
-		buffer.append("case insensitive"); //$NON-NLS-1$
-	return buffer.toString();
+		output.append("*"); //$NON-NLS-1$
+	return super.print(output);
 }
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeNamesCollector.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeNamesCollector.java
index ac6d8a6..dacb9f1 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeNamesCollector.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeNamesCollector.java
@@ -20,6 +20,7 @@
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 import org.eclipse.jdt.internal.core.*;
@@ -134,7 +135,7 @@
 			this.locator.basicParser().dietParse(sourceUnit, compilationResult) :
 			this.locator.basicParser().parse(sourceUnit, compilationResult);
 	if (unit != null) {
-		this.locator.lookupEnvironment.buildTypeBindings(unit);
+		this.locator.lookupEnvironment.buildTypeBindings(unit, null /*no access restriction*/);
 		this.locator.lookupEnvironment.completeTypeBindings(unit, !isTopLevelOrMember);
 		if (!isTopLevelOrMember) {
 			if (unit.scope != null)
@@ -153,7 +154,7 @@
 		this.locator.initialize(javaProject, 0);
 		try {
 			if (this.type.isBinary()) {
-				BinaryTypeBinding binding = this.locator.cacheBinaryType(this.type);
+				BinaryTypeBinding binding = this.locator.cacheBinaryType(this.type, null);
 				if (binding != null)
 					collectSuperTypeNames(binding);
 			} else {
@@ -203,7 +204,7 @@
 					parsedUnit.traverse(new TypeDeclarationVisitor(), parsedUnit.scope);
 			} else if (openable instanceof IClassFile) {
 				IClassFile classFile = (IClassFile) openable;
-				BinaryTypeBinding binding = this.locator.cacheBinaryType(classFile.getType());
+				BinaryTypeBinding binding = this.locator.cacheBinaryType(classFile.getType(), null);
 				if (matches(binding))
 					collectSuperTypeNames(binding);
 			}
@@ -249,10 +250,10 @@
 		IIndexConstants.TYPE_SUFFIX,
 		this.pattern.getMatchRule());
 	IndexQueryRequestor searchRequestor = new IndexQueryRequestor(){
-		public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant) {
+		public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant, AccessRestriction access) {
 			TypeDeclarationPattern record = (TypeDeclarationPattern)indexRecord;
 			if (record.enclosingTypeNames != IIndexConstants.ONE_ZERO_CHAR) {  // filter out local and anonymous classes
-				pathCollector.acceptIndexMatch(documentPath, indexRecord, participant);
+				pathCollector.acceptIndexMatch(documentPath, indexRecord, participant, access);
 			}
 			return true;
 		}		
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeReferencePattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeReferencePattern.java
index 05acc8d..1fab6c9 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeReferencePattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeReferencePattern.java
@@ -28,6 +28,7 @@
 public char[] enclosingTypeName;
 public char classOrInterface;
 public int modifiers;
+public char[][] typeParameterSignatures;
 
 protected boolean checkOnlySuperinterfaces; // used for IMPLEMENTORS
 
@@ -38,6 +39,7 @@
 	char[] packageName,
 	char[] typeName,
 	char[][] enclosingTypeNames,
+	char[][] typeParameterSignatures,
 	char classOrInterface,
 	char[] superTypeName,
 	char superClassOrInterface) {
@@ -72,14 +74,31 @@
 	char[] enclosingTypeName = CharOperation.concatWith(enclosingTypeNames, '$');
 	if (superQualification != null && CharOperation.equals(superQualification, packageName))
 		packageName = ONE_ZERO; // save some space
+	
+	char[] typeParameters = CharOperation.NO_CHAR;
+	int typeParametersLength = 0;
+	if (typeParameterSignatures != null) {
+		StringBuffer buffer = new StringBuffer();
+		for (int i = 0, length = typeParameterSignatures.length; i < length; i++) {
+			char[] typeParameter = typeParameterSignatures[i];
+			buffer.append(typeParameter);
+			typeParametersLength += typeParameter.length;
+			if (i != length-1) {
+				buffer.append(',');
+				typeParametersLength++;
+			}
+		}
+		typeParameters = new char[typeParametersLength];
+		buffer.getChars(0, typeParametersLength, typeParameters, 0);
+	}
 
-	// superSimpleName / superQualification / simpleName / enclosingTypeName / packageName / superClassOrInterface classOrInterface modifiers
+	// superSimpleName / superQualification / simpleName / enclosingTypeName / typeParameters / packageName / superClassOrInterface classOrInterface modifiers
 	int superLength = superSimpleName == null ? 0 : superSimpleName.length;
 	int superQLength = superQualification == null ? 0 : superQualification.length;
 	int simpleLength = simpleName == null ? 0 : simpleName.length;
 	int enclosingLength = enclosingTypeName == null ? 0 : enclosingTypeName.length;
 	int packageLength = packageName == null ? 0 : packageName.length;
-	char[] result = new char[superLength + superQLength + simpleLength + enclosingLength + packageLength + 8];
+	char[] result = new char[superLength + superQLength + simpleLength + enclosingLength + typeParametersLength + packageLength + 9];
 	int pos = 0;
 	if (superLength > 0) {
 		System.arraycopy(superSimpleName, 0, result, pos, superLength);
@@ -101,6 +120,11 @@
 		pos += enclosingLength;
 	}
 	result[pos++] = SEPARATOR;
+	if (typeParametersLength > 0) {
+		System.arraycopy(typeParameters, 0, result, pos, typeParametersLength);
+		pos += typeParametersLength;
+	}
+	result[pos++] = SEPARATOR;
 	if (packageLength > 0) {
 		System.arraycopy(packageName, 0, result, pos, packageLength);
 		pos += packageLength;
@@ -129,7 +153,7 @@
 	super(SUPER_REF_PATTERN, matchRule);
 }
 /*
- * superSimpleName / superQualification / simpleName / enclosingTypeName / pkgName / superClassOrInterface classOrInterface modifiers
+ * superSimpleName / superQualification / simpleName / enclosingTypeName / typeParameters / pkgName / superClassOrInterface classOrInterface modifiers
  */
 public void decodeIndexKey(char[] key) {
 	int slash = CharOperation.indexOf(SEPARATOR, key, 0);
@@ -153,6 +177,14 @@
 
 	slash = CharOperation.indexOf(SEPARATOR, key, start = slash + 1);
 	if (slash == start) {
+		this.typeParameterSignatures = null;
+	} else {
+		char[] names = CharOperation.subarray(key, start, slash);
+		this.typeParameterSignatures = CharOperation.splitOn(',', names);
+	}
+
+	slash = CharOperation.indexOf(SEPARATOR, key, start = slash + 1);
+	if (slash == start) {
 		this.pkgName = null;
 	} else {
 		char[] names = CharOperation.subarray(key, start, slash);
@@ -201,32 +233,16 @@
 
 	return index.query(getIndexCategories(), key, matchRule); // match rule is irrelevant when the key is null
 }
-public String toString(){
-	StringBuffer buffer = new StringBuffer(20);
-	buffer.append(
+protected StringBuffer print(StringBuffer output) {
+	output.append(
 		this.checkOnlySuperinterfaces
 			? "SuperInterfaceReferencePattern: <" //$NON-NLS-1$
 			: "SuperTypeReferencePattern: <"); //$NON-NLS-1$
 	if (superSimpleName != null) 
-		buffer.append(superSimpleName);
+		output.append(superSimpleName);
 	else
-		buffer.append("*"); //$NON-NLS-1$
-	buffer.append(">, "); //$NON-NLS-1$
-	switch(getMatchMode()) {
-		case R_EXACT_MATCH : 
-			buffer.append("exact match, "); //$NON-NLS-1$
-			break;
-		case R_PREFIX_MATCH :
-			buffer.append("prefix match, "); //$NON-NLS-1$
-			break;
-		case R_PATTERN_MATCH :
-			buffer.append("pattern match, "); //$NON-NLS-1$
-			break;
-	}
-	if (isCaseSensitive())
-		buffer.append("case sensitive"); //$NON-NLS-1$
-	else
-		buffer.append("case insensitive"); //$NON-NLS-1$
-	return buffer.toString();
+		output.append("*"); //$NON-NLS-1$
+	output.append(">"); //$NON-NLS-1$
+	return super.print(output);
 }
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationLocator.java
index 58ee864..e84e5a5 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationLocator.java
@@ -50,7 +50,7 @@
 
 	TypeBinding type = (TypeBinding) binding;
 
-	switch (this.pattern.classOrInterface) {
+	switch (this.pattern.typeSuffix) {
 		case CLASS_SUFFIX:
 			if (type.isInterface()) return IMPOSSIBLE_MATCH;
 			break;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationPattern.java
index 80f3a99..cac2eeb 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationPattern.java
@@ -25,12 +25,14 @@
 
 // set to CLASS_SUFFIX for only matching classes 
 // set to INTERFACE_SUFFIX for only matching interfaces
+// set to ENUM_SUFFIX for only matching enums
+// set to ANNOTATION_TYPE_SUFFIX for only matching annotation types
 // set to TYPE_SUFFIX for matching both classes and interfaces
-public char classOrInterface; 
+public char typeSuffix; 
 
 protected static char[][] CATEGORIES = { TYPE_DECL };
 
-public static char[] createIndexKey(char[] typeName, char[] packageName, char[][] enclosingTypeNames, char classOrInterface) {
+public static char[] createIndexKey(char[] typeName, char[] packageName, char[][] enclosingTypeNames, char typeSuffix) {
 	int typeNameLength = typeName == null ? 0 : typeName.length;
 	int packageLength = packageName == null ? 0 : packageName.length;
 	int enclosingNamesLength = 0;
@@ -65,7 +67,7 @@
 		}
 	}
 	result[pos++] = SEPARATOR;
-	result[pos] = classOrInterface;
+	result[pos] = typeSuffix;
 	return result;
 }
 
@@ -73,7 +75,7 @@
 	char[] pkg,
 	char[][] enclosingTypeNames,
 	char[] simpleName,
-	char classOrInterface,
+	char typeSuffix,
 	int matchRule) {
 
 	this(matchRule);
@@ -88,7 +90,7 @@
 			this.enclosingTypeNames[i] = CharOperation.toLowerCase(enclosingTypeNames[i]);
 	}
 	this.simpleName = isCaseSensitive() ? simpleName : CharOperation.toLowerCase(simpleName);
-	this.classOrInterface = classOrInterface;
+	this.typeSuffix = typeSuffix;
 
 	((InternalSearchPattern)this).mustResolve = this.pkg != null && this.enclosingTypeNames != null;
 }
@@ -117,7 +119,7 @@
 		this.enclosingTypeNames = CharOperation.equals(ONE_ZERO, names) ? ONE_ZERO_CHAR : CharOperation.splitOn('.', names);
 	}
 
-	this.classOrInterface = key[key.length - 1];
+	this.typeSuffix = key[key.length - 1];
 }
 public SearchPattern getBlankPattern() {
 	return new TypeDeclarationPattern(R_EXACT_MATCH | R_CASE_SENSITIVE);
@@ -127,10 +129,12 @@
 }
 public boolean matchesDecodedKey(SearchPattern decodedPattern) {
 	TypeDeclarationPattern pattern = (TypeDeclarationPattern) decodedPattern;
-	switch(this.classOrInterface) {
+	switch(this.typeSuffix) {
 		case CLASS_SUFFIX :
 		case INTERFACE_SUFFIX :
-			if (this.classOrInterface != pattern.classOrInterface) return false;
+		case ENUM_SUFFIX :
+		case ANNOTATION_TYPE_SUFFIX :
+			if (this.typeSuffix != pattern.typeSuffix) return false;
 	}
 
 	if (!matchesName(this.simpleName, pattern.simpleName))
@@ -173,8 +177,15 @@
 		case R_PATTERN_MATCH :
 			if (this.pkg == null) {
 				if (this.simpleName == null) {
-					if (this.classOrInterface == CLASS_SUFFIX || this.classOrInterface == INTERFACE_SUFFIX)
-						key = new char[] {ONE_STAR[0], SEPARATOR, this.classOrInterface}; // find all classes or all interfaces
+					switch(this.typeSuffix) {
+						case CLASS_SUFFIX :
+						case INTERFACE_SUFFIX :
+						case ENUM_SUFFIX :
+						case ANNOTATION_TYPE_SUFFIX :
+							key = new char[] {ONE_STAR[0],  SEPARATOR,
+								isCaseSensitive() ? this.typeSuffix : Character.toLowerCase(this.typeSuffix)}; // find all classes or all interfaces
+							break;
+					}
 				} else if (this.simpleName[this.simpleName.length - 1] != '*') {
 					key = CharOperation.concat(this.simpleName, ONE_STAR, SEPARATOR);
 				}
@@ -188,54 +199,44 @@
 
 	return index.query(getIndexCategories(), key, matchRule); // match rule is irrelevant when the key is null
 }
-public String toString() {
-	StringBuffer buffer = new StringBuffer(20);
-	switch (classOrInterface){
+protected StringBuffer print(StringBuffer output) {
+	switch (this.typeSuffix){
 		case CLASS_SUFFIX :
-			buffer.append("ClassDeclarationPattern: pkg<"); //$NON-NLS-1$
+			output.append("ClassDeclarationPattern: pkg<"); //$NON-NLS-1$
 			break;
 		case INTERFACE_SUFFIX :
-			buffer.append("InterfaceDeclarationPattern: pkg<"); //$NON-NLS-1$
+			output.append("InterfaceDeclarationPattern: pkg<"); //$NON-NLS-1$
+			break;
+		case ENUM_SUFFIX :
+			output.append("EnumDeclarationPattern: pkg<"); //$NON-NLS-1$
+			break;
+		case ANNOTATION_TYPE_SUFFIX :
+			output.append("AnnotationTypeDeclarationPattern: pkg<"); //$NON-NLS-1$
 			break;
 		default :
-			buffer.append("TypeDeclarationPattern: pkg<"); //$NON-NLS-1$
+			output.append("TypeDeclarationPattern: pkg<"); //$NON-NLS-1$
 			break;
 	}
 	if (pkg != null) 
-		buffer.append(pkg);
+		output.append(pkg);
 	else
-		buffer.append("*"); //$NON-NLS-1$
-	buffer.append(">, enclosing<"); //$NON-NLS-1$
+		output.append("*"); //$NON-NLS-1$
+	output.append(">, enclosing<"); //$NON-NLS-1$
 	if (enclosingTypeNames != null) {
 		for (int i = 0; i < enclosingTypeNames.length; i++){
-			buffer.append(enclosingTypeNames[i]);
+			output.append(enclosingTypeNames[i]);
 			if (i < enclosingTypeNames.length - 1)
-				buffer.append('.');
+				output.append('.');
 		}
 	} else {
-		buffer.append("*"); //$NON-NLS-1$
+		output.append("*"); //$NON-NLS-1$
 	}
-	buffer.append(">, type<"); //$NON-NLS-1$
+	output.append(">, type<"); //$NON-NLS-1$
 	if (simpleName != null) 
-		buffer.append(simpleName);
+		output.append(simpleName);
 	else
-		buffer.append("*"); //$NON-NLS-1$
-	buffer.append(">, "); //$NON-NLS-1$
-	switch(getMatchMode()){
-		case R_EXACT_MATCH : 
-			buffer.append("exact match, "); //$NON-NLS-1$
-			break;
-		case R_PREFIX_MATCH :
-			buffer.append("prefix match, "); //$NON-NLS-1$
-			break;
-		case R_PATTERN_MATCH :
-			buffer.append("pattern match, "); //$NON-NLS-1$
-			break;
-	}
-	if (isCaseSensitive())
-		buffer.append("case sensitive"); //$NON-NLS-1$
-	else
-		buffer.append("case insensitive"); //$NON-NLS-1$
-	return buffer.toString();
+		output.append("*"); //$NON-NLS-1$
+	output.append(">"); //$NON-NLS-1$
+	return super.print(output);
 }
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java
index de89e5a..8c8262f 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java
@@ -26,6 +26,7 @@
 protected boolean isDeclarationOfReferencedTypesPattern;
 
 public TypeReferenceLocator(TypeReferencePattern pattern) {
+
 	super(pattern);
 
 	this.pattern = pattern;
@@ -111,6 +112,25 @@
 	}
 	return IMPOSSIBLE_MATCH;
 }
+/* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#matchLevelAndReportImportRef(org.eclipse.jdt.internal.compiler.ast.ImportReference, org.eclipse.jdt.internal.compiler.lookup.Binding, org.eclipse.jdt.internal.core.search.matching.MatchLocator)
+ */
+protected void matchLevelAndReportImportRef(ImportReference importRef, Binding binding, MatchLocator locator) throws CoreException {
+	Binding refBinding = binding;
+	if (importRef.isStatic()) {
+		// for static import, binding can be a field binding or a member type binding
+		// verify that in this case binding is static and use declaring class for fields
+		if (binding instanceof FieldBinding) {
+			FieldBinding fieldBinding = (FieldBinding) binding;
+			if (!fieldBinding.isStatic()) return;
+			refBinding = fieldBinding.declaringClass;
+		} else if (binding instanceof MemberTypeBinding) {
+			MemberTypeBinding memberBinding = (MemberTypeBinding) binding;
+			if (!memberBinding.isStatic()) return;
+		}
+	}
+	super.matchLevelAndReportImportRef(importRef, refBinding, locator);
+}
 protected void matchReportImportRef(ImportReference importRef, Binding binding, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
 	if (this.isDeclarationOfReferencedTypesPattern) {
 		if ((element = findElement(element, accuracy)) != null) {
@@ -124,9 +144,29 @@
 		return;
 	}
 
+	// return if this is not necessary to report
+	if (this.pattern.isParameterized() && !this.isEquivalentMatch &&!this.isErasureMatch) {
+		return;
+	}
+
+	// set match rule
+	int rule = SearchMatch.A_ACCURATE;
+	boolean patternHasParameters = false;
+	if (this.pattern.isParameterized()) {
+		patternHasParameters = this.pattern.typeArguments[0] != null && this.pattern.typeArguments[0].length != 0;
+	}
+	if (patternHasParameters) { // binding has no type params, compatible erasure if pattern does
+		rule = SearchPattern.R_EQUIVALENT_MATCH | SearchPattern.R_ERASURE_MATCH;
+	}
+	
+	// Try to find best selection for match
 	if (binding instanceof ReferenceBinding) {
-		int lastIndex = importRef.tokens.length - 1;
 		ReferenceBinding typeBinding = (ReferenceBinding) binding;
+		int lastIndex = importRef.tokens.length - 1;
+		if (importRef.isStatic() && !importRef.onDemand && !typeBinding.isMemberType()) {
+			// for field static import, do not use last token
+			lastIndex--;
+		}
 		if (typeBinding instanceof ProblemReferenceBinding) {
 			ProblemReferenceBinding pbBinding = (ProblemReferenceBinding) typeBinding;
 			typeBinding = pbBinding.original;
@@ -134,12 +174,25 @@
 		}
 		// try to match all enclosing types for which the token matches as well.
 		while (typeBinding != null && lastIndex >= 0) {
-			if (resolveLevelForType(this.pattern.simpleName, this.pattern.qualification, typeBinding) == ACCURATE_MATCH) {
+			if (resolveLevelForType(typeBinding) != IMPOSSIBLE_MATCH) {
 				if (locator.encloses(element)) {
 					long[] positions = importRef.sourcePositions;
-					int start = (int) ((positions[this.pattern.qualification == null ? lastIndex : 0]) >>> 32);
+					// index now depends on pattern type signature
+					int index = lastIndex;
+					if (this.pattern.qualification != null) {
+						if (this.pattern.typeSignatures != null) {
+							if (this.pattern.typeSignatures.length > 1) {
+								index = lastIndex - (this.pattern.typeSignatures.length - 1);
+							}
+						} else {
+							index = lastIndex - this.pattern.segmentsSize;
+						}
+					}
+					if (index < 0) index = 0;
+					int start = (int) ((positions[index]) >>> 32);
 					int end = (int) positions[lastIndex];
-					SearchMatch match = locator.newTypeReferenceMatch(element, accuracy, start, end-start+1, importRef);
+					// report match
+					SearchMatch match = locator.newTypeReferenceMatch(element, accuracy, start, end-start+1, rule, importRef);
 					locator.report(match);
 				}
 				return;
@@ -148,17 +201,23 @@
 			typeBinding = typeBinding.enclosingType();
 		}
 	}
-	locator.reportAccurateTypeReference(importRef, this.pattern.simpleName, element, accuracy);
+	locator.reportAccurateTypeReference(importRef, this.pattern.simpleName, element, accuracy, rule);
 }
 protected void matchReportReference(ArrayTypeReference arrayRef, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
 	if (this.pattern.simpleName == null) {
+		// TODO (frederic) need to add a test for this case while searching generic types...
 		if (locator.encloses(element)) {
 			int offset = arrayRef.sourceStart;
 			SearchMatch match = locator.newTypeReferenceMatch(element, accuracy, offset, arrayRef.sourceEnd-offset+1, arrayRef);
 			locator.report(match);
+			return;
 		}
-	} else
-		locator.reportAccurateTypeReference(arrayRef, this.pattern.simpleName, element, accuracy);
+	}
+	if (arrayRef.resolvedType != null) {
+		matchReportReference(arrayRef, element, accuracy, arrayRef.sourceStart, arrayRef.sourceEnd, -1, arrayRef.resolvedType.leafComponentType(), locator);
+		return;
+	}
+	locator.reportAccurateTypeReference(arrayRef, this.pattern.simpleName, element, accuracy);
 }
 protected void matchReportReference(ASTNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
 	if (this.isDeclarationOfReferencedTypesPattern) {
@@ -174,6 +233,11 @@
 	else if (reference instanceof ArrayTypeReference)
 		matchReportReference((ArrayTypeReference) reference, element, accuracy, locator);
 	else {
+		TypeBinding typeBinding = reference instanceof Expression ? ((Expression)reference).resolvedType : null;
+		if (typeBinding != null) {
+			matchReportReference((Expression)reference, element, accuracy, reference.sourceStart, reference.sourceEnd, -1, typeBinding, locator);
+			return;
+		}
 		int offset = reference.sourceStart;
 		SearchMatch match = locator.newTypeReferenceMatch(element, accuracy, offset, reference.sourceEnd-offset+1, reference);
 		locator.report(match);
@@ -184,16 +248,16 @@
 	TypeBinding typeBinding = null;
 	int lastIndex = qNameRef.tokens.length - 1;
 	switch (qNameRef.bits & ASTNode.RestrictiveFlagMASK) {
-		case BindingIds.FIELD : // reading a field
+		case Binding.FIELD : // reading a field
 			typeBinding = qNameRef.actualReceiverType;
 			lastIndex -= qNameRef.otherBindings == null ? 1 : qNameRef.otherBindings.length + 1;
 			break;
-		case BindingIds.TYPE : //=============only type ==============
+		case Binding.TYPE : //=============only type ==============
 			if (binding instanceof TypeBinding)
 				typeBinding = (TypeBinding) binding;
 			break;
-		case BindingIds.VARIABLE : //============unbound cases===========
-		case BindingIds.TYPE | BindingIds.VARIABLE :
+		case Binding.VARIABLE : //============unbound cases===========
+		case Binding.TYPE | Binding.VARIABLE :
 			if (binding instanceof ProblemReferenceBinding) {
 				typeBinding = (TypeBinding) binding;
 			} else if (binding instanceof ProblemFieldBinding) {
@@ -213,7 +277,7 @@
 	if (typeBinding instanceof ReferenceBinding) {
 		ReferenceBinding refBinding = (ReferenceBinding) typeBinding; 
 		while (refBinding != null && lastIndex >= 0) {
-			if (resolveLevelForType(this.pattern.simpleName, this.pattern.qualification, refBinding) == ACCURATE_MATCH) {
+			if (resolveLevelForType(refBinding) == ACCURATE_MATCH) {
 				if (locator.encloses(element)) {
 					long[] positions = qNameRef.sourcePositions;
 					int start = (int) ((positions[this.pattern.qualification == null ? lastIndex : 0]) >>> 32);
@@ -243,13 +307,26 @@
 	if (typeBinding instanceof ReferenceBinding) {
 		ReferenceBinding refBinding = (ReferenceBinding) typeBinding; 
 		while (refBinding != null && lastIndex >= 0) {
-			if (resolveLevelForType(this.pattern.simpleName, this.pattern.qualification, refBinding) == ACCURATE_MATCH) {
+			if (resolveLevelForType(refBinding) != IMPOSSIBLE_MATCH) {
 				if (locator.encloses(element)) {
 					long[] positions = qTypeRef.sourcePositions;
-					int start = (int) ((positions[this.pattern.qualification == null ? lastIndex : 0]) >>> 32);
+					// index now depends on pattern type signature
+					int index = lastIndex;
+					if (this.pattern.qualification != null) {
+						if (this.pattern.typeSignatures != null) {
+							if (this.pattern.typeSignatures.length > 1) {
+								index = lastIndex - (this.pattern.typeSignatures.length - 1);
+							}
+						} else {
+							index = lastIndex - this.pattern.segmentsSize;
+						}
+					}
+					if (index < 0) index = 0;
+					int start = (int) ((positions[index]) >>> 32);
 					int end = (int) positions[lastIndex];
-					SearchMatch match = locator.newTypeReferenceMatch(element, accuracy, start, end-start+1, qTypeRef);
-					locator.report(match);
+
+					//  Look if there's a need to special report for parameterized type
+					matchReportReference(qTypeRef, element, accuracy, start, end, lastIndex, refBinding, locator);
 				}
 				return;
 			}
@@ -259,6 +336,68 @@
 	}
 	locator.reportAccurateTypeReference(qTypeRef, this.pattern.simpleName, element, accuracy);
 }
+void matchReportReference(Expression expr, IJavaElement element, int accuracy, int start, int end, int lastIndex, TypeBinding refBinding, MatchLocator locator) throws CoreException {
+
+	// Look if there's a need to special report for parameterized type
+	int rule = SearchPattern.R_EXACT_MATCH;
+	int refinedAccuracy = accuracy;
+	boolean patternHasParameters = false;
+	if (this.pattern.isParameterized()) {
+		patternHasParameters = this.pattern.typeArguments[0] != null && this.pattern.typeArguments[0].length != 0;
+	}
+	if (refBinding.isParameterizedType() || refBinding.isRawType()) {
+
+		// Try to refine accuracy
+		ParameterizedTypeBinding parameterizedBinding = (ParameterizedTypeBinding)refBinding;
+		refinedAccuracy = refineAccuracy(accuracy, parameterizedBinding, this.pattern.typeArguments, this.pattern.typeSignatures==null, 0, locator);
+		
+		// See whether it is necessary to report or not
+		boolean report = refinedAccuracy != -1; // impossible match
+		if (report && (refinedAccuracy & SearchPattern.R_ERASURE_MATCH) != 0) { // erasure match
+			if ((refinedAccuracy & SearchPattern.R_EQUIVALENT_MATCH) != 0) { // raw match
+				report = this.isEquivalentMatch || this.isErasureMatch; // report only if pattern is equivalent or erasure
+			} else {
+				report = this.isErasureMatch; // report only if pattern is erasure
+			}
+		}
+		else if (report && (refinedAccuracy & SearchPattern.R_EQUIVALENT_MATCH) != 0) { // equivalent match
+			report  = this.isEquivalentMatch || this.isErasureMatch; // report only if pattern is equivalent or erasure
+		}
+		if (!report)return;
+
+		// Set rule
+		rule |= refinedAccuracy & RULE_MASK;
+		refinedAccuracy = refinedAccuracy & (~RULE_MASK);
+
+		// Make a special report for parameterized types if necessary
+		 if (refBinding.isParameterizedType() && this.pattern.isParameterized())  {
+			TypeReference typeRef = null;
+			TypeReference[] typeArguments = null;
+			if (expr instanceof ParameterizedQualifiedTypeReference) {
+				typeRef = (ParameterizedQualifiedTypeReference) expr;
+				typeArguments = ((ParameterizedQualifiedTypeReference) expr).typeArguments[lastIndex];
+			}
+			else if (expr instanceof ParameterizedSingleTypeReference) {
+				typeRef = (ParameterizedSingleTypeReference) expr;
+				typeArguments = ((ParameterizedSingleTypeReference) expr).typeArguments;
+			}
+			if (typeRef != null) {
+				locator.reportAccurateParameterizedTypeReference(typeRef, start, lastIndex, typeArguments, element, refinedAccuracy, rule);
+				return;
+			}
+		}
+	} else if (patternHasParameters) { // binding has no type params, compatible erasure if pattern does
+		rule = SearchPattern.R_ERASURE_MATCH;
+	}
+
+	// Report match
+	if (expr instanceof ArrayTypeReference)
+		locator.reportAccurateTypeReference(expr, this.pattern.simpleName, element, refinedAccuracy, rule);
+	else {
+		SearchMatch match = locator.newTypeReferenceMatch(element, refinedAccuracy, start, end-start+1, rule, expr);
+		locator.report(match);
+	}
+}
 protected int referenceType() {
 	return IJavaElement.TYPE;
 }
@@ -273,16 +412,16 @@
 		Binding binding = qNameRef.binding;
 		maxType = qNameRef.tokens.length - 1;
 		switch (qNameRef.bits & ASTNode.RestrictiveFlagMASK) {
-			case BindingIds.FIELD : // reading a field
+			case Binding.FIELD : // reading a field
 				typeBinding = qNameRef.actualReceiverType;
 				maxType -= qNameRef.otherBindings == null ? 1 : qNameRef.otherBindings.length + 1;
 				break;
-			case BindingIds.TYPE : //=============only type ==============
+			case Binding.TYPE : //=============only type ==============
 				if (binding instanceof TypeBinding)
 					typeBinding = (TypeBinding) binding;
 				break;
-			case BindingIds.VARIABLE : //============unbound cases===========
-			case BindingIds.TYPE | BindingIds.VARIABLE :
+			case Binding.VARIABLE : //============unbound cases===========
+			case Binding.TYPE | Binding.VARIABLE :
 				if (binding instanceof ProblemFieldBinding) {
 					typeBinding = qNameRef.actualReceiverType;
 					maxType -= qNameRef.otherBindings == null ? 1 : qNameRef.otherBindings.length + 1;
@@ -303,8 +442,12 @@
 	if (typeBinding instanceof ArrayBinding)
 		typeBinding = ((ArrayBinding) typeBinding).leafComponentType;
 	if (typeBinding == null || typeBinding instanceof BaseTypeBinding) return;
-	if (typeBinding instanceof ProblemReferenceBinding)
-		typeBinding = ((ProblemReferenceBinding) typeBinding).original;
+	if (typeBinding instanceof ProblemReferenceBinding) {
+		ReferenceBinding original = ((ProblemReferenceBinding) typeBinding).original;
+		if (original == null) return; // original may not be set (bug 71279)
+		typeBinding = original;
+	}
+	typeBinding = typeBinding.erasure();
 	reportDeclaration((ReferenceBinding) typeBinding, maxType, locator, knownTypes);
 }
 protected void reportDeclaration(ReferenceBinding typeBinding, int maxType, MatchLocator locator, SimpleSet knownTypes) throws CoreException {
@@ -324,6 +467,8 @@
 			if (isBinary) {
 				locator.reportBinaryMemberDeclaration(resource, type, info, SearchMatch.A_ACCURATE);
 			} else {
+				if (typeBinding instanceof ParameterizedTypeBinding)
+					typeBinding = ((ParameterizedTypeBinding) typeBinding).type;
 				ClassScope scope = ((SourceTypeBinding) typeBinding).scope;
 				if (scope != null) {
 					TypeDeclaration typeDecl = scope.referenceContext;
@@ -378,21 +523,21 @@
 		if (binding instanceof ProblemReferenceBinding)
 			binding = ((ProblemReferenceBinding) binding).original;
 		if (binding instanceof ReferenceBinding)
-			return resolveLevelForType(this.pattern.simpleName, this.pattern.qualification, (ReferenceBinding) binding);
+			return resolveLevelForType((ReferenceBinding) binding);
 		return binding == null || binding instanceof ProblemBinding ? INACCURATE_MATCH : IMPOSSIBLE_MATCH;
 	}
 
 	TypeBinding typeBinding = null;
 	QualifiedNameReference qNameRef = (QualifiedNameReference) nameRef;
 	switch (qNameRef.bits & ASTNode.RestrictiveFlagMASK) {
-		case BindingIds.FIELD : // reading a field
+		case Binding.FIELD : // reading a field
 			if (qNameRef.tokens.length < (qNameRef.otherBindings == null ? 2 : qNameRef.otherBindings.length + 2))
 				return IMPOSSIBLE_MATCH; // must be at least A.x
 			typeBinding = nameRef.actualReceiverType;
 			break;
-		case BindingIds.LOCAL : // reading a local variable
+		case Binding.LOCAL : // reading a local variable
 			return IMPOSSIBLE_MATCH; // no type match in it
-		case BindingIds.TYPE : //=============only type ==============
+		case Binding.TYPE : //=============only type ==============
 			if (binding instanceof TypeBinding)
 				typeBinding = (TypeBinding) binding;
 			break;
@@ -400,8 +545,8 @@
 		 * Handling of unbound qualified name references. The match may reside in the resolved fragment,
 		 * which is recorded inside the problem binding, along with the portion of the name until it became a problem.
 		 */
-		case BindingIds.VARIABLE : //============unbound cases===========
-		case BindingIds.TYPE | BindingIds.VARIABLE :
+		case Binding.VARIABLE : //============unbound cases===========
+		case Binding.TYPE | Binding.VARIABLE :
 			if (binding instanceof ProblemReferenceBinding) {
 				typeBinding = (TypeBinding) binding;
 			} else if (binding instanceof ProblemFieldBinding) {
@@ -425,11 +570,23 @@
 	if (typeBinding instanceof ProblemReferenceBinding)
 		typeBinding = ((ProblemReferenceBinding) typeBinding).original;
 
-	if (typeRef instanceof SingleTypeReference)
-		return resolveLevelForType(this.pattern.simpleName, this.pattern.qualification, typeBinding);
-	else
+	if (typeRef instanceof SingleTypeReference) {
+		return resolveLevelForType(typeBinding);
+	} else
 		return resolveLevelForTypeOrEnclosingTypes(this.pattern.simpleName, this.pattern.qualification, typeBinding);
 }
+/* (non-Javadoc)
+ * Resolve level for type with a given binding.
+ * This is just an helper to avoid call of method with all parameters...
+ */
+protected int resolveLevelForType(TypeBinding typeBinding) {
+	return resolveLevelForType(
+			this.pattern.simpleName,
+			this.pattern.qualification,
+			this.pattern.typeArguments,
+			0,
+			typeBinding);
+}
 /**
  * Returns whether the given type binding or one of its enclosing types
  * matches the given simple name pattern and qualification pattern.
@@ -442,9 +599,9 @@
 
 	if (binding instanceof ReferenceBinding) {
 		ReferenceBinding type = (ReferenceBinding) binding;
-		char[] qualifiedPattern = qualifiedPattern(simpleNamePattern, qualificationPattern);
 		while (type != null) {
-			if (resolveLevelForType(qualifiedPattern, type) == ACCURATE_MATCH) return ACCURATE_MATCH;
+			int level = resolveLevelForType(type);
+			if (level != IMPOSSIBLE_MATCH) return level;
 	
 			type = type.enclosingType();
 		}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferencePattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferencePattern.java
index 3faf697..3fec794 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferencePattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferencePattern.java
@@ -10,6 +10,11 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.matching;
 
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.ITypeParameter;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.search.SearchPattern;
 import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
@@ -18,10 +23,11 @@
 
 protected char[] qualification;
 protected char[] simpleName;
-
+	
 protected char[] currentCategory;
 
 /* Optimization: case where simpleName == null */
+public int segmentsSize;
 protected char[][] segments;
 protected int currentSegment;
 
@@ -37,9 +43,30 @@
 		this.segments = this.qualification == null ? ONE_STAR_CHAR : CharOperation.splitOn('.', this.qualification);
 	else
 		this.segments = null;
+	
+	if (this.segments == null)
+		if (this.qualification == null)
+			this.segmentsSize =  0;
+		else
+			this.segmentsSize =  CharOperation.occurencesOf('.', this.qualification) + 1;
+	else
+		this.segmentsSize = this.segments.length;
 
 	((InternalSearchPattern)this).mustResolve = true; // always resolve (in case of a simple name reference being a potential match)
 }
+/*
+ * Instanciate a type reference pattern with additional information for generics search
+ */
+public TypeReferencePattern(char[] qualification, char[] simpleName, String signature, int matchRule) {
+	this(qualification, simpleName,matchRule);
+
+	if (signature != null) computeSignature(signature);
+}
+public TypeReferencePattern(char[] qualification, char[] simpleName, IType type, int matchRule) {
+	this(qualification, simpleName, matchRule);
+
+	this.typeArguments = typeParameterNames(type);
+}
 TypeReferencePattern(int matchRule) {
 	super(TYPE_REF_PATTERN, matchRule);
 }
@@ -77,34 +104,58 @@
 	if (this.segments != null)
 		this.currentSegment = this.segments.length - 1;
 }
-public String toString() {
-	StringBuffer buffer = new StringBuffer(20);
-	buffer.append("TypeReferencePattern: qualification<"); //$NON-NLS-1$
+protected StringBuffer print(StringBuffer output) {
+	output.append("TypeReferencePattern: qualification<"); //$NON-NLS-1$
 	if (qualification != null) 
-		buffer.append(qualification);
+		output.append(qualification);
 	else
-		buffer.append("*"); //$NON-NLS-1$
-	buffer.append(">, type<"); //$NON-NLS-1$
+		output.append("*"); //$NON-NLS-1$
+	output.append(">, type<"); //$NON-NLS-1$
 	if (simpleName != null) 
-		buffer.append(simpleName);
+		output.append(simpleName);
 	else
-		buffer.append("*"); //$NON-NLS-1$
-	buffer.append(">, "); //$NON-NLS-1$
-	switch(getMatchMode()) {
-		case R_EXACT_MATCH : 
-			buffer.append("exact match, "); //$NON-NLS-1$
-			break;
-		case R_PREFIX_MATCH :
-			buffer.append("prefix match, "); //$NON-NLS-1$
-			break;
-		case R_PATTERN_MATCH :
-			buffer.append("pattern match, "); //$NON-NLS-1$
-			break;
+		output.append("*"); //$NON-NLS-1$
+	output.append(">"); //$NON-NLS-1$
+	return super.print(output);
+}
+/*
+ * Returns the type parameter names of the given type.
+ */
+private char[][][] typeParameterNames(IType type) {
+	char[][][] typeParameters = new char[10][][];
+	int ptr = -1;
+	boolean hasParameters = false;
+	try {
+		IJavaElement parent = type;
+		ITypeParameter[] parameters = null;
+		while (parent != null) {
+			if (parent.getElementType() != IJavaElement.TYPE) {
+				if (!hasParameters) return null;
+				if (++ptr < typeParameters.length)
+					System.arraycopy(typeParameters, 0, typeParameters = new char[ptr][][], 0, ptr);
+				return typeParameters;
+			}
+			if (++ptr > typeParameters.length) {
+				System.arraycopy(typeParameters, 0, typeParameters = new char[typeParameters.length+10][][], 0, ptr);
+			}
+			IType parentType = (IType) parent;
+			parameters = parentType.getTypeParameters();
+			int length = parameters==null ? 0 : parameters.length;
+			if (length > 0) {
+				hasParameters = true;
+				typeParameters[ptr] = new char[length][];
+				for (int i=0; i<length; i++)
+					typeParameters[ptr][i] = Signature.createTypeSignature(parameters[i].getElementName(), false).toCharArray();
+			}
+			parent = parent.getParent();
+		}
 	}
-	if (isCaseSensitive())
-		buffer.append("case sensitive"); //$NON-NLS-1$
-	else
-		buffer.append("case insensitive"); //$NON-NLS-1$
-	return buffer.toString();
+	catch (JavaModelException jme) {
+		return null;
+	}
+	if (!hasParameters) return null;
+	if (++ptr < typeParameters.length)
+		System.arraycopy(typeParameters, 0, typeParameters = new char[ptr][][], 0, ptr);
+	return typeParameters;
 }
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java
index 1375e3a..9b28f6c 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java
@@ -101,13 +101,15 @@
 			synchronized(this) {
 				for (int i = this.jobStart; i <= this.jobEnd; i++) {
 					currentJob = this.awaitingJobs[i];
-					this.awaitingJobs[i] = null;
-					if (!(jobFamily == null || currentJob.belongsTo(jobFamily))) { // copy down, compacting
-						this.awaitingJobs[++loc] = currentJob;
-					} else {
-						if (VERBOSE)
-							Util.verbose("-> discarding background job  - " + currentJob); //$NON-NLS-1$
-						currentJob.cancel();
+					if (currentJob != null) { // sanity check
+						this.awaitingJobs[i] = null;
+						if (!(jobFamily == null || currentJob.belongsTo(jobFamily))) { // copy down, compacting
+							this.awaitingJobs[++loc] = currentJob;
+						} else {
+							if (VERBOSE)
+								Util.verbose("-> discarding background job  - " + currentJob); //$NON-NLS-1$
+							currentJob.cancel();
+						}
 					}
 				}
 				this.jobStart = 0;
@@ -125,6 +127,11 @@
 			Util.verbose("ENABLING  background indexing"); //$NON-NLS-1$
 		this.notifyAll(); // wake up the background thread if it is waiting (context must be synchronized)			
 	}
+	protected synchronized boolean isJobWaiting(IJob request) {
+		for (int i = this.jobEnd; i > this.jobStart; i--) // don't check job at jobStart, as it may have already started
+			if (request.equals(this.awaitingJobs[i])) return true;
+		return false;
+	}
 	/**
 	 * Advance to the next available job, once the current one has been completed.
 	 * Note: clients awaiting until the job count is zero are still waiting at this point.