import eclipse 3.1 M4 compiler
authorcrawshaw <crawshaw@ibex.org>
Fri, 31 Dec 2004 10:07:14 +0000 (10:07 +0000)
committercrawshaw <crawshaw@ibex.org>
Fri, 31 Dec 2004 10:07:14 +0000 (10:07 +0000)
darcs-hash:20041231100714-2eb37-8bdd1b5af884c3d6c9242e3e7964c2b8964ad7c3.gz

223 files changed:
src/org/eclipse/jdt/core/Signature.java [new file with mode: 0644]
src/org/eclipse/jdt/core/compiler/CharOperation.java
src/org/eclipse/jdt/core/compiler/IProblem.java
src/org/eclipse/jdt/core/compiler/InvalidInputException.java
src/org/eclipse/jdt/internal/compiler/ASTVisitor.java
src/org/eclipse/jdt/internal/compiler/ClassFile.java
src/org/eclipse/jdt/internal/compiler/CompilationResult.java
src/org/eclipse/jdt/internal/compiler/Compiler.java
src/org/eclipse/jdt/internal/compiler/ConfigurableOption.java [deleted file]
src/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
src/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
src/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
src/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
src/org/eclipse/jdt/internal/compiler/ast/Annotation.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/ast/AnnotationMethodDeclaration.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/ast/Argument.java
src/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
src/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
src/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
src/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
src/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
src/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java
src/org/eclipse/jdt/internal/compiler/ast/Assignment.java
src/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
src/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
src/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
src/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java
src/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
src/org/eclipse/jdt/internal/compiler/ast/Clinit.java
src/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
src/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
src/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
src/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
src/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
src/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java
src/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
src/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
src/org/eclipse/jdt/internal/compiler/ast/Expression.java
src/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java
src/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
src/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
src/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java
src/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
src/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
src/org/eclipse/jdt/internal/compiler/ast/ImplicitDocTypeReference.java
src/org/eclipse/jdt/internal/compiler/ast/ImportReference.java
src/org/eclipse/jdt/internal/compiler/ast/Initializer.java
src/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
src/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
src/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
src/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java
src/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.java
src/org/eclipse/jdt/internal/compiler/ast/JavadocArrayQualifiedTypeReference.java
src/org/eclipse/jdt/internal/compiler/ast/JavadocArraySingleTypeReference.java
src/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java
src/org/eclipse/jdt/internal/compiler/ast/JavadocImportReference.java [deleted file]
src/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java
src/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java
src/org/eclipse/jdt/internal/compiler/ast/JavadocReturnStatement.java
src/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.java
src/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java
src/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
src/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java
src/org/eclipse/jdt/internal/compiler/ast/MarkerAnnotation.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
src/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
src/org/eclipse/jdt/internal/compiler/ast/NameReference.java
src/org/eclipse/jdt/internal/compiler/ast/NormalAnnotation.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
src/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java
src/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
src/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
src/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java
src/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java
src/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
src/org/eclipse/jdt/internal/compiler/ast/Reference.java
src/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
src/org/eclipse/jdt/internal/compiler/ast/SingleMemberAnnotation.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
src/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
src/org/eclipse/jdt/internal/compiler/ast/Statement.java
src/org/eclipse/jdt/internal/compiler/ast/StringLiteralConcatenation.java
src/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java
src/org/eclipse/jdt/internal/compiler/ast/SuperReference.java
src/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
src/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
src/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
src/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
src/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java
src/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
src/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
src/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
src/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
src/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
src/org/eclipse/jdt/internal/compiler/ast/Wildcard.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
src/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.java
src/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
src/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
src/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java
src/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
src/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
src/org/eclipse/jdt/internal/compiler/codegen/FieldNameAndTypeCache.java [deleted file]
src/org/eclipse/jdt/internal/compiler/codegen/MethodNameAndTypeCache.java [deleted file]
src/org/eclipse/jdt/internal/compiler/codegen/QualifiedNamesConstants.java [deleted file]
src/org/eclipse/jdt/internal/compiler/env/AccessRestriction.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/env/IBinaryField.java
src/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java
src/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
src/org/eclipse/jdt/internal/compiler/env/IConstants.java
src/org/eclipse/jdt/internal/compiler/env/IDependent.java
src/org/eclipse/jdt/internal/compiler/env/IGenericType.java
src/org/eclipse/jdt/internal/compiler/env/ISourceMethod.java
src/org/eclipse/jdt/internal/compiler/env/ISourceType.java
src/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
src/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java
src/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
src/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
src/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
src/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
src/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
src/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
src/org/eclipse/jdt/internal/compiler/impl/Constant.java
src/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java
src/org/eclipse/jdt/internal/compiler/impl/StringConstant.java
src/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/BaseTypes.java
src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/Binding.java
src/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
src/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
src/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
src/org/eclipse/jdt/internal/compiler/lookup/CompilerModifiers.java
src/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/ImportBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java
src/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
src/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
src/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
src/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedFieldBinding.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/lookup/ProblemBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
src/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/Scope.java
src/org/eclipse/jdt/internal/compiler/lookup/SignatureWrapper.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/Substitution.java [moved from src/org/eclipse/jdt/internal/compiler/lookup/BindingIds.java with 69% similarity]
src/org/eclipse/jdt/internal/compiler/lookup/SyntheticArgumentBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java [moved from src/org/eclipse/jdt/internal/compiler/lookup/SyntheticAccessMethodBinding.java with 69% similarity]
src/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
src/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
src/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
src/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
src/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java
src/org/eclipse/jdt/internal/compiler/parser/Parser.java
src/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
src/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java
src/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java
src/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java
src/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java
src/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java
src/org/eclipse/jdt/internal/compiler/parser/Scanner.java
src/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
src/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java
src/org/eclipse/jdt/internal/compiler/parser/diagnose/RangeUtil.java
src/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser10.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser11.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser12.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser13.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser14.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser15.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser16.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser17.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser18.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser19.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser20.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser21.rsc [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser6.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser7.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser8.rsc
src/org/eclipse/jdt/internal/compiler/parser/parser9.rsc
src/org/eclipse/jdt/internal/compiler/parser/readableNames.properties
src/org/eclipse/jdt/internal/compiler/problem/AbortCompilationUnit.java
src/org/eclipse/jdt/internal/compiler/problem/AbortMethod.java
src/org/eclipse/jdt/internal/compiler/problem/AbortType.java
src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
src/org/eclipse/jdt/internal/compiler/problem/ShouldNotImplement.java
src/org/eclipse/jdt/internal/compiler/problem/messages.properties
src/org/eclipse/jdt/internal/compiler/util/FloatUtil.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/util/HashtableOfIntValues.java [deleted file]
src/org/eclipse/jdt/internal/compiler/util/HashtableOfLong.java [deleted file]
src/org/eclipse/jdt/internal/compiler/util/SimpleLookupTable.java [new file with mode: 0644]
src/org/eclipse/jdt/internal/compiler/util/Util.java
src/org/eclipse/jdt/internal/compiler/util/messages.properties
src/org/ibex/tool/Compiler.java

diff --git a/src/org/eclipse/jdt/core/Signature.java b/src/org/eclipse/jdt/core/Signature.java
new file mode 100644 (file)
index 0000000..7a2fa00
--- /dev/null
@@ -0,0 +1,2809 @@
+/*******************************************************************************
+ * 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
+ *     IBM Corporation - added J2SE 1.5 support
+ *******************************************************************************/
+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>
+ * Signatures obtained from parsing source (".java") files differ subtly from
+ * ones obtained from pre-compiled binary (".class") files in class names are
+ * usually left unresolved in the former. For example, the normal resolved form
+ * of the type "String" embeds the class's package name ("Ljava.lang.String;"
+ * or "Ljava/lang/String;"), whereas the unresolved form contains only what is
+ * written "QString;".
+ * </p>
+ * <p>
+ * Generic types introduce to the Java language in J2SE 1.5 add three new
+ * facets to signatures: type variables, parameterized types with type arguments,
+ * and formal type parameters. <it>Rich</it> signatures containing these facets
+ * only occur when dealing with code that makes overt use of the new language
+ * features. All other code, and certainly all Java code written or compiled
+ * with J2SE 1.4 or earlier, involved only <it>simple</it> signatures.
+ * </p>
+ * <p>
+ * The syntax for a type signature is:
+ * <pre>
+ * TypeSignature ::=
+ *     "B"  // byte
+ *   | "C"  // char
+ *   | "D"  // double
+ *   | "F"  // float
+ *   | "I"  // int
+ *   | "J"  // long
+ *   | "S"  // short
+ *   | "V"  // void
+ *   | "Z"  // boolean
+ *   | "T" + Identifier + ";" // type variable
+ *   | "[" + TypeSignature  // array X[]
+ *   | ResolvedClassTypeSignature
+ *   | UnresolvedClassTypeSignature
+ * 
+ * ResolvedClassTypeSignature ::= // resolved named type (in compiled code)
+ *     "L" + Identifier + OptionalTypeArguments
+ *           ( ( "." | "/" ) + Identifier + OptionalTypeArguments )* + ";"
+ * 
+ * UnresolvedClassTypeSignature ::= // unresolved named type (in source code)
+ *     "Q" + Identifier + OptionalTypeArguments
+ *           ( ( "." | "/" ) + Identifier + OptionalTypeArguments )* + ";"
+ * 
+ * OptionalTypeArguments ::=
+ *     "&lt;" + TypeArgument+ + "&gt;" 
+ *   |
+ * 
+ * TypeArgument ::=
+ *   | TypeSignature
+ *   | "*" // wildcard ?
+ *   | "+" TypeSignature // wildcard ? extends X
+ *   | "-" TypeSignature // wildcard ? super X
+ * </pre>
+ * </p>
+ * <p>
+ * Examples:
+ * <ul>
+ *   <li><code>"[[I"</code> denotes <code>int[][]</code></li>
+ *   <li><code>"Ljava.lang.String;"</code> denotes <code>java.lang.String</code> in compiled code</li>
+ *   <li><code>"QString;"</code> denotes <code>String</code> in source code</li>
+ *   <li><code>"Qjava.lang.String;"</code> denotes <code>java.lang.String</code> in source code</li>
+ *   <li><code>"[QString;"</code> denotes <code>String[]</code> in source code</li>
+ *   <li><code>"QMap&lt;QString;&ast;&gt;;"</code> denotes <code>Map&lt;String,?&gt;</code> in source code</li>
+ *   <li><code>"Qjava.util.List&ltTV;&gt;;"</code> denotes <code>java.util.List&lt;V&gt;</code> in source code</li>
+ * </ul>
+ * </p>
+ * <p>
+ * The syntax for a method signature is: 
+ * <pre>
+ * MethodSignature ::= "(" + ParamTypeSignature* + ")" + ReturnTypeSignature
+ * ParamTypeSignature ::= TypeSignature
+ * ReturnTypeSignature ::= TypeSignature
+ * </pre>
+ * <p>
+ * Examples:
+ * <ul>
+ *   <li><code>"()I"</code> denotes <code>int foo()</code></li>
+ *   <li><code>"([Ljava.lang.String;)V"</code> denotes <code>void foo(java.lang.String[])</code> in compiled code</li>
+ *   <li><code>"(QString;)QObject;"</code> denotes <code>Object foo(String)</code> in source code</li>
+ * </ul>
+ * </p>
+ * <p>
+ * The syntax for a formal type parameter signature is:
+ * <pre>
+ * FormalTypeParameterSignature ::=
+ *     TypeVariableName + OptionalClassBound + InterfaceBound*
+ * TypeVariableName ::= Identifier
+ * OptionalClassBound ::=
+ *     ":"
+ *   | ":" + TypeSignature
+ * InterfaceBound ::= 
+ *     ":" + TypeSignature
+ * </pre>
+ * <p>
+ * Examples:
+ * <ul>
+ *   <li><code>"X:"</code> denotes <code>X</code></li>
+ *   <li><code>"X:QReader;"</code> denotes <code>X extends Reader</code> in source code</li>
+ *   <li><code>"X:QReader;:QSerializable;"</code> denotes <code>X extends Reader & Serializable</code> in source code</li>
+ * </ul>
+ * </p>
+ * <p>
+ * This class provides static methods and constants only; it is not intended to be
+ * instantiated or subclassed by clients.
+ * </p>
+ */
+public final class Signature {
+
+       /**
+        * Character constant indicating the primitive type boolean in a signature.
+        * Value is <code>'Z'</code>.
+        */
+       public static final char C_BOOLEAN              = 'Z';
+
+       /**
+        * Character constant indicating the primitive type byte in a signature.
+        * Value is <code>'B'</code>.
+        */
+       public static final char C_BYTE                 = 'B';
+
+       /**
+        * Character constant indicating the primitive type char in a signature.
+        * Value is <code>'C'</code>.
+        */
+       public static final char C_CHAR                 = 'C';
+
+       /**
+        * Character constant indicating the primitive type double in a signature.
+        * Value is <code>'D'</code>.
+        */
+       public static final char C_DOUBLE               = 'D';
+
+       /**
+        * Character constant indicating the primitive type float in a signature.
+        * Value is <code>'F'</code>.
+        */
+       public static final char C_FLOAT                = 'F';
+
+       /**
+        * Character constant indicating the primitive type int in a signature.
+        * Value is <code>'I'</code>.
+        */
+       public static final char C_INT                  = 'I';
+       
+       /**
+        * Character constant indicating the semicolon in a signature.
+        * Value is <code>';'</code>.
+        */
+       public static final char C_SEMICOLON                    = ';';
+
+       /**
+        * Character constant indicating the colon in a signature.
+        * Value is <code>':'</code>.
+        * @since 3.0
+        */
+       public static final char C_COLON                        = ':';
+
+       /**
+        * Character constant indicating the primitive type long in a signature.
+        * Value is <code>'J'</code>.
+        */
+       public static final char C_LONG                 = 'J';
+       
+       /**
+        * Character constant indicating the primitive type short in a signature.
+        * Value is <code>'S'</code>.
+        */
+       public static final char C_SHORT                = 'S';
+       
+       /**
+        * Character constant indicating result type void in a signature.
+        * Value is <code>'V'</code>.
+        */
+       public static final char C_VOID                 = 'V';
+       
+       /**
+        * Character constant indicating the start of a resolved type variable in a 
+        * signature. Value is <code>'T'</code>.
+        * @since 3.0
+        */
+       public static final char C_TYPE_VARIABLE        = 'T';
+       
+       /**
+        * 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>.
+        */
+       public static final char C_DOT                  = '.';
+       
+       /** 
+        * Character constant indicating the dollar in a signature.
+        * Value is <code>'$'</code>.
+        */
+       public static final char C_DOLLAR                       = '$';
+
+       /** 
+        * Character constant indicating an array type in a signature.
+        * Value is <code>'['</code>.
+        */
+       public static final char C_ARRAY                = '[';
+
+       /** 
+        * Character constant indicating the start of a resolved, named type in a 
+        * signature. Value is <code>'L'</code>.
+        */
+       public static final char C_RESOLVED             = 'L';
+
+       /** 
+        * Character constant indicating the start of an unresolved, named type in a
+        * signature. Value is <code>'Q'</code>.
+        */
+       public static final char C_UNRESOLVED   = 'Q';
+
+       /**
+        * Character constant indicating the end of a named type in a signature. 
+        * Value is <code>';'</code>.
+        */
+       public static final char C_NAME_END             = ';';
+
+       /**
+        * Character constant indicating the start of a parameter type list in a
+        * signature. Value is <code>'('</code>.
+        */
+       public static final char C_PARAM_START  = '(';
+
+       /**
+        * Character constant indicating the end of a parameter type list in a 
+        * signature. Value is <code>')'</code>.
+        */
+       public static final char C_PARAM_END    = ')';
+
+       /**
+        * Character constant indicating the start of a formal type parameter
+        * (or type argument) list in a signature. Value is <code>'&lt;'</code>.
+        * @since 3.0
+        */
+       public static final char C_GENERIC_START        = '<';
+
+       /**
+        * Character constant indicating the end of a generic type list in a 
+        * signature. Value is <code>'%gt;'</code>.
+        * @since 3.0
+        */
+       public static final char C_GENERIC_END  = '>';
+
+       /**
+        * String constant for the signature of the primitive type boolean.
+        * Value is <code>"Z"</code>.
+        */
+       public static final String SIG_BOOLEAN          = "Z"; //$NON-NLS-1$
+
+       /**
+        * String constant for the signature of the primitive type byte. 
+        * Value is <code>"B"</code>.
+        */
+       public static final String SIG_BYTE             = "B"; //$NON-NLS-1$
+
+       /**
+        * String constant for the signature of the primitive type char.
+        * Value is <code>"C"</code>.
+        */
+       public static final String SIG_CHAR             = "C"; //$NON-NLS-1$
+
+       /**
+        * String constant for the signature of the primitive type double.
+        * Value is <code>"D"</code>.
+        */
+       public static final String SIG_DOUBLE           = "D"; //$NON-NLS-1$
+
+       /**
+        * String constant for the signature of the primitive type float.
+        * Value is <code>"F"</code>.
+        */
+       public static final String SIG_FLOAT            = "F"; //$NON-NLS-1$
+
+       /**
+        * String constant for the signature of the primitive type int.
+        * Value is <code>"I"</code>.
+        */
+       public static final String SIG_INT                      = "I"; //$NON-NLS-1$
+
+       /**
+        * String constant for the signature of the primitive type long.
+        * Value is <code>"J"</code>.
+        */
+       public static final String SIG_LONG                     = "J"; //$NON-NLS-1$
+
+       /**
+        * String constant for the signature of the primitive type short.
+        * Value is <code>"S"</code>.
+        */
+       public static final String SIG_SHORT            = "S"; //$NON-NLS-1$
+
+       /** String constant for the signature of result type void.
+        * Value is <code>"V"</code>.
+        */
+       public static final String SIG_VOID                     = "V"; //$NON-NLS-1$
+       
+
+       /**
+        * Kind constant for a class type signature.
+        * @see #getTypeSignatureKind(String)
+        * @since 3.0
+        */
+       public static int CLASS_TYPE_SIGNATURE = 1;
+
+       /**
+        * Kind constant for a base (primitive or void) type signature.
+        * @see #getTypeSignatureKind(String)
+        * @since 3.0
+        */
+       public static int BASE_TYPE_SIGNATURE = 2;
+
+       /**
+        * Kind constant for a type variable signature.
+        * @see #getTypeSignatureKind(String)
+        * @since 3.0
+        */
+       public static int TYPE_VARIABLE_SIGNATURE = 3;
+
+       /**
+        * Kind constant for an array type signature.
+        * @see #getTypeSignatureKind(String)
+        * @since 3.0
+        */
+       public static int ARRAY_TYPE_SIGNATURE = 4;
+
+       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);
+               
+private Signature() {
+       // Not instantiable
+}
+
+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;
+}
+
+/**
+ * Creates a new type signature with the given amount of array nesting added 
+ * to the given type signature.
+ *
+ * @param typeSignature the type signature
+ * @param arrayCount the desired number of levels of array nesting
+ * @return the encoded array type signature
+ * 
+ * @since 2.0
+ */
+public static char[] createArraySignature(char[] typeSignature, int arrayCount) {
+       if (arrayCount == 0) return typeSignature;
+       int sigLength = typeSignature.length;
+       char[] result = new char[arrayCount + sigLength];
+       for (int i = 0; i < arrayCount; i++) {
+               result[i] = C_ARRAY;
+       }
+       System.arraycopy(typeSignature, 0, result, arrayCount, sigLength);
+       return result;
+}
+/**
+ * Creates a new type signature with the given amount of array nesting added 
+ * to the given type signature.
+ *
+ * @param typeSignature the type signature
+ * @param arrayCount the desired number of levels of array nesting
+ * @return the encoded array type signature
+ */
+public static String createArraySignature(String typeSignature, int arrayCount) {
+       return new String(createArraySignature(typeSignature.toCharArray(), arrayCount));
+}
+
+/**
+ * Creates a method signature from the given parameter and return type 
+ * signatures. The encoded method signature is dot-based.
+ *
+ * @param parameterTypes the list of parameter type signatures
+ * @param returnType the return type signature
+ * @return the encoded method signature
+ * 
+ * @since 2.0
+ */
+public static char[] createMethodSignature(char[][] parameterTypes, char[] returnType) {
+       int parameterTypesLength = parameterTypes.length;
+       int parameterLength = 0;
+       for (int i = 0; i < parameterTypesLength; i++) {
+               parameterLength += parameterTypes[i].length;
+               
+       }
+       int returnTypeLength = returnType.length;
+       char[] result = new char[1 + parameterLength + 1 + returnTypeLength];
+       result[0] = C_PARAM_START;
+       int index = 1;
+       for (int i = 0; i < parameterTypesLength; i++) {
+               char[] parameterType = parameterTypes[i];
+               int length = parameterType.length;
+               System.arraycopy(parameterType, 0, result, index, length);
+               index += length;
+       }
+       result[index] = C_PARAM_END;
+       System.arraycopy(returnType, 0, result, index+1, returnTypeLength);
+       return result;
+}
+
+/**
+ * Creates a method signature from the given parameter and return type 
+ * signatures. The encoded method signature is dot-based. This method
+ * is equivalent to
+ * <code>createMethodSignature(parameterTypes, returnType)</code>.
+ *
+ * @param parameterTypes the list of parameter type signatures
+ * @param returnType the return type signature
+ * @return the encoded method signature
+ * @see Signature#createMethodSignature(char[][], char[])
+ */
+public static String createMethodSignature(String[] parameterTypes, String returnType) {
+       int parameterTypesLenth = parameterTypes.length;
+       char[][] parameters = new char[parameterTypesLenth][];
+       for (int i = 0; i < parameterTypesLenth; i++) {
+               parameters[i] = parameterTypes[i].toCharArray();
+       }
+       return new String(createMethodSignature(parameters, returnType.toCharArray()));
+}
+
+/**
+ * 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, 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 
+ * type name is qualified, then it is expected to be dot-based.
+ *
+ * @param typeName the possibly qualified type name
+ * @param isResolved <code>true</code> if the type name is to be considered
+ *   resolved (for example, a type name from a binary class file), and 
+ *   <code>false</code> if the type name is to be considered unresolved
+ *   (for example, a type name found in source code)
+ * @return the encoded type signature
+ * @see #createTypeSignature(java.lang.String,boolean)
+ */
+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 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.
+ * If the type name is qualified, then it is expected to be dot-based.
+ *
+ * @param typeName the possibly qualified type name
+ * @param isResolved <code>true</code> if the type name is to be considered
+ *   resolved (for example, a type name from a binary class file), and 
+ *   <code>false</code> if the type name is to be considered unresolved
+ *   (for example, a type name found in source code)
+ * @return the encoded type signature
+ * @see #createTypeSignature(java.lang.String,boolean)
+ * 
+ * @since 2.0
+ */
+public static char[] createCharArrayTypeSignature(char[] typeName, boolean isResolved) {
+       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;
+}
+
+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' :
+                   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':
+                   checkPos = checkName(CHAR, typeName, pos, length);
+                   if (checkPos > 0) {
+                       pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+                           buffer.append(C_CHAR);
+                           return pos;
+                       } 
+                   break;
+               case 'd':
+                   checkPos = checkName(DOUBLE, typeName, pos, length);
+                   if (checkPos > 0) {
+                       pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+                           buffer.append(C_DOUBLE);
+                           return pos;
+                       } 
+                   break;
+               case 'f':
+                   checkPos = checkName(FLOAT, typeName, pos, length);
+                   if (checkPos > 0) {
+                       pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+                           buffer.append(C_FLOAT);
+                           return pos;
+                       } 
+                   break;
+               case 'i':
+                   checkPos = checkName(INT, typeName, pos, length);
+                   if (checkPos > 0) {
+                       pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+                           buffer.append(C_INT);
+                           return pos;
+                       } 
+                   break;
+               case 'l':
+                   checkPos = checkName(LONG, typeName, pos, length);
+                   if (checkPos > 0) {
+                       pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+                           buffer.append(C_LONG);
+                           return pos;
+                       } 
+                   break;
+               case 's':
+                   checkPos = checkName(SHORT, typeName, pos, length);
+                   if (checkPos > 0) {
+                       pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+                           buffer.append(C_SHORT);
+                           return pos;
+                       } 
+                   break;
+               case 'v':
+                   checkPos = checkName(VOID, typeName, pos, length);
+                   if (checkPos > 0) {
+                       pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+                           buffer.append(C_VOID);
+                           return pos;
+                       }
+                   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;
+                       }
+                       checkPos = checkName(SUPER, typeName, pos, length);
+                       if (checkPos > 0) {
+                               buffer.append(C_SUPER);
+                               pos = encodeTypeSignature(typeName, checkPos, isResolved, length, buffer);
+                               return pos;
+                       }
+                       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;
+       }
+       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;
+               }
+       }
+       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
+ * types or array types. However, parameterized types are not supported.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * createTypeSignature("int", hucairz) -> "I"
+ * createTypeSignature("java.lang.String", true) -> "Ljava.lang.String;"
+ * createTypeSignature("String", false) -> "QString;"
+ * createTypeSignature("java.lang.String", false) -> "Qjava.lang.String;"
+ * createTypeSignature("int []", false) -> "[I"
+ * </code>
+ * </pre>
+ * </p>
+ *
+ * @param typeName the possibly qualified type name
+ * @param isResolved <code>true</code> if the type name is to be considered
+ *   resolved (for example, a type name from a binary class file), and 
+ *   <code>false</code> if the type name is to be considered unresolved
+ *   (for example, a type name found in source code)
+ * @return the encoded type signature
+ */
+public static String createTypeSignature(String typeName, boolean isResolved) {
+       return createTypeSignature(typeName == null ? null : typeName.toCharArray(), isResolved);
+}
+
+/**
+ * Returns the array count (array nesting depth) of the given type signature.
+ *
+ * @param typeSignature the type signature
+ * @return the array nesting depth, or 0 if not an array
+ * @exception IllegalArgumentException if the signature is not syntactically
+ *   correct
+ * 
+ * @since 2.0
+ */
+public static int getArrayCount(char[] typeSignature) throws IllegalArgumentException {        
+       try {
+               int count = 0;
+               while (typeSignature[count] == C_ARRAY) {
+                       ++count;
+               }
+               return count;
+       } catch (ArrayIndexOutOfBoundsException e) { // signature is syntactically incorrect if last character is C_ARRAY
+               throw new IllegalArgumentException();
+       }
+}
+/**
+ * Returns the array count (array nesting depth) of the given type signature.
+ *
+ * @param typeSignature the type signature
+ * @return the array nesting depth, or 0 if not an array
+ * @exception IllegalArgumentException if the signature is not syntactically
+ *   correct
+ */
+public static int getArrayCount(String typeSignature) throws IllegalArgumentException {
+       return getArrayCount(typeSignature.toCharArray());
+}
+/**
+ * Returns the type signature without any array nesting.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * getElementType({'[', '[', 'I'}) --> {'I'}.
+ * </code>
+ * </pre>
+ * </p>
+ * 
+ * @param typeSignature the type signature
+ * @return the type signature without arrays
+ * @exception IllegalArgumentException if the signature is not syntactically
+ *   correct
+ * 
+ * @since 2.0
+ */
+public static char[] getElementType(char[] typeSignature) throws IllegalArgumentException {
+       int count = getArrayCount(typeSignature);
+       if (count == 0) return typeSignature;
+       int length = typeSignature.length;
+       char[] result = new char[length-count];
+       System.arraycopy(typeSignature, count, result, 0, length-count);
+       return result;
+}
+/**
+ * Returns the type signature without any array nesting.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * getElementType("[[I") --> "I".
+ * </code>
+ * </pre>
+ * </p>
+ * 
+ * @param typeSignature the type signature
+ * @return the type signature without arrays
+ * @exception IllegalArgumentException if the signature is not syntactically
+ *   correct
+ */
+public static String getElementType(String typeSignature) throws IllegalArgumentException {
+       return new String(getElementType(typeSignature.toCharArray()));
+}
+/**
+ * Returns the number of parameter types in the given method signature.
+ *
+ * @param methodSignature the method signature
+ * @return the number of parameters
+ * @exception IllegalArgumentException if the signature is not syntactically
+ *   correct
+ * @since 2.0
+ */
+public static int getParameterCount(char[] methodSignature) throws IllegalArgumentException {
+       try {
+               int count = 0;
+               int i = CharOperation.indexOf(C_PARAM_START, methodSignature);
+               if (i < 0) {
+                       throw new IllegalArgumentException();
+               } else {
+                       i++;
+               }
+               for (;;) {
+                       if (methodSignature[i] == C_PARAM_END) {
+                               return count;
+                       }
+                       int e= scanTypeSignature(methodSignature, i);
+                       if (e < 0) {
+                               throw new IllegalArgumentException();
+                       } else {
+                               i = e + 1;
+                       }
+                       count++;
+               }
+       } catch (ArrayIndexOutOfBoundsException e) {
+               throw new IllegalArgumentException();
+       }
+}
+
+/**
+ * Returns the kind of type signature encoded by the given string.
+ * 
+ * @param typeSignature the type signature string
+ * @return the kind of type signature; one of the kind constants:
+ * {@link #ARRAY_TYPE_SIGNATURE}, {@link #CLASS_TYPE_SIGNATURE},
+ * {@link #BASE_TYPE_SIGNATURE}, or {@link #TYPE_VARIABLE_SIGNATURE}
+ * @exception IllegalArgumentException if this is not a type signature
+ * @since 3.0
+ */
+public static int getTypeSignatureKind(char[] typeSignature) {
+       // need a minimum 1 char
+       if (typeSignature.length < 1) {
+               throw new IllegalArgumentException();
+       }
+       char c = typeSignature[0];
+       switch (c) {
+               case C_ARRAY :
+                       return ARRAY_TYPE_SIGNATURE;
+               case C_RESOLVED :
+               case C_UNRESOLVED :
+                       return CLASS_TYPE_SIGNATURE;
+               case C_TYPE_VARIABLE :
+                       return TYPE_VARIABLE_SIGNATURE;
+               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 :
+                       return BASE_TYPE_SIGNATURE;
+               default :
+                       throw new IllegalArgumentException();
+       }
+}
+
+/**
+ * Returns the kind of type signature encoded by the given string.
+ * 
+ * @param typeSignature the type signature string
+ * @return the kind of type signature; one of the kind constants:
+ * {@link #ARRAY_TYPE_SIGNATURE}, {@link #CLASS_TYPE_SIGNATURE},
+ * {@link #BASE_TYPE_SIGNATURE}, or {@link #TYPE_VARIABLE_SIGNATURE}
+ * @exception IllegalArgumentException if this is not a type signature
+ * @since 3.0
+ */
+public static int getTypeSignatureKind(String typeSignature) {
+       // need a minimum 1 char
+       if (typeSignature.length() < 1) {
+               throw new IllegalArgumentException();
+       }
+       char c = typeSignature.charAt(0);
+       switch (c) {
+               case C_ARRAY :
+                       return ARRAY_TYPE_SIGNATURE;
+               case C_RESOLVED :
+               case C_UNRESOLVED :
+                       return CLASS_TYPE_SIGNATURE;
+               case C_TYPE_VARIABLE :
+                       return TYPE_VARIABLE_SIGNATURE;
+               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 :
+                       return BASE_TYPE_SIGNATURE;
+               default :
+                       throw new IllegalArgumentException();
+       }
+}
+
+/**
+ * Scans the given string for a type signature starting at the given index
+ * and returns the index of the last character.
+ * <pre>
+ * TypeSignature:
+ *  |  BaseTypeSignature
+ *  |  ArrayTypeSignature
+ *  |  ClassTypeSignature
+ *  |  TypeVariableSignature
+ * </pre>
+ * 
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a type signature
+ * @see #appendTypeSignature(char[], int, boolean, StringBuffer)
+ */
+private static int scanTypeSignature(char[] string, int start) {
+       // need a minimum 1 char
+       if (start >= string.length) {
+               throw new IllegalArgumentException();
+       }
+       char c = string[start];
+       switch (c) {
+               case C_ARRAY :
+                       return scanArrayTypeSignature(string, start);
+               case C_RESOLVED :
+               case C_UNRESOLVED :
+                       return scanClassTypeSignature(string, start);
+               case C_TYPE_VARIABLE :
+                       return scanTypeVariableSignature(string, start);
+               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 :
+                       return scanBaseTypeSignature(string, start);
+               default :
+                       throw new IllegalArgumentException();
+       }
+}
+
+/**
+ * Scans the given string for a base type signature starting at the given index
+ * and returns the index of the last character.
+ * <pre>
+ * BaseTypeSignature:
+ *     <b>B</b> | <b>C</b> | <b>D</b> | <b>F</b> | <b>I</b>
+ *   | <b>J</b> | <b>S</b> | <b>V</b> | <b>Z</b>
+ * </pre>
+ * Note that although the base type "V" is only allowed in method return types,
+ * there is no syntactic ambiguity. This method will accept them anywhere
+ * without complaint.
+ * 
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a base type signature
+ */
+private static int scanBaseTypeSignature(char[] string, int start) {
+       // need a minimum 1 char
+       if (start >= string.length) {
+               throw new IllegalArgumentException();
+       }
+       char c = string[start];
+       if ("BCDFIJSVZ".indexOf(c) >= 0) { //$NON-NLS-1$
+               return start;
+       } else {
+               throw new IllegalArgumentException();
+       }
+}
+
+/**
+ * Scans the given string for an array type signature starting at the given
+ * index and returns the index of the last character.
+ * <pre>
+ * ArrayTypeSignature:
+ *     <b>[</b> TypeSignature
+ * </pre>
+ * 
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not an array type signature
+ * @see #appendArrayTypeSignature(char[], int, boolean, StringBuffer)
+ */
+private static int scanArrayTypeSignature(char[] string, int start) {
+       // need a minimum 2 char
+       if (start >= string.length - 1) {
+               throw new IllegalArgumentException();
+       }
+       char c = string[start];
+       if (c != C_ARRAY) { //$NON-NLS-1$
+               throw new IllegalArgumentException();
+       }
+       return scanTypeSignature(string, start + 1);
+}
+
+/**
+ * Scans the given string for a type variable signature starting at the given
+ * index and returns the index of the last character.
+ * <pre>
+ * TypeVariableSignature:
+ *     <b>T</b> Identifier <b>;</b>
+ * </pre>
+ * 
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a type variable signature
+ */
+private static int scanTypeVariableSignature(char[] string, int start) {
+       // need a minimum 3 chars "Tx;"
+       if (start >= string.length - 2) { 
+               throw new IllegalArgumentException();
+       }
+       // must start in "T"
+       char c = string[start];
+       if (c != C_TYPE_VARIABLE) {
+               throw new IllegalArgumentException();
+       }
+       int id = scanIdentifier(string, start + 1);
+       c = string[id + 1];
+       if (c == C_SEMICOLON) {
+               return id + 1;
+       } else {
+               throw new IllegalArgumentException();
+       }
+}
+
+/**
+ * Scans the given string for an identifier starting at the given
+ * index and returns the index of the last character. 
+ * Stop characters are: ";", ":", "&lt;", "&gt;", "/", ".".
+ * 
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not an identifier
+ */
+private static int scanIdentifier(char[] string, int start) {
+       // need a minimum 1 char
+       if (start >= string.length) { 
+               throw new IllegalArgumentException();
+       }
+       int p = start;
+       while (true) {
+               char c = string[p];
+               if (c == '<' || c == '>' || c == ':' || c == ';' || c == '.' || c == '/') {
+                       return p - 1;
+               }
+               p++;
+               if (p == string.length) {
+                       return p - 1;
+               }
+       }
+}
+
+/**
+ * Scans the given string for a class type signature starting at the given
+ * index and returns the index of the last character.
+ * <pre>
+ * ClassTypeSignature:
+ *     { <b>L</b> | <b>Q</b> } Identifier
+ *           { { <b>/</b> | <b>.</b> Identifier [ <b>&lt;</b> TypeArgumentSignature* <b>&gt;</b> ] }
+ *           <b>;</b>
+ * </pre>
+ * Note that although all "/"-identifiers most come before "."-identifiers,
+ * there is no syntactic ambiguity. This method will accept them without
+ * complaint.
+ * 
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a class type signature
+ * @see #appendClassTypeSignature(char[], int, boolean, StringBuffer)
+ */
+private static int scanClassTypeSignature(char[] string, int start) {
+       // need a minimum 3 chars "Lx;"
+       if (start >= string.length - 2) { 
+               throw new IllegalArgumentException();
+       }
+       // must start in "L" or "Q"
+       char c = string[start];
+       if (c != C_RESOLVED && c != C_UNRESOLVED) {
+               return -1;
+       }
+       int p = start + 1;
+       while (true) {
+               if (p >= string.length) {
+                       throw new IllegalArgumentException();
+               }
+               c = string[p];
+               if (c == C_SEMICOLON) {
+                       // all done
+                       return p;
+               } else if (c == C_GENERIC_START) {
+                       int e = scanTypeArgumentSignatures(string, p);
+                       p = e;
+               } else if (c == C_DOT || c == '/') {
+                       int id = scanIdentifier(string, p + 1);
+                       p = id;
+               }
+               p++;
+       }
+}
+
+/**
+ * Scans the given string for a list of type argument signatures starting at
+ * the given index and returns the index of the last character.
+ * <pre>
+ * TypeArgumentSignatures:
+ *     <b>&lt;</b> TypeArgumentSignature* <b>&gt;</b>
+ * </pre>
+ * Note that although there is supposed to be at least one type argument, there
+ * is no syntactic ambiguity if there are none. This method will accept zero
+ * type argument signatures without complaint.
+ * 
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a list of type arguments
+ * signatures
+ * @see #appendTypeArgumentSignatures(char[], int, boolean, StringBuffer)
+ */
+private static int scanTypeArgumentSignatures(char[] string, int start) {
+       // need a minimum 2 char "<>"
+       if (start >= string.length - 1) {
+               throw new IllegalArgumentException();
+       }
+       char c = string[start];
+       if (c != C_GENERIC_START) {
+               throw new IllegalArgumentException();
+       }
+       int p = start + 1;
+       while (true) {
+               if (p >= string.length) {
+                       throw new IllegalArgumentException();
+               }
+               c = string[p];
+               if (c == C_GENERIC_END) {
+                       return p;
+               }
+               int e = scanTypeArgumentSignature(string, p);
+               p = e + 1;
+       }
+}
+
+/**
+ * Scans the given string for a type argument signature starting at the given
+ * index and returns the index of the last character.
+ * <pre>
+ * TypeArgumentSignature:
+ *     <b>&#42;</b>
+ *  |  <b>+</b> TypeSignature
+ *  |  <b>-</b> TypeSignature
+ *  |  TypeSignature
+ * </pre>
+ * Note that although base types are not allowed in type arguments, there is
+ * no syntactic ambiguity. This method will accept them without complaint.
+ * 
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a type argument signature
+ * @see #appendTypeArgumentSignature(char[], int, boolean, StringBuffer)
+ */
+private static int scanTypeArgumentSignature(char[] string, int start) {
+       // need a minimum 1 char
+       if (start >= string.length) {
+               throw new IllegalArgumentException();
+       }
+       char c = string[start];
+       if (c == C_STAR) {
+               return start;
+       }
+       if (c == '+' || c == '-') {
+               return scanTypeSignature(string, start + 1);
+       } else {
+               return scanTypeSignature(string, start);
+       }
+}
+
+/**
+ * Returns the number of parameter types in the given method signature.
+ *
+ * @param methodSignature the method signature
+ * @return the number of parameters
+ * @exception IllegalArgumentException if the signature is not syntactically
+ *   correct
+ */
+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.
+ *
+ * @param methodSignature the method signature
+ * @return the list of parameter type signatures
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ * 
+ * @since 2.0
+ */
+public static char[][] getParameterTypes(char[] methodSignature) throws IllegalArgumentException {
+       try {
+               int count = getParameterCount(methodSignature);
+               char[][] result = new char[count][];
+               if (count == 0) {
+                       return result;
+               }
+               int i = CharOperation.indexOf(C_PARAM_START, methodSignature);
+               if (i < 0) {
+                       throw new IllegalArgumentException();
+               } else {
+                       i++;
+               }
+               int t = 0;
+               for (;;) {
+                       if (methodSignature[i] == C_PARAM_END) {
+                               return result;
+                       }
+                       int e = scanTypeSignature(methodSignature, i);
+                       if (e < 0) {
+                               throw new IllegalArgumentException();
+                       }
+                       result[t] = CharOperation.subarray(methodSignature, i, e + 1);
+                       t++;
+                       i = e + 1;
+               }
+       } catch (ArrayIndexOutOfBoundsException e) {
+               throw new IllegalArgumentException();
+       }
+}
+
+/**
+ * Extracts the parameter type signatures from the given method signature. 
+ * The method signature is expected to be dot-based.
+ *
+ * @param methodSignature the method signature
+ * @return the list of parameter type signatures
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ */
+public static String[] getParameterTypes(String methodSignature) throws IllegalArgumentException {
+       char[][] parameterTypes = getParameterTypes(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 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.
+ *
+ * @param formalTypeParameterSignature the formal type parameter signature
+ * @return the name of the type variable
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ * @since 3.0
+ */
+public static String getTypeVariable(String formalTypeParameterSignature) throws IllegalArgumentException {
+       return new String(getTypeVariable(formalTypeParameterSignature.toCharArray()));
+}
+
+/**
+ * Extracts the type variable name from the given formal type parameter
+ * signature. The signature is expected to be dot-based.
+ *
+ * @param formalTypeParameterSignature the formal type parameter signature
+ * @return the name of the type variable
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ * @since 3.0
+ */
+public static char[] getTypeVariable(char[] formalTypeParameterSignature) throws IllegalArgumentException {
+       int p = CharOperation.indexOf(C_COLON, formalTypeParameterSignature);
+       if (p < 0) {
+               // no ":" means can't be a formal type parameter signature
+               throw new IllegalArgumentException();
+       }
+       return CharOperation.subarray(formalTypeParameterSignature, 0, p);
+}
+
+/**
+ * Extracts the class and interface bounds from the given formal type
+ * parameter signature. The class bound, if present, is listed before
+ * the interface bounds. The signature is expected to be dot-based.
+ *
+ * @param formalTypeParameterSignature the formal type parameter signature
+ * @return the (possibly empty) list of type signatures for the bounds
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ * @since 3.0
+ */
+public static char[][] getTypeParameterBounds(char[] formalTypeParameterSignature) throws IllegalArgumentException {
+       int p1 = CharOperation.indexOf(C_COLON, formalTypeParameterSignature);
+       if (p1 < 0) {
+               // no ":" means can't be a formal type parameter signature
+               throw new IllegalArgumentException();
+       }
+       if (p1 == formalTypeParameterSignature.length - 1) {
+               // no class or interface bounds
+               return CharOperation.NO_CHAR_CHAR;
+       }
+       int p2 = CharOperation.indexOf(C_COLON, formalTypeParameterSignature, p1 + 1);
+       char[] classBound;
+       if (p2 < 0) {
+               // no interface bounds
+               classBound = CharOperation.subarray(formalTypeParameterSignature, p1 + 1, formalTypeParameterSignature.length);
+               return new char[][] {classBound};
+       }
+       if (p2 == p1 + 1) {
+               // no class bound, but 1 or more interface bounds
+               classBound = null;
+       } else {
+               classBound = CharOperation.subarray(formalTypeParameterSignature, p1 + 1, p2);
+       }
+       char[][] interfaceBounds = CharOperation.splitOn(C_COLON, formalTypeParameterSignature, p2 + 1, formalTypeParameterSignature.length);
+       if (classBound == null) {
+               return interfaceBounds;
+       }
+       int resultLength = interfaceBounds.length + 1;
+       char[][] result = new char[resultLength][];
+       result[0] = classBound;
+       System.arraycopy(interfaceBounds, 0, result, 1, interfaceBounds.length);
+       return result;
+}
+
+/**
+ * Extracts the class and interface bounds from the given formal type
+ * parameter signature. The class bound, if present, is listed before
+ * the interface bounds. The signature is expected to be dot-based.
+ *
+ * @param formalTypeParameterSignature the formal type parameter signature
+ * @return the (possibly empty) list of type signatures for the bounds
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ * @since 3.0
+ */
+public static String[] getTypeParameterBounds(String formalTypeParameterSignature) throws IllegalArgumentException {
+       char[][] bounds = getTypeParameterBounds(formalTypeParameterSignature.toCharArray());
+       return CharOperation.toStrings(bounds);
+}
+
+/**
+ * Returns a char array containing all but the last segment of the given 
+ * dot-separated qualified name. Returns the empty char array if it is not qualified.
+ * <p>
+ * For example:
+ * <pre>
+ * <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>
+ *
+ * @param name the name
+ * @return the qualifier prefix, or the empty char array if the name contains no
+ *   dots
+ * @exception NullPointerException if name is null
+ * @since 2.0
+ */
+public static char[] getQualifier(char[] 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;
+       }
+       return CharOperation.subarray(name, 0, lastDot);
+}
+/**
+ * Returns a string containing all but the last segment of the given 
+ * dot-separated qualified name. Returns the empty string if it is not qualified.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * getQualifier("java.lang.Object") -> "java.lang"
+ * getQualifier("Outer.Inner") -> "Outer"
+ * getQualifier("java.util.List<java.lang.String>") -> "java.util"
+ * </code>
+ * </pre>
+ * </p>
+ *
+ * @param name the name
+ * @return the qualifier prefix, or the empty string if the name contains no
+ *   dots
+ * @exception NullPointerException if name is null
+ */
+public static String getQualifier(String name) {
+       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 
+ * expected to be dot-based.
+ *
+ * @param methodSignature the method signature
+ * @return the type signature of the return type
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ * 
+ * @since 2.0
+ */
+public static char[] getReturnType(char[] methodSignature) throws IllegalArgumentException {
+       // skip type parameters
+       int paren = CharOperation.lastIndexOf(C_PARAM_END, methodSignature);
+       if (paren == -1) {
+               throw new IllegalArgumentException();
+       }
+       // 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 
+ * expected to be dot-based.
+ *
+ * @param methodSignature the method signature
+ * @return the type signature of the return type
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ */
+public static String getReturnType(String methodSignature) throws IllegalArgumentException {
+       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>
+ * For example:
+ * <pre>
+ * <code>
+ * getSimpleName({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {'O', 'b', 'j', 'e', 'c', 't'}
+ * </code>
+ * </pre>
+ * </p>
+ *
+ * @param name the name
+ * @return the last segment of the qualified name
+ * @exception NullPointerException if name is null
+ * @since 2.0
+ */
+public static char[] getSimpleName(char[] 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;
+               }
+       }
+       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.
+ * Returns the given name if it is not qualified.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * getSimpleName("java.lang.Object") -> "Object"
+ * </code>
+ * <code>
+ * getSimpleName("java.util.Map<java.lang.String, java.lang.Object>") -> "Map<String,Object>"
+ * </code>
+ * </pre>
+ * </p>
+ *
+ * @param name the name
+ * @return the last segment of the qualified name
+ * @exception NullPointerException if name is null
+ */
+public static String getSimpleName(String 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;
+               }
+       }
+       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.
+ * Returns an array with only the given name if it is not qualified.
+ * Returns an empty array if the name is empty.
+ * <p>
+ * For example:
+ * <pre>
+ * <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({'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>
+ *
+ * @param name the name
+ * @return the list of simple names, possibly empty
+ * @exception NullPointerException if name is null
+ * @since 2.0
+ */
+public static char[][] getSimpleNames(char[] name) {
+       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;
+               }
+       }
+       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.
+ * Returns an array with only the given name if it is not qualified.
+ * Returns an empty array if the name is empty.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * 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>
+ *
+ * @param name the name
+ * @return the list of simple names, possibly empty
+ * @exception NullPointerException if name is null
+ */
+public static String[] getSimpleNames(String name) {
+       return CharOperation.toStrings(getSimpleNames(name.toCharArray()));
+}
+/**
+ * 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
+ * @return the char array representation of the method signature
+ * 
+ * @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();
+       }
+       
+       StringBuffer buffer = new StringBuffer(methodSignature.length + 10);
+       
+       // return type
+       if (includeReturnType) {
+               char[] rts = getReturnType(methodSignature);
+               appendTypeSignature(rts, 0 , fullyQualifyTypeNames, buffer);
+               buffer.append(' ');
+       }
+       
+       // selector
+       if (methodName != null) {
+               buffer.append(methodName);
+       }
+       
+       // parameters
+       buffer.append('(');
+       char[][] pts = getParameterTypes(methodSignature);
+       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]);
+               }
+               if (i != pts.length - 1) {
+                       buffer.append(',');
+                       buffer.append(' ');
+               }
+       }
+       buffer.append(')');
+       char[] result = new char[buffer.length()];
+       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.
+ * 
+ * <p>
+ * For example:
+ * <pre>
+ * <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>
+ * <p>
+ * Note: This method assumes that a type signature containing a <code>'$'</code>
+ * is an inner type signature. While this is correct in most cases, someone could 
+ * define a non-inner type name containing a <code>'$'</code>. Handling this 
+ * correctly in all cases would have required resolving the signature, which 
+ * generally not feasible.
+ * </p>
+ *
+ * @param signature the type signature
+ * @return the string representation of the type
+ * @exception IllegalArgumentException if the signature is not syntactically
+ *   correct
+ * 
+ * @since 2.0
+ */
+public static char[] toCharArray(char[] signature) throws IllegalArgumentException {
+               int sigLength = signature.length;
+               if (sigLength == 0 || signature[0] == C_PARAM_START || signature[0] == C_GENERIC_START) {
+                       return toCharArray(signature, CharOperation.NO_CHAR, null, true, true);
+               }
+               
+               StringBuffer buffer = new StringBuffer(signature.length + 10);
+               appendTypeSignature(signature, 0, true, buffer);
+               char[] result = new char[buffer.length()];
+               buffer.getChars(0, buffer.length(), result, 0);
+               return result;
+}
+
+/**
+ * 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
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a type signature
+ * @see #scanTypeSignature(char[], int)
+ */
+private static int appendTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer) {
+       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
+               }
+       } else {
+               switch (c) {
+                       case C_ARRAY :
+                               return appendArrayTypeSignature(string, start, fullyQualifyTypeNames, buffer);
+                       case C_RESOLVED :
+                       case C_UNRESOLVED :
+                               return appendClassTypeSignature(string, start, fullyQualifyTypeNames, buffer);
+                       case C_TYPE_VARIABLE :
+                               int e = scanTypeVariableSignature(string, start);
+                               buffer.append(CharOperation.subarray(string, start + 1, e));
+                               return e;
+                       case C_BOOLEAN :
+                               buffer.append(BOOLEAN);
+                               return start;
+                       case C_BYTE :
+                               buffer.append(BYTE);
+                               return start;
+                       case C_CHAR :
+                               buffer.append(CHAR);
+                               return start;
+                       case C_DOUBLE :
+                               buffer.append(DOUBLE);
+                               return start;
+                       case C_FLOAT :
+                               buffer.append(FLOAT);
+                               return start;
+                       case C_INT :
+                               buffer.append(INT);
+                               return start;
+                       case C_LONG :
+                               buffer.append(LONG);
+                               return start;
+                       case C_SHORT :
+                               buffer.append(SHORT);
+                               return start;
+                       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
+ * 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
+ * @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) {
+       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();
+       }
+       char c = string[start];
+       if (c != C_ARRAY) { //$NON-NLS-1$
+               throw new IllegalArgumentException();
+       }
+       int e = appendTypeSignature(string, start + 1, fullyQualifyTypeNames, buffer);
+       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
+ * 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
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a class type signature
+ * @see #scanClassTypeSignature(char[], int)
+ */
+private static int appendClassTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer) {
+       // need a minimum 3 chars "Lx;"
+       if (start >= string.length - 2) { 
+               throw new IllegalArgumentException();
+       }
+       // must start in "L" or "Q"
+       char c = string[start];
+       if (c != C_RESOLVED && c != C_UNRESOLVED) {
+               throw new IllegalArgumentException();
+       }
+       boolean resolved = (c == C_RESOLVED);
+       boolean removePackageQualifiers = !fullyQualifyTypeNames;
+       if (!resolved) {
+               // keep everything in an unresolved name
+               removePackageQualifiers = false;
+       }
+       int p = start + 1;
+       int checkpoint = buffer.length();
+       while (true) {
+               if (p >= string.length) {
+                       throw new IllegalArgumentException();
+               }
+               c = string[p];
+               switch(c) {
+                       case C_SEMICOLON :
+                               // all done
+                               return p;
+                       case C_GENERIC_START :
+                               int e = appendTypeArgumentSignatures(string, p, fullyQualifyTypeNames, buffer);
+                               // once we hit type arguments there are no more package prefixes
+                               removePackageQualifiers = false;
+                               p = e;
+                               break;
+                       case C_DOT :
+                               if (removePackageQualifiers) {
+                                       // erase package prefix
+                                       buffer.setLength(checkpoint);
+                               } else {
+                                       buffer.append('.');
+                               }
+                               break;
+                        case '/' :
+                               if (removePackageQualifiers) {
+                                       // erase package prefix
+                                       buffer.setLength(checkpoint);
+                               } else {
+                                       buffer.append('/');
+                               }
+                               break;
+                        case C_DOLLAR :
+                               if (resolved) {
+                                       // once we hit "$" there are no more package prefixes
+                                       removePackageQualifiers = false;
+                                       /**
+                                        * Convert '$' in resolved type signatures into '.'.
+                                        * NOTE: This assumes that the type signature is an inner type
+                                        * signature. This is true in most cases, but someone can define a
+                                        * non-inner type name containing a '$'.
+                                        */
+                                       buffer.append('.');
+                               }
+                               break;
+                        default :
+                               buffer.append(c);
+               }
+               p++;
+       }
+}
+
+/**
+ * Scans the given string for a list of type arguments 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
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a list of type argument
+ * signatures
+ * @see #scanTypeArgumentSignatures(char[], int)
+ */
+private static int appendTypeArgumentSignatures(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer) {
+       // need a minimum 2 char "<>"
+       if (start >= string.length - 1) {
+               throw new IllegalArgumentException();
+       }
+       char c = string[start];
+       if (c != C_GENERIC_START) {
+               throw new IllegalArgumentException();
+       }
+       buffer.append('<');
+       int p = start + 1;
+       int count = 0;
+       while (true) {
+               if (p >= string.length) {
+                       throw new IllegalArgumentException();
+               }
+               c = string[p];
+               if (c == C_GENERIC_END) {
+                       buffer.append('>');
+                       return p;
+               }
+               if (count != 0) {
+                       buffer.append(',');
+               }
+               int e = appendTypeArgumentSignature(string, p, fullyQualifyTypeNames, buffer);
+               count++;
+               p = e + 1;
+       }
+}
+
+/**
+ * Scans the given string for a type argument 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
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a type argument signature
+ * @see #scanTypeArgumentSignature(char[], int)
+ */
+private static int appendTypeArgumentSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer) {
+       // need a minimum 1 char
+       if (start >= string.length) {
+               throw new IllegalArgumentException();
+       }
+       char c = string[start];
+       switch(c) {
+               case C_STAR :
+                       buffer.append('?');
+                       return start;
+               case C_EXTENDS :
+                       buffer.append("? extends "); //$NON-NLS-1$
+                       return appendTypeSignature(string, start + 1, fullyQualifyTypeNames, buffer);
+               case C_SUPER :
+                       buffer.append("? super "); //$NON-NLS-1$
+                       return appendTypeSignature(string, start + 1, fullyQualifyTypeNames, buffer);
+               default :
+                       return appendTypeSignature(string, start, fullyQualifyTypeNames, buffer);
+       }
+}
+
+/**
+ * Converts the given array of qualified name segments to a qualified name.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * toQualifiedName({{'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'}
+ * toQualifiedName({{'O', 'b', 'j', 'e', 'c', 't'}}) -> {'O', 'b', 'j', 'e', 'c', 't'}
+ * toQualifiedName({{}}) -> {}
+ * </code>
+ * </pre>
+ * </p>
+ *
+ * @param segments the list of name segments, possibly empty
+ * @return the dot-separated qualified name, or the empty string
+ * 
+ * @since 2.0
+ */
+public static char[] toQualifiedName(char[][] segments) {
+       int length = segments.length;
+       if (length == 0) return CharOperation.NO_CHAR;
+       if (length == 1) return segments[0];
+       
+       int resultLength = 0;
+       for (int i = 0; i < length; i++) {
+               resultLength += segments[i].length+1;
+       }
+       resultLength--;
+       char[] result = new char[resultLength];
+       int index = 0;
+       for (int i = 0; i < length; i++) {
+               char[] segment = segments[i];
+               int segmentLength = segment.length;
+               System.arraycopy(segment, 0, result, index, segmentLength);
+               index += segmentLength;
+               if (i != length-1) {
+                       result[index++] = C_DOT;
+               }
+       }
+       return result;
+}
+/**
+ * Converts the given array of qualified name segments to a qualified name.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * toQualifiedName(new String[] {"java", "lang", "Object"}) -> "java.lang.Object"
+ * toQualifiedName(new String[] {"Object"}) -> "Object"
+ * toQualifiedName(new String[0]) -> ""
+ * </code>
+ * </pre>
+ * </p>
+ *
+ * @param segments the list of name segments, possibly empty
+ * @return the dot-separated qualified name, or the empty string
+ */
+public static String toQualifiedName(String[] segments) {
+       int length = segments.length;
+       char[][] charArrays = new char[length][];
+       for (int i = 0; i < length; i++) {
+               charArrays[i] = segments[i].toCharArray();
+       }
+       return new String(toQualifiedName(charArrays));
+}
+/**
+ * Converts the given type signature to a readable string. The signature is expected to
+ * be dot-based.
+ * 
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * toString("[Ljava.lang.String;") -> "java.lang.String[]"
+ * toString("I") -> "int"
+ * toString("+QObject;") -> "? extends Object"
+ * </code>
+ * </pre>
+ * </p>
+ * <p>
+ * Note: This method assumes that a type signature containing a <code>'$'</code>
+ * is an inner type signature. While this is correct in most cases, someone could 
+ * define a non-inner type name containing a <code>'$'</code>. Handling this 
+ * correctly in all cases would have required resolving the signature, which 
+ * generally not feasible.
+ * </p>
+ *
+ * @param signature the type signature
+ * @return the string representation of the type
+ * @exception IllegalArgumentException if the signature is not syntactically
+ *   correct
+ */
+public static String toString(String signature) throws IllegalArgumentException {
+       return new String(toCharArray(signature.toCharArray()));
+}
+/**
+ * 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
+ * @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) {
+       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;
+       } else {
+               int paramLength = parameterNames.length;
+               params = new char[paramLength][];
+               for (int i = 0; i < paramLength; i++) {
+                       params[i] = parameterNames[i].toCharArray();
+               }
+       }
+       return new String(toCharArray(methodSignature.toCharArray(), methodName == null ? null : methodName.toCharArray(), params, fullyQualifyTypeNames, includeReturnType, isVarArgs));
+}
+}
index 07d23e3..b21cdf4 100644 (file)
@@ -28,6 +28,12 @@ public final class CharOperation {
        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 @@ public final class CharOperation {
         * @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 @@ public final class CharOperation {
 
        /**
         * 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 @@ public final class CharOperation {
                                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 @@ public final class CharOperation {
                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 @@ public final class CharOperation {
         * @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]);
index 7be59f1..48c5422 100644 (file)
@@ -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 @@ public interface IProblem {
        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 @@ public interface IProblem {
        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 @@ public interface IProblem {
        /** @since 3.0 */
        int IndirectAccessToStaticMethod = Internal + MethodRelated + 119;
 
-           
        // constructors
        int UndefinedConstructor = ConstructorRelated + 130;
        int NotVisibleConstructor = ConstructorRelated + 131;
@@ -445,7 +426,7 @@ public interface IProblem {
        /** @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 @@ public interface IProblem {
        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 @@ public interface IProblem {
        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 @@ public interface IProblem {
        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 @@ public interface IProblem {
        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 @@ public interface IProblem {
        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 @@ public interface IProblem {
        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 @@ public interface IProblem {
        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 @@ public interface IProblem {
        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 @@ public interface IProblem {
        // 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 @@ public interface IProblem {
        /** @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,235 @@ public interface IProblem {
        /** @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;
+
+       /**
+        * 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
index 7055b43..508f522 100644 (file)
@@ -16,8 +16,8 @@ package org.eclipse.jdt.core.compiler;
  */
 public class InvalidInputException extends Exception {
 
-       private static final long serialVersionUID = 2909732853499731592L; // backward compatible
-
+       private static final long serialVersionUID = 2909732853499731592L; // backward compatible
+       
        /**
         * Creates a new exception with no detail message.
         */
index 9e1166d..1a105fb 100644 (file)
@@ -30,33 +30,11 @@ public abstract class ASTVisitor {
        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 abstract class ASTVisitor {
        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 abstract class ASTVisitor {
        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 abstract class ASTVisitor {
        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 abstract class ASTVisitor {
        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 abstract class ASTVisitor {
        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 abstract class ASTVisitor {
        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 abstract class ASTVisitor {
        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 @@ public abstract class ASTVisitor {
                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) {
-               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) {
+       public boolean visit(
+                       AnnotationMethodDeclaration annotationTypeDeclaration,
+                       ClassScope classScope) {
                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 abstract class ASTVisitor {
        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 abstract class ASTVisitor {
        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 abstract class ASTVisitor {
        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 abstract class ASTVisitor {
        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 abstract class ASTVisitor {
        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 @@ public abstract class ASTVisitor {
                        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 abstract class ASTVisitor {
        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 @@ public abstract class ASTVisitor {
                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
+       }
 }
index e575af5..dbed323 100644 (file)
@@ -20,6 +20,7 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.impl.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 @@ import org.eclipse.jdt.internal.compiler.util.Util;
  */
 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;
+       public static final int INITIAL_CONTENTS_SIZE = 400;
+       public static final int INITIAL_HEADER_SIZE = 1500;
+       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;
+       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 int contentsOffset;
-       public int constantPoolOffset;
-       public int methodCountOffset;
+       public ReferenceBinding[] innerClassesBindings;
        public int methodCount;
-       protected boolean creatingProblemType;
-       public static final int INITIAL_CONTENTS_SIZE = 400;
-       public static final int INITIAL_HEADER_SIZE = 1500;
+       public int methodCountOffset;
+       public int numberOfInnerClasses;
        public boolean ownSharedArrays = false; // flag set when header/contents are set to shared arrays
-       public static final int INNER_CLASSES_SIZE = 5;
-       public CodeStream codeStream;
-       protected int problemLine;      // used to create line number attributes for problem methods
+       // used to generate private access methods
+       public int produceDebugAttributes;
+       public SourceTypeBinding referenceBinding;
        public long targetJDK;
        
        /**
@@ -91,7 +348,7 @@ public class ClassFile
                ClassFile enclosingClassFile,
                boolean creatingProblemType) {
            
-               referenceBinding = aType;
+               this.referenceBinding = aType;
                initByteArrays();
 
                // generate the magic numbers inside the header
@@ -100,7 +357,8 @@ public class ClassFile
                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 @@ public class ClassFile
                // 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 @@ public class ClassFile
                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 @@ public class ClassFile
                        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 @@ public class ClassFile
                                // 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 @@ public class ClassFile
                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 @@ public class ClassFile
                }
        }
 
-       /**
-        * 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 @@ public class ClassFile
                        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 @@ public class ClassFile
                                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 @@ public class ClassFile
                                                        }
                                                } 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 @@ public class ClassFile
                                        }
                        }
                }
-               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 @@ public class ClassFile
                        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 @@ public class ClassFile
                        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 @@ public class ClassFile
         * - 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 @@ public class ClassFile
         * 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 @@ public class ClassFile
                }
                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 @@ public class ClassFile
                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 @@ public class ClassFile
                                .scope
                                .referenceCompilationUnit()
                                .compilationResult
-                               .lineSeparatorPositions);
+                               .lineSeparatorPositions,
+                       problemLine);
                contents[attributeOffset++] = (byte) (attributeNumber >> 8);
                contents[attributeOffset] = (byte) attributeNumber;
        }
@@ -612,7 +1031,7 @@ public class ClassFile
                // 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 @@ public class ClassFile
                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 @@ public class ClassFile
                                .scope
                                .referenceCompilationUnit()
                                .compilationResult
-                               .lineSeparatorPositions);
+                               .lineSeparatorPositions,
+                       problemLine);
                completeMethodInfo(methodAttributeOffset, attributeNumber);
        }
 
@@ -695,7 +1116,7 @@ public class ClassFile
                // 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 @@ public class ClassFile
                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 @@ public class ClassFile
                                .scope
                                .referenceCompilationUnit()
                                .compilationResult
-                               .lineSeparatorPositions);
+                               .lineSeparatorPositions,
+                       problemLine);
                completeMethodInfo(methodAttributeOffset, attributeNumber);
        }
 
@@ -761,206 +1184,77 @@ public class ClassFile
                int savedOffset) {
                // we need to move back the contentsOffset to the value at the beginning of the method
                contentsOffset = savedOffset;
-               methodCount--; // we need to remove the method that causes the problem
-               addProblemMethod(method, methodBinding, problems);
-       }
-
-       /**
-        * INTERNAL USE-ONLY
-        * Generate the byte for all the special method infos.
-        * They are:
-        * - synthetic access methods
-        * - default abstract methods
-        */
-       public void addSpecialMethods() {
-               // add all methods (default abstract methods and synthetic)
-
-               // default abstract methods
-               SourceTypeBinding currentBinding = referenceBinding;
-               MethodBinding[] defaultAbstractMethods =
-                       currentBinding.getDefaultAbstractMethods();
-               for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
-                       generateMethodInfoHeader(defaultAbstractMethods[i]);
-                       int methodAttributeOffset = contentsOffset;
-                       int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
-                       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 :
-                                               // generate a method info to emulate an reading access to
-                                               // a non-accessible field
-                                               addSyntheticFieldReadAccessMethod(syntheticAccessMethods[i]);
-                                               break;
-                                       case SyntheticAccessMethodBinding.FieldWriteAccess :
-                                               // generate a method info to emulate an writing access to
-                                               // a non-accessible field
-                                               addSyntheticFieldWriteAccessMethod(syntheticAccessMethods[i]);
-                                               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]);
-                                               break;
-                                       case SyntheticAccessMethodBinding.ConstructorAccess :
-                                               // generate a method info to emulate an access to a non-accessible constructor
-                                               addSyntheticConstructorAccessMethod(syntheticAccessMethods[i]);
-                               }
-                       }
-               }
-       }
-
-       /**
-        * 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);
+               methodCount--; // we need to remove the method that causes the problem
+               addProblemMethod(method, methodBinding, problems);
        }
 
        /**
-        * 
+        * INTERNAL USE-ONLY
+        * Generate the byte for all the special method infos.
+        * They are:
+        * - synthetic access methods
+        * - default abstract methods
         */
-       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
+       public void addSpecialMethods() {
+           
+               // add all methods (default abstract methods and synthetic)
 
-               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++;
+               // default abstract methods
+               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;
+                       int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
+                       completeMethodInfo(methodAttributeOffset, 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);
+               // add synthetic methods infos
+               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(syntheticMethod);
+                                               break;
+                                       case SyntheticMethodBinding.FieldWriteAccess :
+                                               // generate a method info to emulate an writing access to
+                                               // a non-accessible field
+                                               addSyntheticFieldWriteAccessMethod(syntheticMethod);
+                                               break;
+                                       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 SyntheticMethodBinding.ConstructorAccess :
+                                               // generate a method info to emulate an access to a non-accessible constructor
+                                               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;
+                               }
+                       }
                }
-               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 @@ public class ClassFile
                generateCodeAttributeHeader();
                codeStream.init(this);
                codeStream.generateSyntheticBodyForConstructorAccess(methodBinding);
-               completeCodeAttributeForSyntheticAccessMethod(
+               completeCodeAttributeForSyntheticMethod(
                        methodBinding,
                        codeAttributeOffset,
                        ((SourceTypeBinding) methodBinding.declaringClass)
@@ -992,12 +1286,88 @@ public class ClassFile
 
        /**
         * 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 @@ public class ClassFile
                generateCodeAttributeHeader();
                codeStream.init(this);
                codeStream.generateSyntheticBodyForFieldReadAccess(methodBinding);
-               completeCodeAttributeForSyntheticAccessMethod(
+               completeCodeAttributeForSyntheticMethod(
                        methodBinding,
                        codeAttributeOffset,
                        ((SourceTypeBinding) methodBinding.declaringClass)
@@ -1034,7 +1404,7 @@ public class ClassFile
         *
         * @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 @@ public class ClassFile
                generateCodeAttributeHeader();
                codeStream.init(this);
                codeStream.generateSyntheticBodyForFieldWriteAccess(methodBinding);
-               completeCodeAttributeForSyntheticAccessMethod(
+               completeCodeAttributeForSyntheticMethod(
                        methodBinding,
                        codeAttributeOffset,
                        ((SourceTypeBinding) methodBinding.declaringClass)
@@ -1066,12 +1436,11 @@ public class ClassFile
 
        /**
         * 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 @@ public class ClassFile
                generateCodeAttributeHeader();
                codeStream.init(this);
                codeStream.generateSyntheticBodyForMethodAccess(methodBinding);
-               completeCodeAttributeForSyntheticAccessMethod(
+               completeCodeAttributeForSyntheticMethod(
                        methodBinding,
                        codeAttributeOffset,
                        ((SourceTypeBinding) methodBinding.declaringClass)
@@ -1103,69 +1472,6 @@ public class ClassFile
 
        /**
         * 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 @@ public class ClassFile
                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 @@ public class ClassFile
                // 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 @@ public class ClassFile
                        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 @@ public class ClassFile
                        // 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 @@ public class ClassFile
                                                                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 @@ public class ClassFile
                                                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 @@ public class ClassFile
                        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 @@ public class ClassFile
                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 @@ public class ClassFile
                // 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 @@ public class ClassFile
                                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 @@ public class ClassFile
                                                        }
                                                        // 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 @@ public class ClassFile
                                                        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 @@ public class ClassFile
                                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 class ClassFile
         */
        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 class ClassFile
        }
 
        /**
+        * 
+        */
+       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 @@ public class ClassFile
                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 @@ public class ClassFile
                        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 @@ public class ClassFile
                                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 @@ public class ClassFile
                                                        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 @@ public class ClassFile
                        } 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 @@ public class ClassFile
                                                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 @@ public class ClassFile
                        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 @@ public class ClassFile
         * @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 @@ public class ClassFile
                        // 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 @@ public class ClassFile
                                                }
                                                // 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 @@ public class ClassFile
                                                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 @@ public class ClassFile
                        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,115 +2793,74 @@ public class ClassFile
 
        /**
         * INTERNAL USE-ONLY
-        * Request the creation of a ClassFile compatible representation of a problematic type
+        * This methods returns a char[] representing the file name of the receiver
         *
-        * @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
-        * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
+        * @return char[]
         */
-       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);
+       public char[] fileName() {
+               return constantPool.UTF8Cache.returnKeyFor(1);
+       }
 
-               // 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;
-                                                       }
-                                               }
+       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);
                                        }
-                               }
-                       } 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;
-                                                       }
-                                               }
+                                       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;
                        }
-                       // 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[]
-        */
-       public char[] fileName() {
-               return constantPool.UTF8Cache.returnKeyFor(1);
+               } 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;
+               }
        }
 
        /**
@@ -2211,6 +2881,187 @@ public class ClassFile
                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 @@ public class ClassFile
         * @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 @@ public class ClassFile
                        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 @@ public class ClassFile
 
                        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 @@ public class ClassFile
                }
                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 @@ public class ClassFile
        }
 
        /**
+        * 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 @@ public class ClassFile
                }
        }
 
+       
+       private boolean isRuntimeInvisible(Annotation annotation) {
+               final TypeBinding annotationBinding = annotation.resolvedType;
+               if (annotationBinding == null) {
+                       return false;
+               }
+               long metaTagBits = annotationBinding.getAnnotationTagBits();
+               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 @@ public class 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
         * This methods leaves the space for method counts recording.
         */
        public void setForMethodInfos() {
@@ -2560,62 +3724,4 @@ public class ClassFile
                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();
-               }
-       }
 }
index 684df0b..d6b7475 100644 (file)
@@ -35,6 +35,7 @@ import org.eclipse.jdt.core.compiler.*;
 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 class CompilationResult {
        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 class CompilationResult {
         */
        public void record(char[] typeName, ClassFile classFile) {
 
+           SourceTypeBinding sourceType = classFile.referenceBinding;
+           if (!sourceType.isLocalType() && sourceType.isHierarchyInconsistent()) {
+               this.hasInconsistentToplevelHierarchies = true;
+           }
                compiledTypes.put(typeName, classFile);
        }
 
index 92c85dc..ba20e99 100644 (file)
@@ -180,7 +180,7 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
        /**
         * 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 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
 //                     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 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
                                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 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
        /**
         * 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 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
                                        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 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
                                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 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
                                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/src/org/eclipse/jdt/internal/compiler/ConfigurableOption.java b/src/org/eclipse/jdt/internal/compiler/ConfigurableOption.java
deleted file mode 100644 (file)
index 13e2858..0000000
+++ /dev/null
@@ -1,227 +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;
-
-/**
- * Generic option description, which can be modified independently from the
- * component it belongs to.
- * 
- * @deprecated backport 1.0 internal functionality
- */
-
-import java.util.*;
-
-public class ConfigurableOption {
-       private String componentName;
-       private String optionName;
-       private int id;
-
-       private String category;
-       private String name;
-       private String description;
-       private int currentValueIndex;
-       private int defaultValueIndex;
-       private String[] possibleValues;
-
-       // special value for <possibleValues> indicating that 
-       // the <currentValueIndex> is the actual value
-       public final static String[] NoDiscreteValue = {}; 
-/**
- * INTERNAL USE ONLY
- *
- * Initialize an instance of this class according to a specific locale
- *
- * @param loc java.util.Locale
- */
-public ConfigurableOption(
-       String componentName, 
-       String optionName, 
-       Locale loc, 
-       int currentValueIndex) {
-
-       this.componentName = componentName;
-       this.optionName = optionName;
-       this.currentValueIndex = currentValueIndex;
-               
-       ResourceBundle resource = null;
-       try {
-               String location = componentName.substring(0, componentName.lastIndexOf('.'));
-               resource = ResourceBundle.getBundle(location + ".options", loc); //$NON-NLS-1$
-       } catch (MissingResourceException e) {
-               category = "Missing ressources entries for" + componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
-               name = "Missing ressources entries for"+ componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
-               description = "Missing ressources entries for" + componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
-               possibleValues = new String[0];
-               id = -1;
-       }
-       if (resource == null) return;
-       try {
-               id = Integer.parseInt(resource.getString(optionName + ".number")); //$NON-NLS-1$
-       } catch (MissingResourceException e) {
-               id = -1;
-       } catch (NumberFormatException e) {
-               id = -1;
-       }
-       try {
-               category = resource.getString(optionName + ".category"); //$NON-NLS-1$
-       } catch (MissingResourceException e) {
-               category = "Missing ressources entries for" + componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
-       }
-       try {
-               name = resource.getString(optionName + ".name"); //$NON-NLS-1$
-       } catch (MissingResourceException e) {
-               name = "Missing ressources entries for"+ componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
-       }
-       try {
-               StringTokenizer tokenizer = new StringTokenizer(resource.getString(optionName + ".possibleValues"), "|"); //$NON-NLS-1$ //$NON-NLS-2$
-               int numberOfValues = Integer.parseInt(tokenizer.nextToken());
-               if(numberOfValues == -1){
-                       possibleValues = NoDiscreteValue;
-               } else {
-                       possibleValues = new String[numberOfValues];
-                       int index = 0;
-                       while (tokenizer.hasMoreTokens()) {
-                               possibleValues[index] = tokenizer.nextToken();
-                               index++;
-                       }
-               }
-       } catch (MissingResourceException e) {
-               possibleValues = new String[0];
-       } catch (NoSuchElementException e) {
-               possibleValues = new String[0];
-       } catch (NumberFormatException e) {
-               possibleValues = new String[0];
-       }
-       try {
-               description = resource.getString(optionName + ".description");  //$NON-NLS-1$
-       } catch (MissingResourceException e) {
-               description = "Missing ressources entries for"+ componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
-       }
-}
-/**
- * Return a String that represents the localized category of the receiver.
- * @return java.lang.String
- */
-public String getCategory() {
-       return category;
-}
-/**
- * Return a String that identifies the component owner (typically the qualified
- *     type name of the class which it corresponds to).
- *
- * e.g. "org.eclipse.jdt.internal.compiler.api.Compiler"
- *
- * @return java.lang.String
- */
-public String getComponentName() {
-       return componentName;
-}
-/**
- * Answer the index (in possibleValues array) of the current setting for this
- * particular option.
- *
- * In case the set of possibleValues is NoDiscreteValue, then this index is the
- * actual value (e.g. max line lenght set to 80).
- *
- * @return int
- */
-public int getCurrentValueIndex() {
-       return currentValueIndex;
-}
-/**
- * Answer the index (in possibleValues array) of the default setting for this
- * particular option.
- *
- * In case the set of possibleValues is NoDiscreteValue, then this index is the
- * actual value (e.g. max line lenght set to 80).
- *
- * @return int
- */
-public int getDefaultValueIndex() {
-       return defaultValueIndex;
-}
-/**
- * Return an String that represents the localized description of the receiver.
- *
- * @return java.lang.String
- */
-public String getDescription() {
-       return description;
-}
-/**
- * Internal ID which allows the configurable component to identify this particular option.
- *
- * @return int
- */
-public int getID() {
-       return id;
-}
-/**
- * Return a String that represents the localized name of the receiver.
- * @return java.lang.String
- */
-public String getName() {
-       return name;
-}
-/**
- * Return an array of String that represents the localized possible values of the receiver.
- * @return java.lang.String[]
- */
-public String[] getPossibleValues() {
-       return possibleValues;
-}
-/**
- * Change the index (in possibleValues array) of the current setting for this
- * particular option.
- *
- * In case the set of possibleValues is NoDiscreteValue, then this index is the
- * actual value (e.g. max line lenght set to 80).
- */
-public void setValueIndex(int newIndex) {
-       currentValueIndex = newIndex;
-}
-public String toString() {
-       StringBuffer buffer = new StringBuffer();
-       buffer.append("Configurable option for "); //$NON-NLS-1$ 
-       buffer.append(this.componentName).append("\n"); //$NON-NLS-1$ 
-       buffer.append("- category:                      ").append(this.category).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
-       buffer.append("- name:                          ").append(this.name).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
-       /* display current value */
-       buffer.append("- current value: "); //$NON-NLS-1$ 
-       if (possibleValues == NoDiscreteValue){
-               buffer.append(this.currentValueIndex);
-       } else {
-               buffer.append(this.possibleValues[this.currentValueIndex]);
-       }
-       buffer.append("\n"); //$NON-NLS-1$ 
-       
-       /* display possible values */
-       if (possibleValues != NoDiscreteValue){
-               buffer.append("- possible values:       ["); //$NON-NLS-1$ 
-               for (int i = 0, max = possibleValues.length; i < max; i++) {
-                       if (i != 0)
-                               buffer.append(", "); //$NON-NLS-1$ 
-                       buffer.append(possibleValues[i]);
-               }
-               buffer.append("]\n"); //$NON-NLS-1$ 
-               buffer.append("- curr. val. index:      ").append(currentValueIndex).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
-       }
-       buffer.append("- description:           ").append(description).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
-       return buffer.toString();
-}
-       /**
-        * Gets the optionName.
-        * @return Returns a String
-        */
-       public String getOptionName() {
-               return optionName;
-       }
-}
index 74ba90b..1457547 100644 (file)
@@ -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 abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
        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 abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
        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 abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
        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 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
        // 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 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
 
                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 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
 
                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 class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
 
        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 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
                        output.append("abstract "); //$NON-NLS-1$
                return output;
        }
+       
+       /**
+        * Resolve annotations, and check duplicates, answers combined tagBits 
+        * for recognized standard annotations
+        */
+       public 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;
        }
index c25253e..985a97d 100644 (file)
@@ -32,6 +32,7 @@ public abstract class AbstractMethodDeclaration
        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 @@ public abstract class AbstractMethodDeclaration
                        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 @@ public abstract class AbstractMethodDeclaration
                }
        }
 
-       private void generateCode(ClassFile classFile) {
+       public void generateCode(ClassFile classFile) {
 
                classFile.generateMethodInfoHeader(this.binding);
                int methodAttributeOffset = classFile.contentsOffset;
@@ -258,6 +263,11 @@ public abstract class AbstractMethodDeclaration
                return (this.modifiers & AccAbstract) != 0;
        }
 
+       public boolean isAnnotationMethod() {
+
+               return false;
+       }
+       
        public boolean isClinit() {
 
                return false;
@@ -278,6 +288,11 @@ public abstract class AbstractMethodDeclaration
                return false;
        }
 
+       public boolean isMethod() {
+
+               return false;
+       }
+
        public boolean isNative() {
 
                if (this.binding != null)
@@ -305,6 +320,20 @@ public abstract class AbstractMethodDeclaration
 
                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 @@ public abstract class AbstractMethodDeclaration
                        bindArguments(); 
                        bindThrownExceptions();
                        resolveJavadoc();
+                       resolveAnnotations(scope, this.annotations, this.binding);
                        resolveStatements();
                } catch (AbortMethod e) {       // ========= abort on fatal error =============
                        this.ignoreFurtherInvestigation = true;
@@ -395,4 +425,8 @@ public abstract class AbstractMethodDeclaration
                ClassScope classScope) {
                // default implementation: subclass will define it
        }
+       
+       public TypeParameter[] typeParameters() {
+           return null;
+       }
 }
index cce62fc..ec08039 100644 (file)
@@ -15,6 +15,7 @@ import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 
 public abstract class AbstractVariableDeclaration extends Statement implements InvocationSite {
        public int declarationEnd;
@@ -24,6 +25,7 @@ public abstract class AbstractVariableDeclaration extends Statement implements I
        public Expression initialization;
        public int modifiers;
        public int modifiersSourceStart;
+       public Annotation[] annotations;
 
        public char[] name;
 
@@ -32,6 +34,27 @@ public abstract class AbstractVariableDeclaration extends Statement implements I
        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 @@ public abstract class AbstractVariableDeclaration extends Statement implements I
                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(' ');
+               }
+               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(';');
                }
-               return output.append(';');
        }
 
        public void resolve(BlockScope scope) {
index 2a47d4d..e631f12 100644 (file)
@@ -15,15 +15,16 @@ import org.eclipse.jdt.internal.compiler.codegen.*;
 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 @@ public class AllocationExpression
                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 @@ public class AllocationExpression
                                                currentScope.problemReporter().uninitializedLocalVariable(targetLocal, this);
                                        }
                                }
-                                               
                }
        }
        
@@ -88,14 +88,20 @@ public class AllocationExpression
                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 @@ public class AllocationExpression
                                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 @@ public class AllocationExpression
                }
                // 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 class AllocationExpression
        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 class AllocationExpression
        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 @@ public class AllocationExpression
 
                // 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 @@ public class AllocationExpression
                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 @@ public class AllocationExpression
                }
                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 class AllocationExpression
        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/src/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/src/org/eclipse/jdt/internal/compiler/ast/Annotation.java
new file mode 100644 (file)
index 0000000..fb31f38
--- /dev/null
@@ -0,0 +1,299 @@
+/*******************************************************************************
+ * 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[] valuePairs = memberValuePairs();
+               MemberValuePair valueAttribute = null; // remember the first 'value' pair
+               MemberValuePair[] usedValuePairs;
+               int pairsLength = valuePairs.length;
+               System.arraycopy(valuePairs, 0, usedValuePairs = 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 valuePair = usedValuePairs[j];
+                               if (valuePair == null) continue nextPair;
+                               char[] memberName = valuePair.name;
+                               if (CharOperation.equals(memberName, selector)) {
+                                       if (valueAttribute == null && CharOperation.equals(memberName, TypeConstants.VALUE)) {
+                                               valueAttribute = valuePair;
+                                       }
+                                       valuePair.binding = method;
+                                       usedValuePairs[j] = null; // consumed
+                                       foundValue = true;
+                                       boolean foundDuplicate = false;
+                                       for (int k = j+1; k < pairsLength; k++) {
+                                               if (CharOperation.equals(usedValuePairs[k].name, selector)) {
+                                                       foundDuplicate = true;
+                                                       scope.problemReporter().duplicateAnnotationValue(annotationType, usedValuePairs[k]);
+                                                       usedValuePairs[k].binding = method;
+                                                       usedValuePairs[k] = null;
+                                               }
+                                       }
+                                       if (foundDuplicate) {
+                                               scope.problemReporter().duplicateAnnotationValue(annotationType, valuePair);
+                                               continue nextMember;
+                                       }
+                                       valuePair.resolveTypeExpecting(scope, method.returnType);
+                               }
+                       }
+                       if (!foundValue && (method.modifiers & AccAnnotationDefault) == 0) {
+                               scope.problemReporter().missingValueForAnnotationMember(this, method.selector);
+                       }
+               }
+               // check unused pairs
+               for (int i = 0; i < pairsLength; i++) {
+                       if (usedValuePairs[i] != null) {
+                               scope.problemReporter().undefinedAnnotationValue(annotationType, usedValuePairs[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();
+                               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/src/org/eclipse/jdt/internal/compiler/ast/AnnotationMethodDeclaration.java b/src/org/eclipse/jdt/internal/compiler/ast/AnnotationMethodDeclaration.java
new file mode 100644 (file)
index 0000000..c7ef29f
--- /dev/null
@@ -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);
+       }
+}
index b6669ac..4a75e07 100644 (file)
@@ -18,7 +18,7 @@ public class Argument extends LocalDeclaration {
        
        // prefix for setter method (to recognize special hiding argument)
        private final static char[] SET = "set".toCharArray(); //$NON-NLS-1$
-
+       
        public Argument(char[] name, long posNom, TypeReference tr, int modifiers) {
 
                super(name, (int) (posNom >>> 32), (int) posNom);
@@ -31,11 +31,11 @@ public class Argument extends LocalDeclaration {
        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 @@ public class Argument extends LocalDeclaration {
                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 @@ public class Argument extends LocalDeclaration {
                // 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 @@ public class Argument extends LocalDeclaration {
                        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) {
index d9ab28d..d1862ff 100644 (file)
@@ -73,7 +73,7 @@ public class ArrayAllocationExpression extends Expression {
                // 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 @@ public class ArrayAllocationExpression extends Expression {
                // 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 @@ public class ArrayAllocationExpression extends Expression {
 
                // 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 @@ public class ArrayAllocationExpression extends Expression {
                        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 @@ public class ArrayAllocationExpression extends Expression {
                        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 @@ public class ArrayAllocationExpression extends Expression {
                        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) {
index b717047..9310cf7 100644 (file)
@@ -47,7 +47,7 @@ public class ArrayInitializer extends Expression {
                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 @@ public class ArrayInitializer extends Expression {
                                }
                        }
                }
-               if (!valueRequired) {
+               if (valueRequired) {
+                       codeStream.generateImplicitConversion(this.implicitConversion);
+               } else {
                        codeStream.pop();
                }
                codeStream.recordPositionsFrom(pc, this.sourceStart);
@@ -133,12 +135,19 @@ public class ArrayInitializer extends Expression {
        
                // 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 @@ public class ArrayInitializer extends Expression {
                                                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 @@ public class ArrayInitializer extends Expression {
                        }
                }
                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;
        }
index 701f3a6..6c6d1ad 100644 (file)
  *******************************************************************************/
 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 @@ public class ArrayQualifiedTypeReference extends QualifiedTypeReference {
                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;
        }
index 915b347..fc0bb69 100644 (file)
@@ -51,10 +51,9 @@ public class ArrayReference extends Reference {
                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 @@ public class ArrayReference extends Reference {
                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 @@ public class ArrayReference extends Reference {
                                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 @@ public class ArrayReference extends Reference {
                }               
                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;
        }
index eec8865..66d9947 100644 (file)
  *******************************************************************************/
 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 class ArrayTypeReference extends SingleTypeReference {
        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 @@ public class ArrayTypeReference extends SingleTypeReference {
                
                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 @@ public class ArrayTypeReference extends SingleTypeReference {
                visitor.visit(this, scope);
                visitor.endVisit(this, scope);
        }
+       
+       public void traverse(ASTVisitor visitor, ClassScope scope) {
+               
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
 }
index cf3093a..dedee1f 100644 (file)
@@ -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 @@ public class AssertStatement extends Statement {
                                        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 @@ public class AssertStatement extends Statement {
                                        case T_float :
                                        case T_int :
                                        case T_long :
-                                       case T_String :
+                                       case T_JavaLangString :
                                                exceptionArgument.implicitConversion = (id << 4) + id;
                                }
                        }
@@ -168,7 +169,7 @@ public class AssertStatement extends Statement {
                        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 @@ public class AssertStatement extends Statement {
                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;
                        }
                }
index 5b86ade..e43c286 100644 (file)
@@ -42,9 +42,25 @@ public class Assignment extends Expression {
                // 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 @@ public class Assignment extends Expression {
                }
        }
 
+       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 @@ public class Assignment extends Expression {
                }
                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 @@ public class Assignment extends Expression {
                        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 @@ public class Assignment extends Expression {
                        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;
        }
 
index b5804d0..d5a0b3e 100644 (file)
@@ -96,8 +96,8 @@ public class BinaryExpression extends OperatorExpression {
                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 @@ public class BinaryExpression extends OperatorExpression {
                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 @@ public class BinaryExpression extends OperatorExpression {
                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 @@ public class BinaryExpression extends OperatorExpression {
                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 @@ public class BinaryExpression extends OperatorExpression {
                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 @@ public class BinaryExpression extends OperatorExpression {
                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 @@ public class BinaryExpression extends OperatorExpression {
                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 @@ public class BinaryExpression extends OperatorExpression {
                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 @@ public class BinaryExpression extends OperatorExpression {
                codeStream.updateLastRecordedEndPC(codeStream.position);                                        
        }
        
-       public void generateOptimizedStringBuffer(
+       public void generateOptimizedStringConcatenation(
                BlockScope blockScope,
                CodeStream codeStream,
                int typeID) {
@@ -1536,30 +1536,30 @@ public class BinaryExpression extends OperatorExpression {
                 */
 
                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 @@ public class BinaryExpression extends OperatorExpression {
                 */
 
                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 @@ public class BinaryExpression extends OperatorExpression {
                        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 @@ public class BinaryExpression extends OperatorExpression {
                        }
                }
                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 @@ public class BinaryExpression extends OperatorExpression {
                // 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 @@ public class BinaryExpression extends OperatorExpression {
                        case T_long :
                                this.resolvedType = LongBinding;
                                break;
-                       case T_String :
+                       case T_JavaLangString :
                                this.resolvedType = scope.getJavaLangString();
                                break;
                        default : //error........
@@ -1743,10 +1759,10 @@ public class BinaryExpression extends OperatorExpression {
 
                // 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;
        }
 
index 56380f7..ea3a9ae 100644 (file)
@@ -20,6 +20,8 @@ public class CaseStatement extends Statement {
        
        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 @@ public class CaseStatement extends Statement {
                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 @@ public class CaseStatement extends Statement {
                // 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 @@ public class CaseStatement extends Statement {
        
                        // 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))
-                       return constantExpression.constant;
-               if (caseType.isCompatibleWith(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;
-               scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
-                       constantExpression,
-                       caseType,
-                       switchType);
-               return null;
+               }
+               scope.problemReporter().typeMismatchError(caseType, switchExpressionType, constantExpression);
+               return NotAConstant;
        }
 
 
index ecfe767..79e4922 100644 (file)
@@ -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 class CastExpression extends Expression {
 
        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 @@ public class CastExpression extends Expression {
        }
 
        /**
-        * 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 @@ public class CastExpression extends Expression {
                }
                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 @@ public class CastExpression extends Expression {
                        //  <<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 @@ public class CastExpression extends Expression {
        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,33 @@ public class CastExpression extends Expression {
                                }
                        }       
        }
+       
+       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 ? !expressionType.isEquivalentTo(match) : !match.isEquivalentTo(castType)) {
+                               scope.problemReporter().unsafeCast(this);
+                               return true;
+                       }
+                       if ((castType.tagBits & TagBits.HasDirectWildcard) == 0) {
+                               if ((!match.isParameterizedType() && !match.isGenericType())
+                                               || expressionType.isRawType()) {
+                                       scope.problemReporter().unsafeCast(this);
+                                       return true;
+                               }
+                       }
+               }
+               if (!isNarrowing) tagAsUnnecessaryCast(scope, castType);
+               return true;
+       }       
+       
        /**
         * Cast expression code generation
         *
@@ -421,7 +283,7 @@ public class CastExpression extends Expression {
                BlockScope currentScope,
                CodeStream codeStream,
                boolean valueRequired) {
-
+       
                int pc = codeStream.position;
                boolean needRuntimeCheckcast = (this.bits & NeedRuntimeCheckCastMASK) != 0;
                if (constant != NotAConstant) {
@@ -429,8 +291,11 @@ public class CastExpression extends Expression {
                                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 +307,11 @@ public class CastExpression extends Expression {
                        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 +327,17 @@ public class CastExpression extends Expression {
                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 +345,10 @@ public class CastExpression extends Expression {
                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 +363,67 @@ public class CastExpression extends Expression {
                                && ((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) {
index c2d90b0..8aad9ab 100644 (file)
@@ -84,11 +84,9 @@ private void computeValue() {
  */
 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) {
index 4a4136e..4e35315 100644 (file)
@@ -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 @@ public class ClassLiteralAccess extends Expression {
                // 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 @@ public class ClassLiteralAccess extends Expression {
                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 class ClassLiteralAccess extends Expression {
        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(
index 2bbac9c..22dbe6d 100644 (file)
@@ -13,6 +13,7 @@ package org.eclipse.jdt.internal.compiler.ast;
 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 @@ import org.eclipse.jdt.internal.compiler.problem.*;
 
 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 @@ public class Clinit extends AbstractMethodDeclaration {
                                        && (!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 @@ public class Clinit extends AbstractMethodDeclaration {
                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 @@ public class Clinit extends AbstractMethodDeclaration {
                        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 @@ public class Clinit extends AbstractMethodDeclaration {
                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);
+               }
        }
 
 }
index d736614..df96e49 100644 (file)
@@ -19,6 +19,8 @@ import org.eclipse.jdt.internal.compiler.problem.*;
 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 class CompilationUnitDeclaration
        }
 
        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++) {
index 47745f1..fda4ef3 100644 (file)
@@ -54,6 +54,10 @@ public class CompoundAssignment extends Assignment implements OperatorIds {
                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 @@ public class CompoundAssignment extends Assignment implements OperatorIds {
                        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,28 @@ public class CompoundAssignment extends Assignment implements OperatorIds {
                //  <<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);
+               this.expression.computeConversion(scope, TypeBinding.wellKnownType(scope, (result >>> 8) & 0x0000F), originalExpressionType);
+               this.assignmentImplicitConversion =  (unboxedLhs ? BOXING : 0) | (lhsID << 4) | (result & 0x0000F);
+               return this.resolvedType = originalLhsType;
        }
        
        public boolean restrainUsageToNumericTypes(){
index cf86373..2572232 100644 (file)
@@ -12,6 +12,7 @@ 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.lookup.*;
@@ -200,7 +201,7 @@ public class ConditionalExpression extends OperatorExpression {
                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 @@ public class ConditionalExpression extends OperatorExpression {
                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 @@ public class ConditionalExpression extends OperatorExpression {
                }
                // 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 class ConditionalExpression extends OperatorExpression {
        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 @@ public class ConditionalExpression extends OperatorExpression {
                        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 @@ public class ConditionalExpression extends OperatorExpression {
                        // (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 @@ public class ConditionalExpression extends OperatorExpression {
                                        || 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 @@ public class ConditionalExpression extends OperatorExpression {
                        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,
index 7170bbf..892b91b 100644 (file)
@@ -24,8 +24,9 @@ import org.eclipse.jdt.internal.compiler.problem.*;
 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 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
                                }
                        }
                        
+                       // 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 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
                
                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 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
                        // 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 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
                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 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
                }
                
                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 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
                //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 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
                        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 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
                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 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
                }
                visitor.endVisit(this, classScope);
        }
+       public TypeParameter[] typeParameters() {
+           return this.typeParameters;
+       }               
 }
index 0dc995d..a12254a 100644 (file)
@@ -59,11 +59,12 @@ public class DoStatement extends Statement {
 
                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 @@ public class DoStatement extends Statement {
                 *   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 class DoStatement extends Statement {
        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);
        }
index 139c813..1c8a8c1 100644 (file)
@@ -14,58 +14,100 @@ 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.util.FloatUtil;
 
 public class DoubleLiteral extends NumberLiteral {
        double value;
-public DoubleLiteral(char[] token, int s, int e) {
-       super(token, s,e);
-}
-public void computeConstant() {
-
-       //the source is correctly formated so the exception should never occurs
+       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;
+               }
 
-       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);
+       }
 }
index 0caeb81..4b2fec9 100644 (file)
@@ -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 @@ import org.eclipse.jdt.internal.compiler.lookup.*;
 
 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;
+       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
+                               }
+                               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
+                               }
+                               break;
+               }       
        }
-
-
-       //========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;
+       
+       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();
                                }
-                               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;
+                       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 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;
+                       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();
                                }
-                               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;
-                                                               }
-                                                       }
-                                               }
-                                       }
+                       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 true;
+                       return right.analyseCode(
+                               currentScope, flowContext, 
+                               left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).asNegatedCondition().unconditionalInits();
                }
-               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();
-                       }
+       
+       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 {
-                       falseLabel.place();
-               }       
-       }
-}
-/**
- * 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;
+                       this.constant = NotAConstant;
+                       // no optimization for null == null
+               }
        }
-       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);
+       /**
+        * 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;
                }
-       } else {
-               if ((left.implicitConversion & 0xF) /*compile-time*/ == T_boolean) {
-                       generateOptimizedBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
-               } else {
-                       generateOptimizedNonBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
+               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 {
+                               falseLabel.place();
+                       }       
                }
        }
-}
-/**
- * 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);
+       /**
+        * 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 & COMPILE_TYPE_MASK) /*compile-time*/ == T_boolean) {
+                               generateOptimizedBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+                       } else {
+                               generateOptimizedNonBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
                        }
                } else {
-                       // implicit falling through the TRUE case
-                       if (trueLabel == null) {
-                               codeStream.if_icmpne(falseLabel);
+                       if ((left.implicitConversion & COMPILE_TYPE_MASK) /*compile-time*/ == T_boolean) {
+                               generateOptimizedBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
                        } else {
-                               // no implicit fall through TRUE/FALSE --> should never occur
+                               generateOptimizedNonBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
                        }
                }
        }
-       // 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);
-                                       }
+       /**
+        * 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 {
-                                       // implicit falling through the TRUE case
-                                       if (trueLabel == null) {
-                                               codeStream.ifne(falseLabel);
-                                       } else {
-                                               // no implicit fall through TRUE/FALSE --> should never occur
-                                       }
+                                       // no implicit fall through TRUE/FALSE --> should never occur
                                }
                        }
-                       codeStream.recordPositionsFrom(pc, this.sourceStart);
-                       return;
                }
+               // reposition the endPC
+               codeStream.updateLastRecordedEndPC(codeStream.position);                                        
        }
-       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);
+       /**
+        * 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
+                                               }
                                        }
-                               } else {
-                                       // implicit falling through the TRUE case
-                                       if (trueLabel == null) {
-                                               codeStream.ifne(falseLabel);
+                               }
+                               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 {
-                                               // no implicit fall through TRUE/FALSE --> should never occur
+                                               // 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;
                        }
-                       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();
+               // 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 {
-                                                       codeStream.iconst_0();
+                                                       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 {
-                                               if (falseLabel == null) {
-                                                       // implicit falling through the FALSE case
-                                                       if (trueLabel != null) {
-                                                               codeStream.goto_(trueLabel);
-                                                       }
+                                               // implicit falling through the TRUE case
+                                               if (trueLabel == null) {
+                                                       codeStream.ifnonnull(falseLabel);
+                                               } else {
+                                                       // no implicit fall through TRUE/FALSE --> should never occur
                                                }
+                                       }
                                }
                        }
-               } else {
-                       left.generateCode(currentScope, codeStream, valueRequired);
+                       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 @@ public void generateOptimizedNonBooleanEqual(BlockScope currentScope, CodeStream
                                        }
                                }
                        }
+                       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
-                       }
-               }
-       }
-       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;
+       public boolean isCompactableOperation() {
+               return false;
        }
-
-       // 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);
+       
+               // 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);
+                               }
+                       }
                }
-               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)) {
+               // 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);
-               } else {
-                       constant = NotAConstant;
-               }
-               if (rightType.id == T_String) {
-                       right.implicitConversion = String2String;
-               }
-               if (leftType.id == T_String) {
-                       left.implicitConversion = String2String;
+                       return this.resolvedType = BooleanBinding;
                }
-               // check need for operand cast
-               boolean unnecessaryLeftCast = (left.bits & UnnecessaryCastMask) != 0;
-               boolean unnecessaryRightCast = (right.bits & UnnecessaryCastMask) != 0;
-               if (unnecessaryLeftCast || unnecessaryRightCast) {
-                       TypeBinding alternateLeftType = unnecessaryLeftCast ? ((CastExpression)left).expression.resolvedType : leftType;
-                       TypeBinding alternateRightType = unnecessaryRightCast ? ((CastExpression)right).expression.resolvedType : rightType;
-                       if (areTypesCastCompatible(scope, alternateLeftType, alternateRightType)
-                                       || areTypesCastCompatible(scope, alternateRightType, alternateLeftType)) {
-                               if (unnecessaryLeftCast) scope.problemReporter().unnecessaryCast((CastExpression)left); 
-                               if (unnecessaryRightCast) scope.problemReporter().unnecessaryCast((CastExpression)right);
+       
+               // 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;
                }
-               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);
-}
 }
index ec709ff..a0b814e 100644 (file)
@@ -15,24 +15,26 @@ import org.eclipse.jdt.internal.compiler.codegen.*;
 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 @@ public class ExplicitConstructorCall
                        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 @@ public class ExplicitConstructorCall
                                        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 @@ public class ExplicitConstructorCall
                        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 @@ public class ExplicitConstructorCall
         * 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 class ExplicitConstructorCall
        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 @@ public class ExplicitConstructorCall
 
                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 @@ public class ExplicitConstructorCall
                        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 @@ public class ExplicitConstructorCall
                                        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 @@ public class ExplicitConstructorCall
                                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 @@ public class ExplicitConstructorCall
                        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);
index ae3b502..df2538d 100644 (file)
  *******************************************************************************/
 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 @@ import org.eclipse.jdt.internal.compiler.util.Util;
 
 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,345 @@ public abstract class Expression extends Statement {
                                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.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.isClass()) {
+                       if (castType.isArrayType()) {
+                               // ---- (castType.isArray) expressionType.isClass -------
+                               if (expressionType.id == T_JavaLangObject) { // potential runtime error
+                                       tagAsNeedCheckCast();
+                                       return true;
+                               }
+                       } else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isClass ------
+                               
+                               ReferenceBinding 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 -------  
+
+                               ReferenceBinding 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.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
+                               ReferenceBinding match = ((ReferenceBinding)castType).findSuperTypeErasingTo((ReferenceBinding)expressionType.erasure());
+                               if (match == null) {
+                                       // potential runtime error
+                                       reportIllegalCast(scope, castType, expressionType);
+                                       return false;
+                               }                               
+                       }
+               } else { // ----- (castType.isInterface) expressionType.isInterface -------
+
+                       ReferenceBinding 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()) {
+                               compileTimeType = scope.environment().computeBoxingType(compileTimeType);
+                               this.implicitConversion = UNBOXING;
+                       }
+               } 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;
+                               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 +624,58 @@ public abstract class Expression extends Statement {
         * 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;
-                               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;
+                               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;
-                       default : //nothing on regular object ref
+                       default :
+                               generateCode(blockScope, codeStream, true);
+                               codeStream.invokeStringValueOf(typeID);
                }
+               codeStream.invokeStringConcatenationStringConstructor();
        }
 
        public boolean isCompactableOperation() {
@@ -413,11 +685,9 @@ public abstract class Expression extends Statement {
 
        //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 +708,49 @@ public abstract class Expression extends Statement {
        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 +773,39 @@ public abstract class Expression extends Statement {
                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 +816,21 @@ public abstract class Expression extends Statement {
 
                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;
+       }
 }
index 82bc72d..6219111 100644 (file)
@@ -21,8 +21,8 @@ public FalseLiteral(int s , int e) {
        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 computeConstant() {
  */
 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) {
index 7f001c3..9c08cb0 100644 (file)
@@ -17,6 +17,7 @@ import org.eclipse.jdt.internal.compiler.flow.*;
 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 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
                }
                // 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 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
                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 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
                codeStream.recordPositionsFrom(pc, this.sourceStart);
        }
 
-       public TypeBinding getTypeBinding(Scope scope) {
-
-               return this.type.getTypeBinding(scope);
-       }
-
-       public boolean isField() {
-
-               return true;
+       /**
+        * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
+        */
+       public int getKind() {
+               return this.type == null ? ENUM_CONSTANT : FIELD;
        }
-
+       
        public boolean isStatic() {
 
                if (this.binding != null)
@@ -144,6 +153,8 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
 
                        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 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
                                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,8 +173,8 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
                                        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()
+                                       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())) {
@@ -172,7 +183,9 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
                                }
                        }
                        
-                       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 +193,48 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
                                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;
-                                       
-                                       TypeBinding typeBinding = this.binding.type;
-                                       TypeBinding initializationTypeBinding;
+                                       this.binding.setConstant(Constant.NotAConstant);
                                        
+                                       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) {
-
-                                               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);
-
+                                       } else if ((initializationType = this.initialization.resolveType(initializationScope)) != null) {
+
+                                               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 +251,8 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
                        } 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 +260,14 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
        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);
                }
index 9c4a86d..1e00105 100644 (file)
@@ -21,11 +21,16 @@ public class FieldReference extends Reference implements InvocationSite {
 
        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 @@ public class FieldReference extends Reference implements InvocationSite {
                //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 @@ public class FieldReference extends Reference implements InvocationSite {
                                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 @@ public class FieldReference extends Reference implements InvocationSite {
                                        .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 @@ public class FieldReference extends Reference implements InvocationSite {
                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 @@ public class FieldReference extends Reference implements InvocationSite {
                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 @@ public class FieldReference extends Reference implements InvocationSite {
                        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 @@ public class FieldReference extends Reference implements InvocationSite {
                        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 @@ public class FieldReference extends Reference implements InvocationSite {
                        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 @@ public class FieldReference extends Reference implements InvocationSite {
                                }
                        }
                }
+               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 @@ public class FieldReference extends Reference implements InvocationSite {
                        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 @@ public class FieldReference extends Reference implements InvocationSite {
                //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 @@ public class FieldReference extends Reference implements InvocationSite {
        /*
         * 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 @@ public class FieldReference extends Reference implements InvocationSite {
                        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 @@ public class FieldReference extends Reference implements InvocationSite {
                                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 @@ public class FieldReference extends Reference implements InvocationSite {
                        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 @@ public class FieldReference extends Reference implements InvocationSite {
                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) {
index c7d53d6..0fa1908 100644 (file)
 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);
+       }
 }
index 51c5db6..ad6c97a 100644 (file)
@@ -83,14 +83,15 @@ public class ForStatement extends Statement {
                
                // 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 @@ public class ForStatement extends Statement {
                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 @@ public class ForStatement extends Statement {
                                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 @@ public class ForStatement extends Statement {
 
                // 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 @@ public class ForStatement extends Statement {
                                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/src/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java b/src/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
new file mode 100644 (file)
index 0000000..1c1dbb1
--- /dev/null
@@ -0,0 +1,461 @@
+/*******************************************************************************
+ * 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;
+                                               }
+                                       } 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 (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);
+       }
+}
index a262104..223a9ed 100644 (file)
@@ -71,6 +71,11 @@ public class IfStatement extends Statement {
                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 @@ public class IfStatement extends Statement {
                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 @@ public class IfStatement extends Statement {
                                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 class IfStatement extends Statement {
        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)
index 9dda67e..546e57c 100644 (file)
@@ -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 @@ public class ImplicitDocTypeReference extends TypeReference {
        /* (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 @@ public class ImplicitDocTypeReference extends TypeReference {
                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) {
index 4623b2d..fca4408 100644 (file)
@@ -23,6 +23,7 @@ public class ImportReference extends ASTNode {
        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 @@ public class ImportReference extends ASTNode {
                this.sourceStart = (int) (sourcePositions[0] >>> 32);
                this.modifiers = modifiers;
        }
+       
+       public boolean isStatic() {
+               return (this.modifiers & AccStatic) != 0;
+       }
 
        /**
         * @return char[][]
@@ -67,6 +72,11 @@ public class ImportReference extends ASTNode {
        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);
        }
 }
index ff53718..987149f 100644 (file)
@@ -57,16 +57,18 @@ public class Initializer extends FieldDeclaration {
                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 @@ public class Initializer extends FieldDeclaration {
 
                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;
index feacdaf..5a47db8 100644 (file)
@@ -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 @@ public class InstanceOfExpression extends OperatorExpression {
                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 @@ public class InstanceOfExpression extends OperatorExpression {
                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 @@ public class InstanceOfExpression extends OperatorExpression {
                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)) {
index 46a2172..0e7821e 100644 (file)
@@ -56,7 +56,7 @@ public void computeConstant() {
                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 computeConstant() {
  */ 
 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) {
index f683964..03cdba4 100644 (file)
 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 class Javadoc extends ASTNode {
         */
        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 @@ public class Javadoc extends ASTNode {
         * 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 @@ public class Javadoc extends ASTNode {
                }
 
                // @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 @@ public class Javadoc extends ASTNode {
                }
 
                // @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 @@ public class Javadoc extends ASTNode {
                
                // 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 @@ public class Javadoc extends ASTNode {
                                                        }
                                                }
                                        }
-                                       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 @@ public class Javadoc extends ASTNode {
 
                // @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 @@ public class Javadoc extends ASTNode {
                }
        }
        
+       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 @@ public class Javadoc extends ASTNode {
                        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 @@ public class Javadoc extends ASTNode {
 
                        // 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 @@ public class Javadoc extends ASTNode {
                                                }
                                        }
                                        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 @@ public class Javadoc extends ASTNode {
         */
        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 @@ public class Javadoc extends ASTNode {
 
                        // 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 @@ public class Javadoc extends ASTNode {
         * 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 @@ public class Javadoc extends ASTNode {
                }
                // 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 @@ public class Javadoc extends ASTNode {
                                                }
                                        }
                                } 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];
                                                                }
index 6c7ff1f..032ebd2 100644 (file)
@@ -17,6 +17,7 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 public class JavadocAllocationExpression extends AllocationExpression {
 
        public int tagSourceStart, tagSourceEnd;
+       public int tagValue;
        public boolean superAccess = false;
        
        public JavadocAllocationExpression(long pos) {
@@ -37,7 +38,7 @@ public class JavadocAllocationExpression extends AllocationExpression {
                } 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 @@ public class JavadocAllocationExpression extends AllocationExpression {
                if (isMethodUseDeprecated(this.binding, scope)) {
                        scope.problemReporter().javadocDeprecatedMethod(this.binding, this, scope.getDeclarationModifiers());
                }
-
+               // TODO (frederic) add support for unsafe type operation warning
                return allocationType;
        }
        
index 57be26e..d55372a 100644 (file)
@@ -35,27 +35,23 @@ public class JavadocArgumentExpression extends Expression {
         */
        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;
index 86b4d0e..e2c44c4 100644 (file)
@@ -12,6 +12,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;
 
 
@@ -39,4 +40,9 @@ public class JavadocArrayQualifiedTypeReference extends ArrayQualifiedTypeRefere
                visitor.visit(this, scope);
                visitor.endVisit(this, scope);
        }
+       
+       public void traverse(ASTVisitor visitor, ClassScope scope) {
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
 }
index 8395065..67cde84 100644 (file)
@@ -12,6 +12,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;
 
 
@@ -37,4 +38,9 @@ public class JavadocArraySingleTypeReference extends ArrayTypeReference {
                visitor.visit(this, scope);
                visitor.endVisit(this, scope);
        }
+
+       public void traverse(ASTVisitor visitor, ClassScope scope) {
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
 }
index 04f1016..9277647 100644 (file)
@@ -16,11 +16,23 @@ import org.eclipse.jdt.internal.compiler.lookup.*;
 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 @@ public class JavadocFieldReference extends FieldReference {
                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 @@ public class JavadocFieldReference extends FieldReference {
         * @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/src/org/eclipse/jdt/internal/compiler/ast/JavadocImportReference.java b/src/org/eclipse/jdt/internal/compiler/ast/JavadocImportReference.java
deleted file mode 100644 (file)
index 2f6d5b0..0000000
+++ /dev/null
@@ -1,32 +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.ast;
-
-/**
- */
-public class JavadocImportReference extends ImportReference {
-
-       public int tagSourceStart, tagSourceEnd;
-
-       /**
-        * @param tokens
-        * @param sourcePositions
-        * @param tagStart
-        * @param tagEnd
-        */
-       public JavadocImportReference(char[][] tokens, long[] sourcePositions, int tagStart, int tagEnd) {
-               super(tokens, sourcePositions, false, AccDefault);
-               this.tagSourceStart = tagStart;
-               this.tagSourceEnd = tagEnd;
-               this.bits |= InsideJavadoc;
-       }
-
-}
index ec69136..3d10d73 100644 (file)
@@ -17,6 +17,7 @@ import org.eclipse.jdt.internal.compiler.lookup.*;
 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 @@ public class JavadocMessageSend extends MessageSend {
                // 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 @@ public class JavadocMessageSend extends MessageSend {
                }
 
                // 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 @@ public class JavadocMessageSend extends MessageSend {
                }
                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 @@ public class JavadocMessageSend extends MessageSend {
                        // 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;
                }
index 388f8ef..5daff1e 100644 (file)
@@ -47,40 +47,41 @@ public class JavadocQualifiedTypeReference extends QualifiedTypeReference {
                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 (isTypeUseDeprecated(this.resolvedType, scope)) {
-                               reportDeprecatedType(scope);
+               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);
                        }
+                       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 @@ public class JavadocQualifiedTypeReference extends QualifiedTypeReference {
         * We need to override to handle package references
         */
        public TypeBinding resolveType(ClassScope classScope) {
-               return internalResolveType(classScope);
+               return internalResolveType(classScope, false);
        }
 }
index 8a53e1b..d541e00 100644 (file)
@@ -16,6 +16,7 @@ import org.eclipse.jdt.internal.compiler.lookup.*;
 
 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 @@ public class JavadocReturnStatement extends ReturnStatement {
                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 @@ public class JavadocReturnStatement extends ReturnStatement {
                                : 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)
         */
index 5661217..4bfe4c6 100644 (file)
@@ -17,8 +17,10 @@ public class JavadocSingleNameReference extends SingleNameReference {
 
        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 @@ public class JavadocSingleNameReference extends SingleNameReference {
                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);
                        }
                }
        }
index 541f099..44c3c3c 100644 (file)
@@ -46,40 +46,39 @@ public class JavadocSingleTypeReference extends SingleTypeReference {
                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 (isTypeUseDeprecated(this.resolvedType, scope)) {
-                               reportDeprecatedType(scope);
+               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);
                        }
+                       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);
        }
 
index 353fc00..57fee6e 100644 (file)
@@ -40,21 +40,24 @@ public class LocalDeclaration extends AbstractVariableDeclaration {
                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 @@ public class LocalDeclaration extends AbstractVariableDeclaration {
                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 @@ public class LocalDeclaration extends AbstractVariableDeclaration {
                        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 @@ public class LocalDeclaration extends AbstractVariableDeclaration {
                // 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 @@ public class LocalDeclaration extends AbstractVariableDeclaration {
                        // (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);
                        }
                }
        }
index 70294b5..6da299b 100644 (file)
@@ -38,7 +38,7 @@ public void computeConstant() {
        {       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 computeConstant() {
  */ 
 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/src/org/eclipse/jdt/internal/compiler/ast/MarkerAnnotation.java b/src/org/eclipse/jdt/internal/compiler/ast/MarkerAnnotation.java
new file mode 100644 (file)
index 0000000..65f1bd5
--- /dev/null
@@ -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/src/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java b/src/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java
new file mode 100644 (file)
index 0000000..04d0ee8
--- /dev/null
@@ -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);
+       }
+}
index a9a2e9d..05b78da 100644 (file)
@@ -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.codegen.*;
 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 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
        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 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean
        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 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean
                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 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean
        // 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 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean
        }
        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 boolean isTypeAccess() {
 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 @@ public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo f
 
                // 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 @@ public TypeBinding resolveType(BlockScope scope) {
        // 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 @@ public TypeBinding resolveType(BlockScope scope) {
                        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)
+       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.codegenBinding = this.binding = 
+       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);
+               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 :
+               }
                // 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;
+               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 = this.binding == null ? null : this.binding.returnType;
+               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 @@ public TypeBinding resolveType(BlockScope scope) {
        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 setFieldIndex(int depth) {
 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++)
index b738665..c9de4c6 100644 (file)
@@ -13,6 +13,7 @@ package org.eclipse.jdt.internal.compiler.ast;
 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 @@ import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
 public class MethodDeclaration extends AbstractMethodDeclaration {
        
        public TypeReference returnType;
-
+       public TypeParameter[] typeParameters;
+       
        /**
         * MethodDeclaration constructor comment.
         */
@@ -49,10 +51,14 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
                                }
                        }
                                
+                       // 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 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
                                        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 class MethodDeclaration extends AbstractMethodDeclaration {
                }
        }
 
+       public boolean isMethod() {
+
+               return true;
+       }
+
        public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
 
                //fill up the method body with statement
@@ -110,29 +127,35 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
                        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 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
                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 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
                }
                visitor.endVisit(this, classScope);
        }
+       public TypeParameter[] typeParameters() {
+           return this.typeParameters;
+       }               
 }
index 98a3f30..c48432f 100644 (file)
@@ -12,11 +12,10 @@ package org.eclipse.jdt.internal.compiler.ast;
 
 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 @@ public abstract class NameReference extends Reference implements InvocationSite,
        //no changeClass in java.
 public NameReference() {
        super();
-       bits |= TYPE | VARIABLE; // restrictiveFlag
+       bits |= Binding.TYPE | Binding.VARIABLE; // restrictiveFlag
        
 }
 public FieldBinding fieldBinding() {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/NormalAnnotation.java b/src/org/eclipse/jdt/internal/compiler/ast/NormalAnnotation.java
new file mode 100644 (file)
index 0000000..d8a720e
--- /dev/null
@@ -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);
+       }
+}
index d79b252..ea507f3 100644 (file)
@@ -12,6 +12,7 @@ package org.eclipse.jdt.internal.compiler.ast;
 
 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 class NullLiteral extends MagicLiteral {
         */ 
        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;
+       }
+       
        /**
         * 
         */
index 4574e0b..7ea85eb 100644 (file)
@@ -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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                                        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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                                        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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                        "\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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                        "\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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
        
                                {       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 abstract class OperatorExpression extends Expression implements OperatorI
 
        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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                //      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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                //      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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                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_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_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_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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                //      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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                //      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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                //      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 @@ public abstract class OperatorExpression extends Expression implements OperatorI
                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/src/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java b/src/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java
new file mode 100644 (file)
index 0000000..eed5a1f
--- /dev/null
@@ -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/src/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java b/src/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
new file mode 100644 (file)
index 0000000..8c4494f
--- /dev/null
@@ -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);
+       }
+}
index af7dd02..289eca2 100644 (file)
@@ -16,7 +16,10 @@ import org.eclipse.jdt.internal.compiler.flow.*;
 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 class QualifiedAllocationExpression extends AllocationExpression {
 
        public QualifiedAllocationExpression(TypeDeclaration anonymousType) {
                this.anonymousType = anonymousType;
+               anonymousType.allocation = this;
        }
 
        public FlowInfo analyseCode(
@@ -44,8 +48,9 @@ public class QualifiedAllocationExpression extends AllocationExpression {
                }
                
                // 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 @@ public class QualifiedAllocationExpression extends AllocationExpression {
                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 @@ public class QualifiedAllocationExpression extends AllocationExpression {
                                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 @@ public class QualifiedAllocationExpression extends AllocationExpression {
                
                // 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 class QualifiedAllocationExpression extends AllocationExpression {
        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 class QualifiedAllocationExpression extends AllocationExpression {
        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 @@ public class QualifiedAllocationExpression extends AllocationExpression {
                                        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 @@ public class QualifiedAllocationExpression extends AllocationExpression {
                }
                // 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 @@ public class QualifiedAllocationExpression extends AllocationExpression {
                                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 @@ public class QualifiedAllocationExpression extends AllocationExpression {
 
                        // 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 @@ public class QualifiedAllocationExpression extends AllocationExpression {
                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()) {
@@ -307,24 +332,17 @@ public class QualifiedAllocationExpression extends AllocationExpression {
                        if (targetEnclosing == null) {
                                scope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, (ReferenceBinding)receiverType);
                                return this.resolvedType = anonymousType.binding;
-                       } else  if (!enclosingInstanceType.isCompatibleWith(targetEnclosing)) {
-                               scope.problemReporter().typeMismatchErrorActualTypeExpectedType(enclosingInstance, enclosingInstanceType, targetEnclosing);
+                       } 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
        }
        
@@ -333,7 +351,13 @@ public class QualifiedAllocationExpression extends AllocationExpression {
                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++)
index 8afa15a..154a32b 100644 (file)
@@ -25,9 +25,11 @@ public class QualifiedNameReference extends NameReference {
        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 @@ public class QualifiedNameReference extends NameReference {
                this.sourceStart = sourceStart;
                this.sourceEnd = sourceEnd;
        }
+       
        public FlowInfo analyseAssignment(
                BlockScope currentScope,
                FlowContext flowContext,
@@ -49,11 +52,12 @@ public class QualifiedNameReference extends NameReference {
                // 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 @@ public class QualifiedNameReference extends NameReference {
                                        }
                                }
                                break;
-                       case LOCAL :
+                       case Binding.LOCAL :
                                // first binding is a local variable
                                LocalVariableBinding localBinding;
                                if (!flowInfo
@@ -77,6 +81,7 @@ public class QualifiedNameReference extends NameReference {
                                } 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 @@ public class QualifiedNameReference extends NameReference {
                                lastFieldBinding = otherBindings[i];
                                needValue = !otherBindings[i+1].isStatic();
                                if (needValue) {
-                                       manageSyntheticReadAccessIfNecessary(
+                                       manageSyntheticAccessIfNecessary(
                                                currentScope, 
                                                lastFieldBinding, 
                                                i == 0 
@@ -119,7 +124,7 @@ public class QualifiedNameReference extends NameReference {
                        } else {
                                lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
                        }
-                       manageSyntheticReadAccessIfNecessary(
+                       manageSyntheticAccessIfNecessary(
                                currentScope,
                                lastFieldBinding,
                                lastReceiverType,
@@ -166,7 +171,7 @@ public class QualifiedNameReference extends NameReference {
                } 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 @@ public class QualifiedNameReference extends NameReference {
 
                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 @@ public class QualifiedNameReference extends NameReference {
                                        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 @@ public class QualifiedNameReference extends NameReference {
                                } 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 @@ public class QualifiedNameReference extends NameReference {
                        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 @@ public class QualifiedNameReference extends NameReference {
                                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 @@ public class QualifiedNameReference extends NameReference {
                                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 @@ public class QualifiedNameReference extends NameReference {
                                                } 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 @@ public class QualifiedNameReference extends NameReference {
                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 @@ public class QualifiedNameReference extends NameReference {
                // 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 @@ public class QualifiedNameReference extends NameReference {
                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 @@ public class QualifiedNameReference extends NameReference {
                                }
                        }
                }
+               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 @@ public class QualifiedNameReference extends NameReference {
         * 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 @@ public class QualifiedNameReference extends NameReference {
                                        }
                                }
                                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 @@ public class QualifiedNameReference extends NameReference {
                                        }
                                }
                }
-
+                                               
                // 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 @@ public class QualifiedNameReference extends NameReference {
                                                } 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 @@ public class QualifiedNameReference extends NameReference {
                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 @@ public class QualifiedNameReference extends NameReference {
                        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,97 +681,50 @@ public class QualifiedNameReference extends NameReference {
                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);
-                       }
+
+               // 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);
                }
-       }
-       /*
-        * 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);
+               
+               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[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);
+                   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;
                        }
                }
@@ -697,24 +734,19 @@ public class QualifiedNameReference extends NameReference {
                if (fieldBinding.declaringClass != lastReceiverType
                        && !lastReceiverType.isArrayType()                      
                        && fieldBinding.declaringClass != null
-                       && fieldBinding.constant == NotAConstant
+                       && !fieldBinding.isConstantValue()
                        && ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
                                        && (fieldBinding != binding || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
-                                       && fieldBinding.declaringClass.id != T_Object)
+                                       && fieldBinding.declaringClass.id != T_JavaLangObject)
                                || !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);
-                       }
+                   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 @@ public class QualifiedNameReference extends NameReference {
                // 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 @@ public class QualifiedNameReference extends NameReference {
                                                        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 @@ public class QualifiedNameReference extends NameReference {
                                        }
                                        // 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;
index 592c433..67e95fc 100644 (file)
@@ -44,7 +44,7 @@ public class QualifiedSuperReference extends QualifiedThisReference {
                if (currentCompatibleType == null)
                        return null; // error case
 
-               if (currentCompatibleType.id == T_Object) {
+               if (currentCompatibleType.id == T_JavaLangObject) {
                        scope.problemReporter().cannotUseSuperInJavaLangObject(this);
                        return null;
                }
index 93e4c1c..9dcbb4c 100644 (file)
@@ -72,15 +72,19 @@ public class QualifiedThisReference extends ThisReference {
        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 @@ public class QualifiedThisReference extends ThisReference {
                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) {
index b37276b..d3518a0 100644 (file)
@@ -12,6 +12,7 @@ package org.eclipse.jdt.internal.compiler.ast;
 
 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 @@ public class QualifiedTypeReference extends TypeReference {
                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(){
index 41d498b..5a62bb6 100644 (file)
@@ -67,4 +67,19 @@ public abstract void generateCompoundAssignment(BlockScope currentScope, CodeStr
 
 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;
+}
+
 }
index ca74dae..74b3192 100644 (file)
@@ -18,7 +18,6 @@ import org.eclipse.jdt.internal.compiler.lookup.*;
 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 @@ public class ReturnStatement extends Statement {
                        }
                } 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 @@ public class ReturnStatement extends Statement {
                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 @@ public class ReturnStatement extends Statement {
                        expression.printExpression(0, output) ;
                return output.append(';');
        }
+       
        public void resolve(BlockScope scope) {
+               
                MethodScope methodScope = scope.methodScope();
                MethodBinding methodBinding;
                TypeBinding methodType =
@@ -196,6 +203,7 @@ public class ReturnStatement extends Statement {
                                        ? null 
                                        : methodBinding.returnType)
                                : VoidBinding;
+               TypeBinding expressionType;
                if (methodType == VoidBinding) {
                        // the expression should be null
                        if (expression == null)
@@ -208,25 +216,30 @@ public class ReturnStatement extends Statement {
                        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/src/org/eclipse/jdt/internal/compiler/ast/SingleMemberAnnotation.java b/src/org/eclipse/jdt/internal/compiler/ast/SingleMemberAnnotation.java
new file mode 100644 (file)
index 0000000..ff9881f
--- /dev/null
@@ -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);
+       }
+}
index 908732b..eb937a6 100644 (file)
@@ -19,11 +19,12 @@ import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 
 public class SingleNameReference extends NameReference implements OperatorIds {
+    
        public char[] token;
-
        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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                // 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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                                                        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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                        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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                                        }
                                }
                                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 class SingleNameReference extends NameReference implements OperatorIds {
        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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                                        }
                                }
                                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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                }
                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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                                && ((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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                                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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                        }
                } 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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                                                        } 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 class SingleNameReference extends NameReference implements OperatorIds {
         */
        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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                                        }
                                }
                                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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                }
                // 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 class SingleNameReference extends NameReference implements OperatorIds {
        
        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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                                                }
                                        }
                                }
+                               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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                                                        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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                
                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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                //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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
                        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 class SingleNameReference extends NameReference implements OperatorIds {
        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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
        
                                        // 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 @@ public class SingleNameReference extends NameReference implements OperatorIds {
        
                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;
+       }       
 }
index 4d29467..55655f0 100644 (file)
@@ -25,22 +25,23 @@ public class SingleTypeReference extends TypeReference {
                
        }
 
-       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 class SingleTypeReference extends TypeReference {
 
        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) {
index 2e240f7..591165d 100644 (file)
@@ -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 @@ public abstract class Statement extends ASTNode {
                }
                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 class Statement extends ASTNode {
 
        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;
        }
 
 }
index 77ee9cc..1ea7892 100644 (file)
@@ -18,7 +18,7 @@ import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
  */
 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
index 59b697b..754efdf 100644 (file)
@@ -44,8 +44,10 @@ public abstract class SubRoutineStatement extends Statement {
                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() {
index a877d12..9519a34 100644 (file)
@@ -54,7 +54,7 @@ public class SuperReference extends ThisReference {
                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;
                }
index 65cddb1..6050f9f 100644 (file)
 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 class SwitchStatement extends Statement {
        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 class SwitchStatement extends Statement {
        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 @@ public class SwitchStatement extends Statement {
                                }
                        }
                        // 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 class SwitchStatement extends Statement {
        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);
index 2a45c54..b49d6ad 100644 (file)
@@ -41,6 +41,8 @@ public class SynchronizedStatement extends SubRoutineStatement {
                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 @@ public class SynchronizedStatement extends SubRoutineStatement {
         * @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 @@ public class SynchronizedStatement extends SubRoutineStatement {
                        this.anyExceptionLabelsCount = 0;
                }
                int pc = codeStream.position;
-
+       
                // generate the synchronization expression
                expression.generateCode(scope, codeStream, true);
                if (block.isEmptyBlock()) {
@@ -97,7 +99,7 @@ public class SynchronizedStatement extends SubRoutineStatement {
                        // 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 @@ public class SynchronizedStatement extends SubRoutineStatement {
                        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 @@ public class SynchronizedStatement extends SubRoutineStatement {
                //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);
        }
 
index 78ccdfa..c81c876 100644 (file)
@@ -97,6 +97,10 @@ public class ThisReference extends Reference {
                return true ;
        }
 
+       public int nullStatus(FlowInfo flowInfo) {
+               return FlowInfo.NON_NULL;
+       }
+       
        public StringBuffer printExpression(int indent, StringBuffer output){
        
                if (this.isImplicitThis()) return output;
index dac8920..515d313 100644 (file)
@@ -68,7 +68,7 @@ public class ThrowStatement extends Statement {
                        // 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) {
index 14dc78f..a3bd34d 100644 (file)
@@ -23,8 +23,8 @@ public TrueLiteral(int s , int e) {
        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 computeConstant() {
  */ 
 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) {
index bda4130..9101bce 100644 (file)
@@ -83,7 +83,7 @@ public class TryStatement extends SubRoutineStatement {
                                        .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 @@ public class TryStatement extends SubRoutineStatement {
                                                .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 @@ public class TryStatement extends SubRoutineStatement {
                                "(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 @@ public class TryStatement extends SubRoutineStatement {
 
                // 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 @@ public class TryStatement extends SubRoutineStatement {
         * returnAddress is only allocated if jsr is allowed
         */
        public void generateCode(BlockScope currentScope, CodeStream codeStream) {
-
                if ((bits & IsReachableMASK) == 0) {
                        return;
                }
@@ -260,15 +260,11 @@ public class TryStatement extends SubRoutineStatement {
                        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 @@ public class TryStatement extends SubRoutineStatement {
                                        // 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 @@ public class TryStatement extends SubRoutineStatement {
                                        }
                                }
                        }
+                       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 @@ public class TryStatement extends SubRoutineStatement {
                                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 @@ public class TryStatement extends SubRoutineStatement {
                }
                // 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 @@ public class TryStatement extends SubRoutineStatement {
                                        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 @@ public class TryStatement extends SubRoutineStatement {
                                                                        AccDefault,
                                                                        false);
                                                        finallyScope.addLocalVariable(this.secretReturnValue);
-                                                       this.secretReturnValue.constant = NotAConstant; // not inlinable
+                                                       this.secretReturnValue.setConstant(NotAConstant); // not inlinable
                                                }
                                        }
                                }
@@ -518,17 +505,21 @@ public class TryStatement extends SubRoutineStatement {
                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];
index b6ba6f1..580877d 100644 (file)
@@ -15,6 +15,7 @@ import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.*;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
+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 class TypeDeclaration
 
        public int modifiers = AccDefault;
        public int modifiersSourceStart;
+       public Annotation[] annotations;
        public char[] name;
        public TypeReference superclass;
        public TypeReference[] superInterfaces;
@@ -46,12 +48,17 @@ public class TypeDeclaration
        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 @@ public class TypeDeclaration
                                                        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 @@ public class TypeDeclaration
                return this.compilationResult;
        }
 
-       public ConstructorDeclaration createsInternalConstructor(
+       public ConstructorDeclaration createDefaultConstructor(
                boolean needExplicitConstructorCall,
                boolean needToInsert) {
 
@@ -312,7 +319,7 @@ public class TypeDeclaration
                //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 @@ public class TypeDeclaration
        }
        
        // 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 @@ public class TypeDeclaration
                                        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 @@ public class TypeDeclaration
                                        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 @@ public class TypeDeclaration
                                        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 @@ public class TypeDeclaration
                }
                // 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 @@ public class TypeDeclaration
                        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 @@ public class TypeDeclaration
                //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 @@ public class TypeDeclaration
                }
                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 class TypeDeclaration
        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 class TypeDeclaration
        public StringBuffer printStatement(int tab, StringBuffer output) {
                return print(tab, output);
        }
+       
 
-       public void resolve() {
 
-               if (this.binding == null) {
+       public void resolve() {
+               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 @@ public class TypeDeclaration
                                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 @@ public class TypeDeclaration
                        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 @@ public class TypeDeclaration
                        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 (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 (memberTypes != null) {
-                                       int memberTypesLength = memberTypes.length;
-                                       for (int i = 0; i < memberTypesLength; i++)
-                                               memberTypes[i].traverse(visitor, scope);
+                               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 (fields != null) {
-                                       int fieldsLength = fields.length;
-                                       for (int i = 0; i < fieldsLength; i++) {
+                               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 @@ public class TypeDeclaration
                        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 (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 (fields != null) {
-                                       int fieldsLength = fields.length;
-                                       for (int i = 0; i < fieldsLength; i++) {
+                               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/src/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java b/src/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java
new file mode 100644 (file)
index 0000000..bfa7e3f
--- /dev/null
@@ -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
index 2e8e10c..5865269 100644 (file)
@@ -77,11 +77,21 @@ public static final TypeReference baseTypeReference(int baseType, int dim) {
                        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 abstract char [][] getTypeName() ;
 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 @@ protected void reportDeprecatedType(Scope scope) {
        scope.problemReporter().deprecatedType(this.resolvedType, this);
 }
 public abstract void traverse(ASTVisitor visitor, ClassScope classScope);
+public abstract void traverse(ASTVisitor visitor, BlockScope classScope);
 }
index 1e3a2fc..7e38c26 100644 (file)
@@ -71,7 +71,7 @@ public class UnaryExpression extends OperatorExpression {
                }
                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 @@ public class UnaryExpression extends OperatorExpression {
                                }
                                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 @@ public class UnaryExpression extends OperatorExpression {
                                // - <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 @@ public class UnaryExpression extends OperatorExpression {
                                } 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 @@ public class UnaryExpression extends OperatorExpression {
                        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 @@ public class UnaryExpression extends OperatorExpression {
                // (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 @@ public class UnaryExpression extends OperatorExpression {
                                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 @@ public class UnaryExpression extends OperatorExpression {
                        this.constant =
                                Constant.computeConstantOperation(
                                        this.expression.constant,
-                                       expressionTypeId,
+                                       expressionTypeID,
                                        (bits & OperatorMASK) >> OperatorSHIFT);
                } else {
                        this.constant = Constant.NotAConstant;
@@ -284,7 +291,7 @@ public class UnaryExpression extends OperatorExpression {
                }
                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;
        }
index b7e1441..fc7be36 100644 (file)
@@ -55,22 +55,23 @@ public class WhileStatement extends Statement {
                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 @@ public class WhileStatement extends Statement {
                        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 @@ public class WhileStatement extends Statement {
                        // 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 @@ public class WhileStatement extends Statement {
                FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
                                loopingContext.initsOnBreak, 
                                isConditionOptimizedTrue, 
-                               postCondInfo.initsWhenFalse(), 
+                               exitBranch,
                                isConditionOptimizedFalse,
                                !isConditionTrue /*while(true); unreachable(); */);
                mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
@@ -178,9 +181,7 @@ public class WhileStatement extends Statement {
                        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 class WhileStatement extends Statement {
        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/src/org/eclipse/jdt/internal/compiler/ast/Wildcard.java b/src/org/eclipse/jdt/internal/compiler/ast/Wildcard.java
new file mode 100644 (file)
index 0000000..8c99f7d
--- /dev/null
@@ -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);
+       }
+}
index 127b0cd..57b09e0 100644 (file)
@@ -59,5 +59,14 @@ public interface ClassFileConstants extends IConstants {
        
        // 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;
 }
index 6899fa0..fea4ef4 100644 (file)
@@ -14,33 +14,88 @@ import java.io.File;
 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 {
-       private int constantPoolCount;
-       private int[] constantPoolOffsets;
-       private long version;
+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 char[] superclassName;
-       private int interfacesCount;
-       private char[][] interfaceNames;
-       private int fieldsCount;
+       private int classNameIndex;
+       private int constantPoolCount;
+       private int[] constantPoolOffsets;
        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 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit
                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 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit
 }
 
 /**
- * @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,192 @@ public ClassFileReader(byte classFileBytes[], char[] fileName) throws ClassForma
 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 = decodeElementValueForJavaLangAnnotationTarget(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' :
+                       readOffset += 2;
+                       int utf8Offset = this.constantPoolOffsets[u2At(readOffset)];
+                       char[] constName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+                       readOffset += 2;
+                       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' :
+                       readOffset += 2;
+                       int utf8Offset = this.constantPoolOffsets[u2At(readOffset)];
+                       char[] constName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+                       readOffset += 2;
+                       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 = decodeElementValueForJavaLangAnnotationRetention(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);
+       }
+}
 /**
  * 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 +533,14 @@ public IBinaryField[] getFields() {
        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 +578,25 @@ public char[] getInnerSourceName() {
 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 +663,7 @@ public IBinaryMethod[] getMethods() {
  */
 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 +688,9 @@ public char[] getName() {
 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 +699,56 @@ public char[] getSuperclassName() {
 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();
+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;
        }
-       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();
+
+       while (index1 < length1) {
+               if (!currentFieldInfos[index1++].isSynthetic()) return true;
        }
-       return classFileReader;
+       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;
 
-/**
- * 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$
+       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;
+       }
 
-       print.flush();
-       return out.toString();
+       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 +792,11 @@ public boolean hasStructuralChanges(byte[] newBytes, boolean orderRequired, bool
                // 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 +890,11 @@ public boolean hasStructuralChanges(byte[] newBytes, boolean orderRequired, bool
                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 +925,23 @@ private boolean hasStructuralFieldChanges(FieldInfo currentFieldInfo, FieldInfo
                                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 +979,75 @@ private void initialize() throws ClassFormatException {
                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();
+}
 }
index fd3f30e..019ff5e 100644 (file)
@@ -10,6 +10,7 @@ package org.eclipse.jdt.internal.compiler.classfmt;
 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;
index 26392d8..b986492 100644 (file)
@@ -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.IntConstant;
 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 int accessFlags;
+       private int attributeBytes;
        private Constant constant;
-       private boolean isDeprecated;
-       private boolean isSynthetic;
        private int[] constantPoolOffsets;
-       private int accessFlags;
+       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 @@ public FieldInfo (byte classFileBytes[], int offsets[], int offset) {
        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 @@ public Constant getConstant() {
        }
        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 @@ public Constant getConstant() {
  * @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 @@ public char[] getName() {
        }
        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 @@ public char[] getName() {
  * @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 @@ public Object getWrappedConstantValue() {
                                case T_long :
                                        this.wrappedConstantValue = new Long(fieldConstant.longValue());
                                        break;
-                               case T_String :
+                               case T_JavaLangString :
                                        this.wrappedConstantValue = fieldConstant.stringValue();
                        }
                }
@@ -164,6 +269,18 @@ public boolean hasConstant() {
        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 @@ private void readConstantAttribute() {
                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 @@ public String toString() {
                .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();
-}
-
 }
index c9255be..7a27b96 100644 (file)
  *******************************************************************************/
 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 @@ public MethodInfo (byte classFileBytes[], int offsets[], int offset) {
        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 @@ public char[][] getExceptionTypeNames() {
        }
        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 @@ public char[][] getExceptionTypeNames() {
  * @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 @@ public char[] getMethodDescriptor() {
  * @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 @@ public char[] getSelector() {
        }
        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 isConstructor() {
 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 @@ private void readExceptionAttributes() {
                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 int sizeInBytes() {
 }
 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 @@ public String toString() {
                                + ((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();
-}
 }
index 577b9bd..a49ff00 100644 (file)
 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$
 }
index 4d7a6ef..343c4e6 100644 (file)
@@ -49,7 +49,9 @@ public class CodeStream implements OperatorIds, ClassFileConstants, Opcodes, Bas
        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 class CodeStream implements OperatorIds, ClassFileConstants, Opcodes, Bas
        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 @@ public final void anewarray(TypeBinding typeBinding) {
        }
        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 @@ final public void castore() {
        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 @@ public void generateClassLiteralAccessForType(TypeBinding accessedType, FieldBin
                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$
-       }
-       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();
+               endLabel = new Label(this);
+               if (syntheticFieldBinding != null) { // non interface case
+                       this.getstatic(syntheticFieldBinding);
+                       this.dup();
+                       this.ifnonnull(endLabel);
+                       this.pop();
+               }
 
-       if (syntheticFieldBinding != null) { // non interface case
-               this.dup();
-               this.putstatic(syntheticFieldBinding);
+               /* 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.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 @@ final public void generateCodeAttributeForProblemMethod(String problemMessage) {
        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 @@ public void generateImplicitConversion(int implicitConversionCode) {
                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 @@ public void generateOuterAccess(Object[] mappingSequence, ASTNode invocationSite
  * @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 @@ public void generateSyntheticOuterArgumentValues(BlockScope currentScope, Refere
 /**
  * @param accessBinding the access method binding to generate
  */
-public void generateSyntheticBodyForConstructorAccess(SyntheticAccessMethodBinding accessBinding) {
+public void generateSyntheticBodyForConstructorAccess(SyntheticMethodBinding accessBinding) {
 
        initializeMaxLocals(accessBinding);
 
@@ -1804,8 +1836,14 @@ public void generateSyntheticBodyForConstructorAccess(SyntheticAccessMethodBindi
        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 @@ public void generateSyntheticBodyForConstructorAccess(SyntheticAccessMethodBindi
                        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 @@ public void generateSyntheticBodyForConstructorAccess(SyntheticAccessMethodBindi
        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 @@ public void generateSyntheticBodyForFieldReadAccess(SyntheticAccessMethodBinding
        } 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 @@ public void generateSyntheticBodyForFieldWriteAccess(SyntheticAccessMethodBindin
        }
        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 @@ public void generateSyntheticBodyForMethodAccess(SyntheticAccessMethodBinding ac
                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 @@ public void generateSyntheticBodyForMethodAccess(SyntheticAccessMethodBinding ac
                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 @@ public void generateSyntheticBodyForMethodAccess(SyntheticAccessMethodBinding ac
        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 byte[] getContents() {
 }
 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 @@ public void init(ClassFile targetClassFile) {
                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,41 +3074,50 @@ public void init(ClassFile targetClassFile) {
  */
 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
-                               }
-                       }
-                       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++;
-                                       }
-                               }
+       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
                        }
                }
-               TypeBinding[] arguments;
-               if ((arguments = methodBinding.parameters) != null) {
-                       for (int i = 0, max = arguments.length; i < max; i++) {
+               SyntheticArgumentBinding syntheticArguments[];
+               if ((syntheticArguments = methodBinding.declaringClass.syntheticOuterLocalVariables()) != null) {
+                       for (int i = 0, max = syntheticArguments.length; i < max; i++) {
                                TypeBinding argType;
-                               if (((argType = arguments[i]) == LongBinding) || (argType == DoubleBinding)) {
-                                       maxLocals += 2;
+                               if (((argType = syntheticArguments[i].type) == LongBinding) || (argType == DoubleBinding)) {
+                                       this.maxLocals += 2;
                                } else {
-                                       maxLocals++;
+                                       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)) {
+                               this.maxLocals += 2;
+                       } else {
+                               this.maxLocals++;
+                       }
+               }
+       }
 }
 /**
  * This methods searches for an existing entry inside the pcToSourceMap table with a pc equals to @pc.
@@ -2792,45 +3165,53 @@ final public void instance_of(TypeBinding typeBinding) {
        }
        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 @@ final public void invokeinterface(MethodBinding methodBinding) {
 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 @@ final public void invokestatic(MethodBinding methodBinding) {
  * 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--;
-}
-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();
+       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 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();
-       }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokestatic;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangStringValueOf(typeID));
+       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;
+       }
+       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$
-       countLabels = 0;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
+       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;
+       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));
+       }
+       stackDepth += returnTypeSize - argCount;
+       if (stackDepth > stackMax) {
+               stackMax = stackDepth;
        }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokevirtual;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangThrowableGetMessage());
 }
 final public void invokevirtual(MethodBinding methodBinding) {
        if (DEBUG) System.out.println(position + "\t\tinvokevirtual:"+methodBinding); //$NON-NLS-1$
@@ -3433,13 +4084,13 @@ final public void lconst_1() {
        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 @@ final public void ldc(float constant) {
                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(float constant) {
        }
 }
 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 @@ final public void ldc(int constant) {
                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(int constant) {
        }
 }
 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 @@ final public void ldc(String constant) {
                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 @@ final public void ldc(String constant) {
                        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 @@ final public void ldc(String constant) {
                }
                // 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 @@ final public void ldc(String constant) {
                        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 @@ final public void ldc(String constant) {
                                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 @@ final public void multianewarray(TypeBinding typeBinding, int dimensions) {
        }
        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 @@ final public void new_(TypeBinding typeBinding) {
        }
        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 @@ final public void newarray(int array_Type) {
        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 @@ public void newJavaLangError() {
        }
        position++;
        bCodeStream[classFileOffset++] = OPC_new;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangError());
+       writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangErrorConstantPoolName));
 }
 
 public void newJavaLangAssertionError() {
@@ -4374,9 +5054,22 @@ public void newJavaLangAssertionError() {
        }
        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 @@ public void newNoClassDefFoundError() {
        }
        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 @@ public void newWrapperFor(int typeID) {
        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 pop2() {
 }
 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 @@ public void recordPositionsFrom(int startPC, int sourcePos) {
                                        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 recordPositionsFrom(int startPC, int sourcePos) {
  */
 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
index 66a2f72..a4a4509 100644 (file)
  *******************************************************************************/
 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 class ConstantPool implements ClassFileConstants, TypeIds {
        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 @@ public class ConstantPool implements ClassFileConstants, TypeIds {
        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 class ConstantPool implements ClassFileConstants, TypeIds {
 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 @@ public byte[] dumpBytes() {
        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;
-       }
-       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;
-                       }       
+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 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;
-                       }                       
+       CharArrayCache value2 = (CharArrayCache) value.get(name);
+       if (value2 == null) {
+               return -1;
        }
-       return -1;
+       return value2.get(signature);
 }
-/**
- * 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;
+private int getFromNameAndTypeCache(char[] name, char[] signature) {
+       CharArrayCache value = (CharArrayCache) this.nameAndTypeCacheForFieldsAndMethods.get(name);
+       if (value == null) {
+               return -1;
        }
-       return -1;
+       return value.get(signature);
 }
 public int literalIndex(byte[] utf8encoding, char[] stringCharArray) {
        int index;
@@ -908,35 +557,20 @@ public int literalIndex(String stringConstant) {
  */
 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);
-               }
-       } 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);
+       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());
                }
+               writeU1(FieldRefTag);
+               writeU2(classIndex);
+               writeU2(nameAndTypeIndex);
        }
        return index;
 }
@@ -951,99 +585,54 @@ public int literalIndex(FieldBinding aFieldBinding) {
  */
 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);
-                       }
-               }
-       } 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);
-                       }
+       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());
                }
+               // 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,1979 +640,236 @@ public int literalIndex(TypeBinding aTypeBinding) {
                        // 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++;
-                       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);
+               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;
 }
-/**
- * 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>
- */
-public int literalIndexForFields(int nameIndex, int typeIndex, FieldBinding key) {
-       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);
+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;
 }
-/**
- * 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;
+public int literalIndexForMethod(char[] selector, char[] signature) {
+       int index = getFromNameAndTypeCache(selector, signature);
+       if (index == -1) {
                // The entry doesn't exit yet
-               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangBooleanConstantPoolName);
-               index = wellKnownTypes[JAVA_LANG_BOOLEAN_TYPE] = currentIndex++;
+               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(ClassTag);
-               // Then add the 8 bytes representing the long
+               writeU1(NameAndTypeTag);
                writeU2(nameIndex);
+               writeU2(typeIndex);
        }
        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;
+public int literalIndexForField(char[] declaringClass, char[] name, char[] signature) {
+       int index = getFromCache(declaringClass, name, signature);
+       if (index == -1) {
                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);
+               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());
+                       }
+                       writeU1(ClassTag);
+                       // Then add the 8 bytes representing the long
                        writeU2(nameIndex);
-                       writeU2(typeIndex);
                }
-               index = wellKnownFields[TYPE_BOOLEAN_FIELD] = currentIndex++;
+               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);
-               writeU2(nameAndTypeIndex);
+               // The write the nameAndType index
+               writeU2(nameAndTypeIndex);              
        }
        return index;
 }
 /**
- * This method returns the index into the constantPool corresponding to the type descriptor.
+ * This method returns the index into the constantPool corresponding 
+ * nameAndType constant with nameIndex, typeIndex.
  *
- * @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 literalIndexForJavaLangByte() {
+private int literalIndexForFields(int nameIndex, int typeIndex, char[] name, char[] signature) {
        int index;
-       if ((index = wellKnownTypes[JAVA_LANG_BYTE_TYPE]) == 0) {
-               int nameIndex;
+       if ((index = getFromNameAndTypeCache(name, signature)) == -1) {
                // The entry doesn't exit yet
-               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangByteConstantPoolName);
-               index = wellKnownTypes[JAVA_LANG_BYTE_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);
+               writeU2(typeIndex);
        }
        return index;
 }
 /**
- * This method returns the index into the constantPool 
- * corresponding to the field binding aFieldBinding.
+ * This method returns the index into the constantPool corresponding to the type descriptor.
  *
+ * @param stringCharArray char[]
  * @return <CODE>int</CODE>
  */
-public int literalIndexForJavaLangByteTYPE() {
+public int literalIndexForLdc(char[] stringCharArray) {
        int index;
-       if ((index = wellKnownFields[TYPE_BYTE_FIELD]) == 0) {
-               int nameAndTypeIndex;
-               int classIndex;
+       if ((index = stringCache.get(stringCharArray)) < 0) {
+               int stringIndex;
                // 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);
+               if ((stringIndex = UTF8Cache.get(stringCharArray)) < 0) {
+                       // The entry doesn't exit yet
+                       // Write the tag first
+                       writeU1(Utf8Tag);
+                       // Then the size of the stringName array
+                       int savedCurrentOffset = currentOffset;
+                       if (currentOffset + 2 >= poolContent.length) {
+                               // we need to resize the poolContent array because we won't have
+                               // enough space to write the length
+                               resizePoolContents(2);
+                       }
+                       currentOffset += 2;
+                       int length = 0;
+                       for (int i = 0; i < stringCharArray.length; i++) {
+                               char current = stringCharArray[i];
+                               if ((current >= 0x0001) && (current <= 0x007F)) {
+                                       // we only need one byte: ASCII table
+                                       writeU1(current);
+                                       length++;
+                               } else
+                                       if (current > 0x07FF) {
+                                               // we need 3 bytes
+                                               length += 3;
+                                               writeU1(0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = 1110 0000
+                                               writeU1(0x80 | ((current >> 6) & 0x3F)); // 0x80 = 1000 0000
+                                               writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
+                                       } else {
+                                               // we can be 0 or between 0x0080 and 0x07FF
+                                               // In that case we only need 2 bytes
+                                               length += 2;
+                                               writeU1(0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = 1100 0000
+                                               writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
+                                       }
+                       }
+                       if (length >= 65535) {
+                               currentOffset = savedCurrentOffset - 1;
+                               return -1;
+                       }
+                       stringIndex = UTF8Cache.put(stringCharArray, currentIndex++);
+                       // Now we know the length that we have to write in the constant pool
+                       // we use savedCurrentOffset to do that
+                       if (length > 65535) {
+                               return 0;
+                       }
+                       poolContent[savedCurrentOffset] = (byte) (length >> 8);
+                       poolContent[savedCurrentOffset + 1] = (byte) length;
                }
-               index = wellKnownFields[TYPE_BYTE_FIELD] = currentIndex++;
+               index = stringCache.put(stringCharArray, currentIndex++);
                if (index > 0xFFFF){
                        this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
                }
-               writeU1(FieldRefTag);
-               writeU2(classIndex);
-               writeU2(nameAndTypeIndex);
+               // Write the tag first
+               writeU1(StringTag);
+               // Then the string index
+               writeU2(stringIndex);
        }
        return index;
 }
 /**
- * This method returns the index into the constantPool corresponding to the type descriptor.
+ * This method returns the index into the constantPool corresponding 
+ * nameAndType constant with nameIndex, typeIndex.
  *
+ * @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 literalIndexForJavaLangCharacter() {
+public int literalIndexForMethods(int nameIndex, int typeIndex, char[] selector, char[] signature) {
        int index;
-       if ((index = wellKnownTypes[JAVA_LANG_CHARACTER_TYPE]) == 0) {
-               int nameIndex;
+       if ((index = getFromNameAndTypeCache(selector, signature)) == -1) {
                // The entry doesn't exit yet
-               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangCharacterConstantPoolName);
-               index = wellKnownTypes[JAVA_LANG_CHARACTER_TYPE] = currentIndex++;
+               index = putInNameAndTypeCache(selector, 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);
+               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 {
+               value.put(key2, index);
        }
        return index;
 }
 /**
- * This method returns the index into the constantPool 
- * corresponding to the field binding aFieldBinding.
- *
- * @return <CODE>int</CODE>
+ * @param key1
+ * @param key2
+ * @param key3
+ * @param index
+ * @return the given index
  */
-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);
+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 = 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);
-       }
-       return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @param stringCharArray char[]
- * @return <CODE>int</CODE>
- */
-public int literalIndexForLdc(char[] stringCharArray) {
-       int index;
-       if ((index = stringCache.get(stringCharArray)) < 0) {
-               int stringIndex;
-               // The entry doesn't exit yet
-               if ((stringIndex = UTF8Cache.get(stringCharArray)) < 0) {
-                       // The entry doesn't exit yet
-                       // Write the tag first
-                       writeU1(Utf8Tag);
-                       // Then the size of the stringName array
-                       int savedCurrentOffset = currentOffset;
-                       if (currentOffset + 2 >= poolContent.length) {
-                               // we need to resize the poolContent array because we won't have
-                               // enough space to write the length
-                               resizePoolContents(2);
-                       }
-                       currentOffset += 2;
-                       int length = 0;
-                       for (int i = 0; i < stringCharArray.length; i++) {
-                               char current = stringCharArray[i];
-                               if ((current >= 0x0001) && (current <= 0x007F)) {
-                                       // we only need one byte: ASCII table
-                                       writeU1(current);
-                                       length++;
-                               } else
-                                       if (current > 0x07FF) {
-                                               // we need 3 bytes
-                                               length += 3;
-                                               writeU1(0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = 1110 0000
-                                               writeU1(0x80 | ((current >> 6) & 0x3F)); // 0x80 = 1000 0000
-                                               writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
-                                       } else {
-                                               // we can be 0 or between 0x0080 and 0x07FF
-                                               // In that case we only need 2 bytes
-                                               length += 2;
-                                               writeU1(0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = 1100 0000
-                                               writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
-                                       }
-                       }
-                       if (length >= 65535) {
-                               currentOffset = savedCurrentOffset - 1;
-                               return -1;
-                       }
-                       stringIndex = UTF8Cache.put(stringCharArray, currentIndex++);
-                       // Now we know the length that we have to write in the constant pool
-                       // we use savedCurrentOffset to do that
-                       if (length > 65535) {
-                               return 0;
-                       }
-                       poolContent[savedCurrentOffset] = (byte) (length >> 8);
-                       poolContent[savedCurrentOffset + 1] = (byte) length;
-               }
-               index = stringCache.put(stringCharArray, currentIndex++);
-               if (index > 0xFFFF){
-                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
-               }
-               // Write the tag first
-               writeU1(StringTag);
-               // Then the string index
-               writeU2(stringIndex);
-       }
-       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 = 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);
-               }
-       } 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);
-               }
-       }
-       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 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);
-               }
-               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 @@ public void resetForClinit(int constantPoolIndex, int constantPoolOffset) {
        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/src/org/eclipse/jdt/internal/compiler/codegen/FieldNameAndTypeCache.java b/src/org/eclipse/jdt/internal/compiler/codegen/FieldNameAndTypeCache.java
deleted file mode 100644 (file)
index 0982a06..0000000
+++ /dev/null
@@ -1,161 +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;
-
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
-
-public class FieldNameAndTypeCache {
-       public FieldBinding keyTable[];
-       public int valueTable[];
-       int elementSize;
-       int threshold;
-/**
- * Constructs a new, empty hashtable. A default capacity is used.
- * Note that the hashtable will automatically grow when it gets full.
- */
-public FieldNameAndTypeCache() {
-       this(13);
-}
-/**
- * Constructs a new, empty hashtable with the specified initial
- * capacity.
- * @param initialCapacity int
- *     the initial number of buckets
- */
-public FieldNameAndTypeCache(int initialCapacity) {
-       this.elementSize = 0;
-       this.threshold = (int) (initialCapacity * 0.66f);
-       this.keyTable = new FieldBinding[initialCapacity];
-       this.valueTable = new int[initialCapacity];
-}
-/**
- * Clears the hash table so that it has no more elements in it.
- */
-public void clear() {
-       for (int i = keyTable.length; --i >= 0;) {
-               keyTable[i] = null;
-               valueTable[i] = 0;
-       }
-       elementSize = 0;
-}
-/** Returns true if the collection contains an element for the key.
- *
- * @param key char[] the key that we are looking for
- * @return boolean
- */
-public boolean containsKey(FieldBinding key) {
-       int index = hashCode(key);
-       while (keyTable[index] != null) {
-               if (equalsForNameAndType(keyTable[index], key))
-                       return true;
-               index = (index + 1) % keyTable.length;
-       }
-       return false;
-}
-/**
- * Return true if the two field binding are consider like equals.
- */
-public boolean equalsForNameAndType(FieldBinding field1, FieldBinding field2) {
-       return ((field1.type == field2.type) && CharOperation.equals(field1.name, field2.name));
-}
-/** Gets the object associated with the specified key in the
- * hashtable.
- * @param key <CODE>char[]</CODE> the specified key
- * @return int the element for the key or -1 if the key is not
- *     defined in the hash table.
- */
-public int get(FieldBinding key) {
-       int index = hashCode(key);
-       while (keyTable[index] != null) {
-               if (equalsForNameAndType(keyTable[index], key))
-                       return valueTable[index];
-               index = (index + 1) % keyTable.length;
-       }
-       return -1;
-}
-/**
- * Return the hashcode for the key parameter
- *
- * @param key org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- * @return int
- */
-public int hashCode(FieldBinding key) {
-       return ((CharOperation.hashCode(key.name) + key.type.hashCode()) & 0x7FFFFFFF) % keyTable.length;
-}
-/**
- * Puts the specified element into the hashtable, using the specified
- * key.  The element may be retrieved by doing a get() with the same key.
- * The key and the element cannot be null. 
- * 
- * @param key <CODE>Object</CODE> the specified key in the hashtable
- * @param value <CODE>int</CODE> the specified element
- * @return int the old value of the key, or -1 if it did not have one.
- */
-public int put(FieldBinding key, int value) { 
-       int index = hashCode(key);
-       while (keyTable[index] != null) {
-               if (equalsForNameAndType(keyTable[index], key))
-                       return valueTable[index] = value;
-               index = (index + 1) % keyTable.length;
-       }
-       keyTable[index] = key;
-       valueTable[index] = value;
-
-       // assumes the threshold is never equal to the size of the table
-       if (++elementSize > threshold)
-               rehash();
-       return value;
-}
-/**
- * Rehashes the content of the table into a bigger table.
- * This method is called automatically when the hashtable's
- * size exceeds the threshold.
- */
-private void rehash() {
-       FieldNameAndTypeCache newHashtable = new FieldNameAndTypeCache(keyTable.length * 2);
-       for (int i = keyTable.length; --i >= 0;)
-               if (keyTable[i] != null)
-                       newHashtable.put(keyTable[i], valueTable[i]);
-
-       this.keyTable = newHashtable.keyTable;
-       this.valueTable = newHashtable.valueTable;
-       this.threshold = newHashtable.threshold;
-}
-/**
- * Returns the number of elements contained in the hashtable.
- *
- * @return <CODE>int</CODE> The size of the table
- */
-public int size() {
-       return elementSize;
-}
-/**
- * Converts to a rather lengthy String.
- *
- * @return String the ascii representation of the receiver
- */
-public String toString() {
-       int max = size();
-       StringBuffer buf = new StringBuffer();
-       buf.append("{"); //$NON-NLS-1$
-       for (int i = 0; i < max; ++i) {
-               if (keyTable[i] != null) {
-                       buf.append(keyTable[i]).append("->").append(valueTable[i]); //$NON-NLS-1$
-               }
-               if (i < max) {
-                       buf.append(", "); //$NON-NLS-1$
-               }
-       }
-       buf.append("}"); //$NON-NLS-1$
-       return buf.toString();
-}
-}
diff --git a/src/org/eclipse/jdt/internal/compiler/codegen/MethodNameAndTypeCache.java b/src/org/eclipse/jdt/internal/compiler/codegen/MethodNameAndTypeCache.java
deleted file mode 100644 (file)
index 2ab3da3..0000000
+++ /dev/null
@@ -1,162 +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;
-
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
-
-public class MethodNameAndTypeCache {
-       public MethodBinding keyTable[];
-       public int valueTable[]; 
-       int elementSize;
-       int threshold;
-/**
- * Constructs a new, empty hashtable. A default capacity is used.
- * Note that the hashtable will automatically grow when it gets full.
- */
-public MethodNameAndTypeCache() {
-       this(13);
-}
-/**
- * Constructs a new, empty hashtable with the specified initial
- * capacity.
- * @param initialCapacity int
- *     the initial number of buckets
- */
-public MethodNameAndTypeCache(int initialCapacity) {
-       this.elementSize = 0;
-       this.threshold = (int) (initialCapacity * 0.66f);
-       this.keyTable = new MethodBinding[initialCapacity];
-       this.valueTable = new int[initialCapacity];
-}
-/**
- * Clears the hash table so that it has no more elements in it.
- */
-public void clear() {
-       for (int i = keyTable.length; --i >= 0;) {
-               keyTable[i] = null;
-               valueTable[i] = 0;
-       }
-       elementSize = 0;
-}
-/** Returns true if the collection contains an element for the key.
- *
- * @param key char[] the key that we are looking for
- * @return boolean
- */
-public boolean containsKey(MethodBinding key) {
-       int index = hashCode(key);
-       while (keyTable[index] != null) {
-               if (equalsForNameAndType(keyTable[index], key))
-                       return true;
-               index = (index + 1) % keyTable.length;
-       }
-       return false;
-}
-/**
- * Returns true if the two methodBinding are consider to be equal for the name and type
- * purpose
- */
-public boolean equalsForNameAndType(MethodBinding method1, MethodBinding method2) {
-       return CharOperation.equals(method1.selector, method2.selector) && CharOperation.equals(method1.signature(), method2.signature());
-}
-/** Gets the object associated with the specified key in the
- * hashtable.
- * @param key <CODE>char[]</CODE> the specified key
- * @return int the element for the key or -1 if the key is not
- *     defined in the hash table.
- */
-public int get(MethodBinding key) {
-       int index = hashCode(key);
-       while (keyTable[index] != null) {
-               if (equalsForNameAndType(keyTable[index], key))
-                       return valueTable[index];
-               index = (index + 1) % keyTable.length;
-       }
-       return -1;
-}
-/**
- * Return the hashcode for the key parameter
- *
- * @param key org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- * @return int
- */
-public int hashCode(MethodBinding key) {
-       return CharOperation.hashCode(key.selector) % keyTable.length;
-}
-/**
- * Puts the specified element into the hashtable, using the specified
- * key.  The element may be retrieved by doing a get() with the same key.
- * The key and the element cannot be null. 
- * 
- * @param key <CODE>Object</CODE> the specified key in the hashtable
- * @param value <CODE>int</CODE> the specified element
- * @return int the old value of the key, or -1 if it did not have one.
- */
-public int put(MethodBinding key, int value) { 
-       int index = hashCode(key);
-       while (keyTable[index] != null) {
-               if (equalsForNameAndType(keyTable[index], key))
-                       return valueTable[index] = value;
-               index = (index + 1) % keyTable.length;
-       }
-       keyTable[index] = key;
-       valueTable[index] = value;
-
-       // assumes the threshold is never equal to the size of the table
-       if (++elementSize > threshold)
-               rehash();
-       return value;
-}
-/**
- * Rehashes the content of the table into a bigger table.
- * This method is called automatically when the hashtable's
- * size exceeds the threshold.
- */
-private void rehash() {
-       MethodNameAndTypeCache newHashtable = new MethodNameAndTypeCache(keyTable.length * 2);
-       for (int i = keyTable.length; --i >= 0;)
-               if (keyTable[i] != null)
-                       newHashtable.put(keyTable[i], valueTable[i]);
-
-       this.keyTable = newHashtable.keyTable;
-       this.valueTable = newHashtable.valueTable;
-       this.threshold = newHashtable.threshold;
-}
-/**
- * Returns the number of elements contained in the hashtable.
- *
- * @return <CODE>int</CODE> The size of the table
- */
-public int size() {
-       return elementSize;
-}
-/**
- * Converts to a rather lengthy String.
- *
- * @return String the ascii representation of the receiver
- */
-public String toString() {
-       int max = size();
-       StringBuffer buf = new StringBuffer();
-       buf.append("{"); //$NON-NLS-1$
-       for (int i = 0; i < max; ++i) {
-               if (keyTable[i] != null) {
-                       buf.append(keyTable[i]).append("->").append(valueTable[i]); //$NON-NLS-1$
-               }
-               if (i < max) {
-                       buf.append(", "); //$NON-NLS-1$
-               }
-       }
-       buf.append("}"); //$NON-NLS-1$
-       return buf.toString();
-}
-}
diff --git a/src/org/eclipse/jdt/internal/compiler/codegen/QualifiedNamesConstants.java b/src/org/eclipse/jdt/internal/compiler/codegen/QualifiedNamesConstants.java
deleted file mode 100644 (file)
index aff4cb8..0000000
+++ /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/src/org/eclipse/jdt/internal/compiler/env/AccessRestriction.java b/src/org/eclipse/jdt/internal/compiler/env/AccessRestriction.java
new file mode 100644 (file)
index 0000000..1ed5061
--- /dev/null
@@ -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();
+       }
+}
index d928f82..28211a1 100644 (file)
@@ -30,4 +30,14 @@ Constant getConstant();
  */
 
 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();
 }
index 75435bc..9f2ecd0 100644 (file)
@@ -29,7 +29,7 @@ char[][] getExceptionTypeNames();
 
 /**
  * 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[][] getExceptionTypeNames();
 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();
index aacda73..f693287 100644 (file)
@@ -65,6 +65,16 @@ IBinaryMethod[] getMethods();
  */
 
 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[] getName();
  */
 
 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
index 4f3bfa1..c6cb0ac 100644 (file)
  *******************************************************************************/
 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"
+       
        
 }
index bf645ec..91b5b4a 100644 (file)
@@ -18,15 +18,26 @@ package org.eclipse.jdt.internal.compiler.env;
  * 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();
index cca5c60..414d190 100644 (file)
 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 @@ int getModifiers();
  */
 
 boolean isBinaryType();
-boolean isClass();
-boolean isInterface();
 }
index fc08366..8eba3ab 100644 (file)
@@ -59,4 +59,14 @@ int getNameSourceStart();
  */
 
 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();
 }
index 594d718..3464fe8 100644 (file)
@@ -29,14 +29,14 @@ int getDeclarationSourceStart();
 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 @@ ISourceImport[] getImports();
 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 @@ char[] getPackageName();
  * 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();
 }
index b7ab4e6..1f015d5 100644 (file)
@@ -16,19 +16,28 @@ public class NameEnvironmentAnswer {
        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.
index 115979e..d7dc642 100644 (file)
@@ -83,6 +83,42 @@ public class ConditionalFlowInfo extends FlowInfo {
                                && 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 @@ public class ConditionalFlowInfo extends FlowInfo {
        }
        
        /**
+        * 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) {
index d17ab89..0069d50 100644 (file)
@@ -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 @@ import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
  */
 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 @@ public class FinallyFlowContext extends FlowContext {
         * 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 @@ public class FinallyFlowContext extends FlowContext {
                                }
                        }
                }
+               
+               // 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 @@ public class FinallyFlowContext extends FlowContext {
                        }
                }
        }
+
+       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;
+       }
 }
index 340781f..46b46a5 100644 (file)
@@ -13,11 +13,13 @@ package org.eclipse.jdt.internal.compiler.flow;
 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 @@ public class FlowContext implements TypeConstants {
                                
                        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 @@ public class FlowContext implements TypeConstants {
 
                        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 @@ public class FlowContext implements TypeConstants {
                // 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 class FlowContext implements TypeConstants {
                }
        }
 
+       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
        }
index 1736a5c..3219a62 100644 (file)
@@ -16,7 +16,11 @@ import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
 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 class FlowInfo {
         */
        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 @@ public abstract class FlowInfo {
        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);
index 450bdff..9f1ed05 100644 (file)
@@ -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 @@ public class LoopingFlowContext extends SwitchFlowContext {
        Reference finalAssignments[];
        VariableBinding finalVariables[];
        int assignCount = 0;
+       
+       Expression[] nullReferences;
+       int[] nullStatus;
+       int nullCount;
+       
        Scope associatedScope;
        
        public LoopingFlowContext(
@@ -43,9 +49,9 @@ public class LoopingFlowContext extends SwitchFlowContext {
                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 @@ public class LoopingFlowContext extends SwitchFlowContext {
                                }
                        }
                }
+               // 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 class LoopingFlowContext extends SwitchFlowContext {
 
        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 @@ public class LoopingFlowContext extends SwitchFlowContext {
                }
        }
 
-       boolean recordFinalAssignment(
+       protected boolean recordFinalAssignment(
                VariableBinding binding,
                Reference finalAssignment) {
 
@@ -141,6 +170,21 @@ public class LoopingFlowContext extends SwitchFlowContext {
                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) {
index 4ae4c52..88cd296 100644 (file)
@@ -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 class UnconditionalFlowInfo extends FlowInfo {
        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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                // 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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                                        // 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];
+                                       }
+                                       for (; i < length; i++) {
+                                               extraDefiniteInits[i] = 0;
+                                               extraDefiniteNulls[i] = 0;
+                                               extraDefiniteNonNulls[i] = 0;
                                        }
-                                       while (i < length)
-                                               extraDefiniteInits[i++] = 0;
                                }
                        } else {
                                // no extra storage on otherInits
@@ -88,6 +105,8 @@ public class UnconditionalFlowInfo extends FlowInfo {
                                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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                        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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                        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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                // 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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                        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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                        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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                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 @@ public class UnconditionalFlowInfo extends FlowInfo {
        }
        
        /**
+        * 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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                // We do not want to complain in unreachable code
                if ((this.reachMode & UNREACHABLE) != 0)
                        return true;
-               if (local.isArgument) {
+
+               // final constants are inlined, and thus considered as always initialized
+               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.constant != Constant.NotAConstant) {
+               if (local.isConstantValue()) {
                        return true;
                }
-               return isDefinitelyAssigned(local.id + maxFieldCount);
+               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 @@ public class UnconditionalFlowInfo extends FlowInfo {
         */
        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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                                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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                                        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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                                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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                                long mask;
                                extraDefiniteInits[vectorIndex] &= ~(mask = 1L << (position % BitCacheSize));
                                extraPotentialInits[vectorIndex] &= ~mask;
+                               extraDefiniteNulls[vectorIndex] &= ~mask;
+                               extraDefiniteNonNulls[vectorIndex] &= ~mask;
                        }
                }
        }
@@ -462,6 +708,10 @@ public class UnconditionalFlowInfo extends FlowInfo {
                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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                                        // 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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                                        // 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;
+                                               this.extraDefiniteNulls[i] = 0;
+                                               this.extraDefiniteNonNulls[i++] = 0;
                                        }
-                                       while (i < length)
-                                               this.extraDefiniteInits[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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                                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 @@ public class UnconditionalFlowInfo extends FlowInfo {
                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$
        }
        
index 0d729a4..78f82b8 100644 (file)
@@ -55,6 +55,7 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
        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 class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
        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 class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
        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_ReportUnsafeTypeOperation = "org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation"; //$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,12 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
        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_ReportInconsistentNullCheck = "org.eclipse.jdt.core.compiler.problem.inconsistentNullCheck"; //$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 +160,13 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
        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 UnsafeTypeOperation = 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 InconsistentNullCheck = ASTNode.Bit37L;
 
        // Default severity level for handlers
        public long errorThreshold = 0;
@@ -162,7 +182,13 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
                | IncompatibleNonInheritedInterfaceMethod
                | NoImplicitStringConversion
                | FinallyBlockNotCompleting
-               | AssertUsedAsAnIdentifier;
+               | AssertUsedAsAnIdentifier
+               | EnumUsedAsAnIdentifier
+               | UnsafeTypeOperation
+               | MissingSerialVersion
+               | VarargsArgumentNeedCast
+               | ForbiddenReference
+               /*| InconsistentNullCheck*/;
 
        // Debug attributes
        public static final int Source = 1; // SourceFileAttribute
@@ -197,6 +223,12 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
        // 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 +248,11 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
        // 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 +315,15 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
                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 +334,11 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
                optionsMap.put(OPTION_ReportUnusedDeclaredThrownException, getSeverityString(UnusedDeclaredThrownException));
                optionsMap.put(OPTION_ReportUnusedDeclaredThrownExceptionWhenOverriding, this.reportUnusedDeclaredThrownExceptionWhenOverriding ? ENABLED : DISABLED); 
                optionsMap.put(OPTION_ReportUnqualifiedFieldAccess, getSeverityString(UnqualifiedFieldAccess));
+               optionsMap.put(OPTION_ReportUnsafeTypeOperation, getSeverityString(UnsafeTypeOperation));
+               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 +353,11 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
                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_ReportInconsistentNullCheck, getSeverityString(InconsistentNullCheck)); 
                return optionsMap;              
        }
        
@@ -406,6 +453,7 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
                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 +532,53 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
                                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 +598,23 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
                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_ReportUnsafeTypeOperation)) != null) updateSeverity(UnsafeTypeOperation, 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_ReportInconsistentNullCheck)) != null) updateSeverity(InconsistentNullCheck, optionValue);
+               
                // Javadoc options
                if ((optionValue = optionsMap.get(OPTION_DocCommentSupport)) != null) {
                        if (ENABLED.equals(optionValue)) {
@@ -542,11 +639,25 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
                }
                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 +732,8 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
                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 +761,16 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
                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(UnsafeTypeOperation)); //$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- inconsistent null check: ").append(getSeverityString(InconsistentNullCheck)); //$NON-NLS-1$
                return buf.toString();
        }
 
index f82b409..3130eed 100644 (file)
@@ -112,7 +112,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
        //          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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                                                                                                                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 abstract class Constant implements TypeIds, OperatorIds {
        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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                                        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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                                        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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                                        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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                                        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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                                        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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                                        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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                                        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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                                        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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                                        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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                                        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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                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 @@ public abstract class Constant implements TypeIds, OperatorIds {
                        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$
                }
index 52398d0..9ae827d 100644 (file)
@@ -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 @@ public interface ITypeRequestor {
        /**
         * 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 @@ public interface ITypeRequestor {
         * 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);
 }
index 0248540..51ab819 100644 (file)
@@ -43,6 +43,6 @@ public String toString(){
 
        return "(String)\"" + value +"\""; } //$NON-NLS-2$ //$NON-NLS-1$
 public int typeID() {
-       return T_String;
+       return T_JavaLangString;
 }
 }
index da45684..541002b 100644 (file)
@@ -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 final class ArrayBinding extends TypeBinding {
 
        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 @@ public char[] constantPoolName() {
        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 @@ public int dimensions() {
 * 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 @@ public boolean isCompatibleWith(TypeBinding right) {
        } 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 @@ public char[] sourceName() {
        }
        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$
 }
index b1ec5eb..a6e82bf 100644 (file)
 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$
 }
index 6ada2f8..6d837a5 100644 (file)
  *******************************************************************************/
 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 @@ null is NOT a valid value for a non-public field... it just means the field is n
 */
 
 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 @@ public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType,
        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 @@ public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType,
        }
 
        this.modifiers = binaryType.getModifiers();
-       if (binaryType.isInterface())
+       if (binaryType.getKind() == IGenericType.INTERFACE_DECL)
                this.modifiers |= AccInterface;
                
        if (binaryType.isAnonymous()) {
@@ -108,28 +172,85 @@ public MethodBinding[] availableMethods() {
        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 @@ void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
                        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;
+       TypeBinding[] parameters = NoParameters;
+       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) {
-                       exceptions = new ReferenceBinding[size];
-                       for (int i = 0; i < size; i++)
-                               exceptions[i] = environment.getTypeFromConstantPoolName(exceptionTypes[i], 0, -1);
+                       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;
+                       }
                }
-       }
 
-       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*/}
+               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);
+                       }
                }
-       }
 
-       // 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;
+               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);
+                               }
+                       }
                }
        }
 
-       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;
+       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();
+       }
+       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 @@ private void createMethods(IBinaryMethod[] iMethods) {
        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,15 @@ public FieldBinding[] fields() {
                resolveTypeFor(fields[i]);
        return fields;
 }
+public long getAnnotationTagBits() {
+       return this.tagBits;
+}
 // 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 +551,8 @@ public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
 // 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 +573,15 @@ public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes
 
        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 +608,7 @@ public ReferenceBinding getMemberType(char[] typeName) {
                        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 +648,81 @@ public boolean hasMemberTypes() {
 }
 // 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 +732,71 @@ public MethodBinding[] methods() {
 
        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 +866,7 @@ public String toString() {
        s += "\n\n\n"; //$NON-NLS-1$
        return s;
 }
+MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types
+       return methods;
+}
 }
index d6225aa..226f46f 100644 (file)
  *******************************************************************************/
 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;
+       }
+       
+       public long getAnnotationTagBits() {
+               // TODO (philippe) need to generalize to methods & fields
+               return 0;
+       }
+
        /* API
        * Answer true if the receiver is not a problem binding
        */
-       
        public final boolean isValidBinding() {
                return problemId() == NoError;
        }
@@ -29,14 +60,13 @@ public abstract class Binding implements BindingIds, CompilerModifiers, ProblemR
        * 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(){
index f0f9451..50a15c7 100644 (file)
@@ -14,7 +14,6 @@ import org.eclipse.jdt.core.compiler.CharOperation;
 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 @@ public class BlockScope extends Scope {
                                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 class BlockScope extends Scope {
         */
        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 class BlockScope extends Scope {
         */
        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 @@ public class BlockScope extends Scope {
                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 @@ public class BlockScope extends Scope {
                        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 @@ public class BlockScope extends Scope {
                                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 @@ public class BlockScope extends Scope {
                                        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 @@ public class BlockScope extends Scope {
                                        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 @@ public class BlockScope extends Scope {
                Binding binding =
                        getBinding(
                                compoundName[currentIndex++],
-                               VARIABLE | TYPE | PACKAGE,
+                               Binding.VARIABLE | Binding.TYPE | Binding.PACKAGE,
                                invocationSite, 
                                true /*resolve*/);
                if (!binding.isValidBinding())
@@ -638,7 +638,7 @@ public class BlockScope extends Scope {
 
                // 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 @@ public class BlockScope extends Scope {
                                // 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 @@ public class BlockScope extends Scope {
 
                                //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 @@ public class BlockScope extends Scope {
                                currentType = currentEnclosingType;
                        }
                        if (currentType == targetEnclosingType
-                               || (!onlyExactMatch && targetEnclosingType.isSuperclassOf(currentType))) {
+                               || (!onlyExactMatch && currentType.findSuperTypeErasingTo(targetEnclosingType) != null)) {
                                return path;
                        }
                }
index 6d83943..82bda2d 100644 (file)
 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'};
 
@@ -54,7 +60,7 @@ public class ClassScope extends Scope {
                        if (hierarchyIsInconsistent) { // 72468
                                referenceContext.binding.fields = new FieldBinding[1];
                                referenceContext.binding.fields[0] =
-                                       new FieldBinding(IncompleteHierarchy, VoidBinding, AccPrivate, referenceContext.binding, null);
+                                       new FieldBinding(IncompleteHierarchy, IntBinding, AccPrivate, referenceContext.binding, null);
                        } else {
                                referenceContext.binding.fields = NoFields;
                        }
@@ -64,9 +70,13 @@ public class ClassScope extends Scope {
                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++;
@@ -77,7 +87,7 @@ public class ClassScope extends Scope {
                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 {
@@ -111,7 +121,7 @@ public class ClassScope extends Scope {
                }
                // 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;
@@ -123,7 +133,7 @@ public class ClassScope extends Scope {
                        fieldBindings = newFieldBindings;
                }
                if (hierarchyIsInconsistent)
-                       fieldBindings[count++] = new FieldBinding(IncompleteHierarchy, VoidBinding, AccPrivate, referenceContext.binding, null);
+                       fieldBindings[count++] = new FieldBinding(IncompleteHierarchy, IntBinding, AccPrivate, referenceContext.binding, null);
 
                if (count != fieldBindings.length)
                        System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count);
@@ -157,7 +167,8 @@ public class ClassScope extends Scope {
                LocalTypeBinding localType = new LocalTypeBinding(this, enclosingType, this.switchCase());
                referenceContext.binding = localType;
                checkAndSetModifiers();
-
+               buildTypeVariables();
+               
                // Look at member types
                ReferenceBinding[] memberTypeBindings = NoMemberTypes;
                if (referenceContext.memberTypes != null) {
@@ -166,7 +177,7 @@ public class ClassScope extends Scope {
                        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;
                                }
@@ -186,7 +197,6 @@ public class ClassScope extends Scope {
                                                continue nextMember;
                                        }
                                }
-
                                ClassScope memberScope = new ClassScope(this, referenceContext.memberTypes[i]);
                                LocalTypeBinding memberBinding = memberScope.buildLocalType(localType, packageBinding);
                                memberBinding.setAsMemberType();
@@ -209,25 +219,76 @@ public class ClassScope extends Scope {
                referenceContext.binding.verifyMethods(environment().methodVerifier());
        }
        
+       private void buildMemberTypes(AccessRestriction accessRestriction) {
+           SourceTypeBinding sourceType = referenceContext.binding;
+               ReferenceBinding[] memberTypeBindings = NoMemberTypes;
+               if (referenceContext.memberTypes != null) {
+                       int length = referenceContext.memberTypes.length;
+                       memberTypeBindings = new ReferenceBinding[length];
+                       int count = 0;
+                       nextMember : for (int i = 0; i < length; i++) {
+                               TypeDeclaration memberContext = referenceContext.memberTypes[i];
+                               if (memberContext.kind() == IGenericType.INTERFACE_DECL
+                                       && sourceType.isNestedType()
+                                       && sourceType.isClass()
+                                       && !sourceType.isStatic()) {
+                                       problemReporter().nestedClassCannotDeclareInterface(memberContext);
+                                       continue nextMember;
+                               }
+                               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 nextMember;
+                                       }
+                                       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 nextMember;
+                                       }
+                               }
+
+                               ClassScope memberScope = new ClassScope(this, memberContext);
+                               memberTypeBindings[count++] = memberScope.buildType(sourceType, sourceType.fPackage, accessRestriction);
+                       }
+                       if (count != length)
+                               System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
+               }
+               sourceType.memberTypes = memberTypeBindings;
+       }
+       
        private void buildMethods() {
-               if (referenceContext.methods == null) {
+               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.length;
+               int size = methods == null ? 0 : methods.length;
+               // look for <clinit> method
                int clinitIndex = -1;
                for (int i = 0; i < size; i++) {
-                       if (methods[i] instanceof Clinit) {
+                       if (methods[i].isClinit()) {
                                clinitIndex = i;
                                break;
                        }
                }
-               MethodBinding[] methodBindings = new MethodBinding[clinitIndex == -1 ? size : size - 1];
 
-               int count = 0;
+               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);
@@ -242,7 +303,8 @@ public class ClassScope extends Scope {
                referenceContext.binding.methods = methodBindings;
                referenceContext.binding.modifiers |= AccUnresolved; // until methods() is sent
        }
-       SourceTypeBinding buildType(SourceTypeBinding enclosingType, PackageBinding packageBinding) {
+       
+       SourceTypeBinding buildType(SourceTypeBinding enclosingType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
                // provide the typeDeclaration with needed scopes
                referenceContext.scope = this;
                referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
@@ -259,49 +321,32 @@ public class ClassScope extends Scope {
                }
 
                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
 
-               // Look at member types
-               ReferenceBinding[] memberTypeBindings = NoMemberTypes;
-               if (referenceContext.memberTypes != null) {
-                       int size = referenceContext.memberTypes.length;
-                       memberTypeBindings = new ReferenceBinding[size];
-                       int count = 0;
-                       nextMember : for (int i = 0; i < size; i++) {
-                               TypeDeclaration memberContext = referenceContext.memberTypes[i];
-                               if (memberContext.isInterface()
-                                       && sourceType.isNestedType()
-                                       && sourceType.isClass()
-                                       && !sourceType.isStatic()) {
-                                       problemReporter().nestedClassCannotDeclareInterface(memberContext);
-                                       continue nextMember;
-                               }
-                               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 nextMember;
-                                       }
-                                       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 nextMember;
-                                       }
-                               }
-
-                               ClassScope memberScope = new ClassScope(this, memberContext);
-                               memberTypeBindings[count++] = memberScope.buildType(sourceType, packageBinding);
-                       }
-                       if (count != size)
-                               System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
+               if (sourceType.id == T_JavaLangObject) { // handle the case of redefining java.lang.Object up front
+                       problemReporter().objectCannotBeGeneric(referenceContext);
+                       return; 
                }
-               sourceType.memberTypes = memberTypeBindings;
-               return sourceType;
+               sourceType.typeVariables = createTypeVariables(typeParameters, sourceType);
+               sourceType.modifiers |= AccGenericSignature;
        }
        
        private void checkAndSetModifiers() {
@@ -319,11 +364,18 @@ public class ClassScope extends Scope {
                                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) {
@@ -368,13 +420,18 @@ public class ClassScope extends Scope {
                // 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);
@@ -382,13 +439,38 @@ public class ClassScope extends Scope {
                                                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);
@@ -417,9 +499,9 @@ public class ClassScope extends Scope {
 
                                        // 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);
@@ -429,13 +511,13 @@ public class ClassScope extends Scope {
                                        // 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;
                                }
                        }
 
@@ -465,16 +547,30 @@ public class ClassScope extends Scope {
                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.
@@ -493,13 +589,13 @@ public class ClassScope extends Scope {
                        // 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))
@@ -512,81 +608,85 @@ public class ClassScope extends Scope {
                }
                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)
@@ -606,26 +706,32 @@ public class ClassScope extends Scope {
        */
        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);
-               }
-               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);
+                       return !detectHierarchyCycle(sourceType, sourceType.superclass, null);
+               }
+               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;
@@ -635,10 +741,36 @@ public class ClassScope extends Scope {
                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.
@@ -652,9 +784,16 @@ public class ClassScope extends Scope {
        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;
@@ -662,21 +801,14 @@ public class ClassScope extends Scope {
                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) {
@@ -685,8 +817,26 @@ public class ClassScope extends Scope {
                                        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;
@@ -707,15 +857,16 @@ public class ClassScope extends Scope {
        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);
@@ -740,27 +891,80 @@ public class ClassScope extends Scope {
                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
@@ -773,10 +977,13 @@ public class ClassScope extends Scope {
                                        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
                                }
                        }
 
@@ -790,7 +997,9 @@ public class ClassScope extends Scope {
                                                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;
@@ -800,93 +1009,68 @@ public class ClassScope extends Scope {
                        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 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);
-                               }
+
+       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;
                        }
-                       // 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;
+               } 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
+                       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.
index d4a8d4f..9033073 100644 (file)
 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 @@ public class CompilationUnitScope extends Scope {
        private CompoundNameVector qualifiedReferences;
        private SimpleNameVector simpleNameReferences;
        private ObjectVector referencedTypes;
+       private ObjectVector referencedSuperTypes;
        
        HashtableOfType constantPoolNameUsage;
 
@@ -50,17 +46,19 @@ public CompilationUnitScope(CompilationUnitDeclaration unit, LookupEnvironment e
                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 @@ void buildTypeBindings() {
                }
 
                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 @@ void checkAndSetImports() {
        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 @@ void checkAndSetImports() {
                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 @@ void faultInImports() {
        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 @@ void faultInImports() {
        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;
                        }
+                       if (importReference.isStatic() && importBinding instanceof PackageBinding) {
+                               problemReporter().cannotImportPackage(importReference);
+                               continue nextImport;
+                       }
                        resolvedImports[index++] = new ImportBinding(compoundName, true, importBinding, importReference);
                } else {
-                       Binding typeBinding = findSingleTypeImport(compoundName);
-                       if (!typeBinding.isValidBinding()) {
-                               problemReporter().importProblem(importReference, typeBinding);
+                       Binding importBinding = findSingleImport(compoundName, importReference.isStatic());
+                       if (!importBinding.isValidBinding()) {
+                               problemReporter().importProblem(importReference, importBinding);
                                continue nextImport;
                        }
-                       if (typeBinding instanceof PackageBinding) {
+                       if (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);
+                       // 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;
                                }
-                               problemReporter().duplicateImport(importReference);
-                               continue nextImport;
+                               typesBySimpleNames.put(compoundName[compoundName.length - 1], referenceBinding);
                        }
-                       resolvedImports[index++] = new ImportBinding(compoundName, false, typeBinding, importReference);
-                       typesBySimpleNames.put(compoundName[compoundName.length - 1], (ReferenceBinding) typeBinding);
+                       resolvedImports[index++] = new ImportBinding(compoundName, false, importBinding, importReference);
                }
        }
 
@@ -339,7 +350,7 @@ void faultInImports() {
        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 @@ public void faultInTypes() {
        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 @@ private Binding findOnDemandImport(char[][] compoundName) {
 
        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 @@ ImportBinding[] getDefaultImports() {
 
        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 @@ void recordReference(char[][] qualifiedEnclosingName, char[] simpleName) {
        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 @@ Binding resolveSingleTypeImport(ImportBinding importBinding) {
        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()) {
-                       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
+                       if (enclosing != null)
+                               recordSuperTypeReference(enclosing);
                }
                ReferenceBinding superclass = type.superclass();
-               if (superclass != null && !referencedTypes.containsIdentical(superclass))
-                               referencedTypes.add(superclass); // to record its supertypes
+               if (superclass != null)
+                       recordSuperTypeReference(superclass);
                ReferenceBinding[] interfaces = type.superInterfaces();
-               if (interfaces != null && interfaces.length > 0)
+               if (interfaces != null)
                        for (int j = 0, length = interfaces.length; j < length; j++)
-                               if (!referencedTypes.containsIdentical(interfaces[j]))
-                                       referencedTypes.add(interfaces[j]); // to record its supertypes
+                               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);
        }
 
        int size = qualifiedReferences.size;
@@ -597,6 +642,25 @@ public void storeDependencyInfo() {
 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);
index 31f21cc..f8e80f1 100644 (file)
  *******************************************************************************/
 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)
 }
index 4889096..f84a723 100644 (file)
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 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 +35,27 @@ public FieldBinding(FieldDeclaration field, TypeBinding type, int modifiers, Ref
 }
 // 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 +107,15 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
        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 +125,7 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
                                temp = temp.enclosingType();
                        }
 
-                       ReferenceBinding outerDeclaringClass = declaringClass;
+                       ReferenceBinding outerDeclaringClass = (ReferenceBinding)declaringClass.erasure();
                        temp = outerDeclaringClass.enclosingType();
                        while (temp != null) {
                                outerDeclaringClass = temp;
@@ -136,6 +150,28 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
        } 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;
 }
@@ -207,4 +243,26 @@ public final boolean isViewedAsDeprecated() {
 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;            
+}
 }
index 6eb0985..05c2992 100644 (file)
@@ -18,7 +18,7 @@ public class ImportBinding extends Binding {
        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 @@ public ImportBinding(char[][] compoundName, boolean isOnDemand, Binding binding,
 * 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$
index e9703ba..462f95e 100644 (file)
@@ -11,6 +11,8 @@
 package org.eclipse.jdt.internal.compiler.lookup;
 
 public interface InvocationSite {
+       
+       TypeBinding[] genericTypeArguments();
        boolean isSuperAccess();
        boolean isTypeAccess();
        void setDepth(int depth);
index cacc605..541448f 100644 (file)
@@ -13,7 +13,6 @@ package org.eclipse.jdt.internal.compiler.lookup;
 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 @@ public char[] constantPoolName() /* java/lang/Object */ {
 
 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 @@ ArrayBinding createArrayType(int dimensionCount) {
 
        // 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 void setConstantPoolName(char[] computedConstantPoolName) /* java/lang/Ob
 
 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;
index 0ab99f2..9084ae4 100644 (file)
  *******************************************************************************/
 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 class LocalVariableBinding extends VariableBinding {
        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 @@ public class LocalVariableBinding extends VariableBinding {
        /* 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() {
 
index a7a9c9c..83b7380 100644 (file)
  *******************************************************************************/
 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;
+       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;
 
        PackageBinding defaultPackage;
-       ImportBinding[] defaultImports;
        HashtableOfPackage knownPackages;
-       static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound);
-       static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR, NotFound);
+       private int lastCompletedUnitIndex = -1;
+       private int lastUnitIndex = -1;
 
-       private INameEnvironment nameEnvironment;
-       private MethodVerifier verifier;
-       private ArrayBinding[][] uniqueArrayBindings;
+       public INameEnvironment nameEnvironment;
+       public CompilerOptions options;
+       public ProblemReporter problemReporter;
 
-       private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4];
-       private int lastUnitIndex = -1;
-       private int lastCompletedUnitIndex = -1;
-       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[] 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 @@ public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions options,
        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 @@ public ReferenceBinding askForType(char[][] compoundName) {
 
        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 @@ ReferenceBinding askForType(PackageBinding packageBinding, char[] name) {
 
        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 @@ ReferenceBinding askForType(PackageBinding packageBinding, char[] name) {
 * 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 @@ public void buildTypeBindings(CompilationUnitDeclaration unit) {
 * 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,67 @@ public void completeTypeBindings(CompilationUnitDeclaration parsedUnit, boolean
                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_JavaLangVoid :
+                       return VoidBinding;
+
+               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);                           
+               case TypeIds.T_void :
+                       boxedType = getType(JAVA_LANG_VOID);
+                       if (boxedType != null) return boxedType;
+                       return new ProblemReferenceBinding(     JAVA_LANG_VOID, NotFound);                              
+       }
+       return type;
+}      
 private PackageBinding computePackageFrom(char[][] constantPoolName) {
        if (constantPoolName.length == 1)
                return defaultPackage;
@@ -252,10 +331,10 @@ private PackageBinding computePackageFrom(char[][] constantPoolName) {
        }
        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 +359,7 @@ ArrayBinding createArrayType(TypeBinding type, int dimensionCount) {
        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 +370,26 @@ ArrayBinding createArrayType(TypeBinding type, int dimensionCount) {
                (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 +427,146 @@ PackageBinding createPackage(char[][] compoundName) {
        }
        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[] originalArguments, ReferenceBinding enclosingType) {
+
+       // relocalize wildcard onto genericType (could come from other types)
+       TypeBinding[] typeArguments = originalArguments;
+       for (int i = 0, length = typeArguments == null ? 0 : typeArguments.length; i < length; i++) {
+               TypeBinding argument = originalArguments[i];
+               if (argument.isWildcard()) {
+                       WildcardBinding wildcard = (WildcardBinding) argument;
+                       if (wildcard.genericType != genericType) { // wildcard comes from different type
+                               if (typeArguments == originalArguments) {
+                                       System.arraycopy(originalArguments, 0, typeArguments = new TypeBinding[length], 0, i);
+                               }
+                               typeArguments[i] = createWildcard(genericType, i, wildcard.bound, wildcard.kind);
+                       } else if (typeArguments != originalArguments) {
+                               typeArguments[i] = argument;
+                       }
+               } else if (typeArguments != originalArguments) {
+                       typeArguments[i] = argument;
+               }
+       }
+       
+       // 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 +617,7 @@ PackageBinding getTopLevelPackage(char[] name) {
        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 +656,24 @@ public ReferenceBinding getType(char[][] compoundName) {
 
        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 +683,7 @@ public ReferenceBinding getType(char[][] compoundName) {
 * 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 +696,9 @@ ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int en
        } 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 +711,7 @@ ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int en
 * 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 +752,111 @@ TypeBinding getTypeFromSignature(char[] signature, int start, int end) {
                                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 +866,66 @@ boolean isPackage(char[][] compoundName, char[] name) {
 
 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;
                        }
                }
        }
index 0441fb3..f3e07f3 100644 (file)
@@ -12,7 +12,7 @@ package org.eclipse.jdt.internal.compiler.lookup;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
 
 public class MethodBinding extends Binding implements BaseTypes, TypeConstants {
        public int modifiers;
@@ -21,20 +21,22 @@ public class MethodBinding extends Binding implements BaseTypes, TypeConstants {
        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 +46,8 @@ public MethodBinding(int modifiers, char[] selector, TypeBinding returnType, Typ
                        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 +60,6 @@ public MethodBinding(MethodBinding initialMethodBinding, ReferenceBinding declar
 }
 /* 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 +74,65 @@ public final boolean areParametersEqual(MethodBinding method) {
                        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 +165,7 @@ public final boolean canBeSeenBy(InvocationSite invocationSite, Scope scope) {
                        temp = temp.enclosingType();
                }
 
-               ReferenceBinding outerDeclaringClass = declaringClass;
+               ReferenceBinding outerDeclaringClass = (ReferenceBinding)declaringClass.erasure();
                temp = outerDeclaringClass.enclosingType();
                while (temp != null) {
                        outerDeclaringClass = temp;
@@ -173,7 +227,15 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
        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 +245,7 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
                                temp = temp.enclosingType();
                        }
 
-                       ReferenceBinding outerDeclaringClass = declaringClass;
+                       ReferenceBinding outerDeclaringClass = (ReferenceBinding)declaringClass.erasure();
                        temp = outerDeclaringClass.enclosingType();
                        while (temp != null) {
                                outerDeclaringClass = temp;
@@ -208,6 +270,34 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
        } 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,9 +314,71 @@ public TypeBinding constantPoolDeclaringClass() {
 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;
 }
+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
 */
@@ -243,10 +395,7 @@ public final boolean isBridge() {
 /* 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 +512,9 @@ public final boolean isSynthetic() {
        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 +525,13 @@ public final boolean isViewedAsDeprecated() {
                (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 +568,10 @@ public char[] shortReadableName() {
                }
        }
        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 +593,13 @@ public final char[] signature() /* (ILjava/lang/Thread;)Ljava/lang/Object; */ {
        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 +607,8 @@ public final char[] signature() /* (ILjava/lang/Thread;)Ljava/lang/Object; */ {
                        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 +617,7 @@ public final char[] signature() /* (ILjava/lang/Thread;)Ljava/lang/Object; */ {
                        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 +629,13 @@ public final char[] signature() /* (ILjava/lang/Thread;)Ljava/lang/Object; */ {
                }
        }
        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 +643,7 @@ public final int sourceEnd() {
                return 0;
        return method.sourceEnd;
 }
-AbstractMethodDeclaration sourceMethod() {
+public AbstractMethodDeclaration sourceMethod() {
        SourceTypeBinding sourceType;
        try {
                sourceType = (SourceTypeBinding) declaringClass;
@@ -495,6 +663,7 @@ public final int sourceStart() {
                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 +704,14 @@ public String toString() {
        }
        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;
+}
 }
index 92b806b..67cf2dd 100644 (file)
@@ -16,6 +16,7 @@ import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
 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 @@ public class MethodScope extends BlockScope {
                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 @@ public class MethodScope extends BlockScope {
                        // 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 @@ public class MethodScope extends BlockScope {
                // 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 @@ public class MethodScope extends BlockScope {
                                        | 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 @@ public class MethodScope extends BlockScope {
                        // 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 @@ public class MethodScope extends BlockScope {
                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;
        }
 
index 115864c..e47cdd3 100644 (file)
  *******************************************************************************/
 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 @@ Binding creation is responsible for reporting all problems with types:
                - 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 @@ public MethodVerifier(LookupEnvironment environment) {
        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,51 +63,79 @@ private boolean areParametersEqual(MethodBinding one, MethodBinding two) {
                if (!areTypesEqual(oneArgs[i], twoArgs[i])) return false;
        return true;
 }
-private boolean areReturnTypesEqual(MethodBinding one, MethodBinding two) {
+boolean areReturnTypesEqual(MethodBinding one, MethodBinding two) {
        return areTypesEqual(one.returnType, two.returnType);
 }
-private boolean areTypesEqual(TypeBinding one, TypeBinding two) {
+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) {
+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.isStatic() != inheritedMethod.isStatic()) {  // Cannot override a static method or hide an instance method
-                       this.problemReporter(currentMethod).staticAndInstanceConflict(currentMethod, inheritedMethod);
+                       problemReporter(currentMethod).staticAndInstanceConflict(currentMethod, inheritedMethod);
                        continue nextMethod;
                }
 
-               if (!currentMethod.isAbstract() && inheritedMethod.isAbstract()) {
-                       if ((currentMethod.modifiers & CompilerModifiers.AccOverriding) == 0)
+               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)) {
-                       this.problemReporter(currentMethod).incompatibleReturnType(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
@@ -114,9 +145,10 @@ private void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBin
                                                        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);
                }
        }
 }
@@ -126,24 +158,27 @@ Verify that newExceptions are all included in inheritedExceptions.
 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) {
+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 && 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;
        }
 
@@ -159,13 +194,13 @@ private void checkInheritedMethods(MethodBinding[] methods, int length) {
        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;
                                }
@@ -183,13 +218,13 @@ private void checkInheritedMethods(MethodBinding[] methods, int length) {
        // 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)
@@ -209,10 +244,9 @@ For each inherited method identifier (message pattern - vm signature minus the r
                                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;
@@ -236,13 +270,16 @@ private void checkMethods() {
                                MethodBinding currentMethod = current[i];
                                for (int j = 0, length2 = inherited.length; j < length2; j++) {
                                        MethodBinding inheritedMethod = inherited[j];
-                                       if (inheritedMethod != null && areParametersEqual(currentMethod, inheritedMethod)) {
-                                               matchingInherited[++index] = inheritedMethod;
-                                               inherited[j] = null; // do not want to find it again
+                                       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
                        }
                }
 
@@ -252,39 +289,48 @@ private void checkMethods() {
                        if (inheritedMethod != null) {
                                matchingInherited[++index] = inheritedMethod;
                                for (int j = i + 1; j < length; j++) {
-                                       if (inherited[j] != null && areParametersEqual(inheritedMethod, 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 (!areReturnTypesEqual(method, abstractMethod) || !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:
@@ -298,7 +344,10 @@ Binding creation is responsible for reporting:
        - 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;
@@ -306,83 +355,81 @@ private void computeInheritedMethods() {
        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
        HashtableOfObject nonVisibleDefaultMethods = new HashtableOfObject(3); // maps method selectors to an array of methods
        boolean allSuperclassesAreAbstract = true;
 
-       while (superType != null) {
-               if (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;
+       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())
-                                       continue nextMethod;
-                               MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(method.selector);
-                               if (existingMethods != null) {
-                                       for (int i = 0, length = existingMethods.length; i < length; i++) {
-                                               if (areReturnTypesEqual(method, existingMethods[i]) && 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;
                                        }
                                }
-                               MethodBinding[] nonVisible = (MethodBinding[]) nonVisibleDefaultMethods.get(method.selector);
-                               if (nonVisible != null)
-                                       for (int i = 0, l = nonVisible.length; i < l; i++)
-                                               if (areReturnTypesEqual(method, nonVisible[i]) && areParametersEqual(method, nonVisible[i])) 
-                                                       continue nextMethod;
-
-                               if (!method.isDefault() || method.declaringClass.fPackage == type.fPackage) {
-                                       if (existingMethods == null) {
-                                               existingMethods = new MethodBinding[] {method};
-                                       } else {
-                                               int length = existingMethods.length;
-                                               System.arraycopy(existingMethods, 0, existingMethods = new MethodBinding[length + 1], 0, length);
-                                               existingMethods[length] = method;
-                                       }
-                                       this.inheritedMethods.put(method.selector, existingMethods);
+                       }
+                       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 (!inheritedMethod.isDefault() || inheritedMethod.declaringClass.fPackage == type.fPackage) {
+                               if (existingMethods == null) {
+                                       existingMethods = new MethodBinding[] {inheritedMethod};
                                } else {
-                                       if (nonVisible == null) {
-                                               nonVisible = new MethodBinding[] {method};
-                                       } else {
-                                               int length = nonVisible.length;
-                                               System.arraycopy(nonVisible, 0, nonVisible = new MethodBinding[length + 1], 0, length);
-                                               nonVisible[length] = method;
-                                       }
-                                       nonVisibleDefaultMethods.put(method.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);
-
-                                       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 (areReturnTypesEqual(method, current[i]) && areParametersEqual(method, current[i])) {
-                                                               this.problemReporter().overridesPackageDefaultMethod(current[i], method);
-                                                               break foundMatch;
-                                                       }
+                                       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 (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(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++) {
@@ -400,21 +447,20 @@ private void computeInheritedMethods() {
 
                                        MethodBinding[] methods = superType.unResolvedMethods();
                                        nextMethod : 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);
+                                               MethodBinding inheritedMethod = methods[m];
+                                               MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(inheritedMethod.selector);
                                                if (existingMethods == null) {
-                                                       existingMethods = new MethodBinding[] {method};
+                                                       existingMethods = new MethodBinding[] {inheritedMethod};
                                                } else {
                                                        int length = existingMethods.length;
-                                                       for (int e = 0; e < length; e++) {
-                                                               MethodBinding existing = existingMethods[e];
-                                                               if (areParametersEqual(method, existing) && existing.declaringClass.implementsInterface(superType, true))
+                                                       // 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] = method;
+                                                       existingMethods[length] = inheritedMethod;
                                                }
-                                               this.inheritedMethods.put(method.selector, existingMethods);
+                                               this.inheritedMethods.put(inheritedMethod.selector, existingMethods);
                                        }
                                }
                        }
@@ -428,7 +474,7 @@ private void computeInheritedMethods() {
                        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
@@ -446,12 +492,18 @@ private void computeMethods() {
                }
        }
 }
-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
@@ -462,17 +514,20 @@ private boolean isAsVisible(MethodBinding newMethod, MethodBinding inheritedMeth
 
        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
@@ -487,10 +542,10 @@ private boolean mustImplementAbstractMethod(MethodBinding abstractMethod) {
        }
        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();
@@ -503,23 +558,21 @@ ReferenceBinding[] resolvedExceptionTypesFor(MethodBinding method) {
 
        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/src/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java b/src/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
new file mode 100644 (file)
index 0000000..cec3089
--- /dev/null
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * 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
+       // then when do you need a bridge method?
+       if (originalInherited.returnType != currentMethod.returnType) {
+               switch (originalInherited.returnType.leafComponentType().kind()) {
+                       case Binding.PARAMETERIZED_TYPE :
+                               if (!currentMethod.returnType.leafComponentType().isParameterizedType())
+                                       problemReporter(currentMethod).unsafeReturnTypeOverride(currentMethod, originalInherited, ((MethodDeclaration) currentMethod.sourceMethod()).returnType);
+                               break;
+                       case Binding.TYPE_PARAMETER :
+                               if (!currentMethod.returnType.leafComponentType().isTypeVariable())
+                                       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 && inheritedVars.length > 0; // must match unless all are replaced
+//             && currentVars.length > 0;
+}
+boolean hasBoundedParameters(ParameterizedTypeBinding parameterizedType) {
+       TypeBinding[] arguments = parameterizedType.arguments;
+       if (arguments == null) return false;
+
+       nextArg : for (int i = 0, l = arguments.length; i < l; i++) {
+               if (arguments[i].isWildcard())
+                       if (((WildcardBinding) arguments[i]).kind == org.eclipse.jdt.internal.compiler.ast.Wildcard.UNBOUND)
+                               continue nextArg;
+               if (arguments[i].isTypeVariable())
+                       if (((TypeVariableBinding) arguments[i]).firstBound == null)
+                               continue nextArg;
+               return true;
+       }
+       return false;
+}
+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
index 8143f9b..2b78a5d 100644 (file)
@@ -91,7 +91,7 @@ public class NestedTypeBinding extends SourceTypeBinding {
                if (synthLocal == null) return null;
        
                if (synthLocal.matchingField == null)
-                       synthLocal.matchingField = addSyntheticField(actualOuterLocalVariable);
+                       synthLocal.matchingField = addSyntheticFieldForInnerclass(actualOuterLocalVariable);
                return synthLocal;
        }
 
@@ -103,7 +103,7 @@ public class NestedTypeBinding extends SourceTypeBinding {
                if (synthLocal == null) return null;
        
                if (synthLocal.matchingField == null)
-                       synthLocal.matchingField = addSyntheticField(targetEnclosingType);
+                       synthLocal.matchingField = addSyntheticFieldForInnerclass(targetEnclosingType);
                return synthLocal;
        }
 
@@ -209,7 +209,7 @@ public class NestedTypeBinding extends SourceTypeBinding {
                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;
index ee68a49..9f29f95 100644 (file)
@@ -17,7 +17,7 @@ import org.eclipse.jdt.internal.compiler.util.HashtableOfType;
 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 @@ void addType(ReferenceBinding element) {
 * 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 @@ PackageBinding getPackage0(char[] name) {
 */
 
 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 @@ ReferenceBinding getType0(char[] name) {
 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/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedFieldBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedFieldBinding.java
new file mode 100644 (file)
index 0000000..d494449
--- /dev/null
@@ -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/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
new file mode 100644 (file)
index 0000000..bf283be
--- /dev/null
@@ -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/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
new file mode 100644 (file)
index 0000000..bbe65e7
--- /dev/null
@@ -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/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
new file mode 100644 (file)
index 0000000..df77613
--- /dev/null
@@ -0,0 +1,856 @@
+/*******************************************************************************
+ * 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#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;
+       }       
+}
index c4fab5f..b1dd4db 100644 (file)
@@ -38,7 +38,7 @@ ProblemBinding(char[] name, ReferenceBinding searchType, int problemId) {
 * Answer the receiver's binding type from Binding.BindingID.
 */
 
-public final int bindingType() {
+public final int kind() {
        return VARIABLE | TYPE;
 }
 /* API
index 71f0547..e5ae8db 100644 (file)
 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 ProblemMethodBinding(MethodBinding closestMatch, char[] selector, TypeBin
 */
 
 public final int problemId() {
-       return problemId;
+       return this.problemReason;
 }
 }
index b34f200..97570b7 100644 (file)
@@ -20,4 +20,10 @@ public interface ProblemReasons {
        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;
 }
index 7225ba7..00d8a18 100644 (file)
@@ -12,31 +12,32 @@ package org.eclipse.jdt.internal.compiler.lookup;
 
 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/src/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java
new file mode 100644 (file)
index 0000000..ce950e2
--- /dev/null
@@ -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;
+       }
+}
index 6cda282..e7f50f5 100644 (file)
@@ -45,7 +45,7 @@ public MethodBinding[] availableMethods() {
 */
 
 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 @@ public final boolean canBeSeenBy(ReferenceBinding receiverType, SourceTypeBindin
        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 @@ public final boolean canBeSeenBy(ReferenceBinding receiverType, SourceTypeBindin
                                temp = temp.enclosingType();
                        }
 
-                       ReferenceBinding outerDeclaringClass = this;
+                       ReferenceBinding outerDeclaringClass = (ReferenceBinding)this.erasure();
                        temp = outerDeclaringClass.enclosingType();
                        while (temp != null) {
                                outerDeclaringClass = temp;
@@ -168,7 +180,7 @@ public final boolean canBeSeenBy(Scope scope) {
                        temp = temp.enclosingType();
                }
 
-               ReferenceBinding outerDeclaringClass = this;
+               ReferenceBinding outerDeclaringClass = (ReferenceBinding)this.erasure();
                temp = outerDeclaringClass.enclosingType();
                while (temp != null) {
                        outerDeclaringClass = temp;
@@ -181,96 +193,157 @@ public final boolean canBeSeenBy(Scope scope) {
        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;
-       }
-
-       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;
-       }
+       
+       switch (compoundName.length) {
 
-       // 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 @@ public char[] constantPoolName() /* java/lang/Object */ {
        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 @@ public final int depth() {
                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,6 +377,92 @@ public int fieldCount() {
 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 (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.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]).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 (erasure() == erasure) return this;
+    ReferenceBinding currentType = this;
+    if (erasure.isClass()) {
+               while ((currentType = currentType.superclass()) != null) {
+                       if (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() == 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;
 }
@@ -317,22 +470,17 @@ 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 +500,30 @@ public PackageBinding getPackage() {
 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 +543,7 @@ public boolean implementsInterface(ReferenceBinding anInterface, boolean searchH
        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 +575,72 @@ boolean implementsMethod(MethodBinding method) {
 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 final boolean isLocalType() {
-       return (tagBits & IsLocalType) != 0;
-}
-public final boolean isMemberType() {
-       return (tagBits & IsMemberType) != 0;
-}
-public final boolean isNestedType() {
-       return (tagBits & IsNestedType) != 0;
+public boolean isInterface() {
+       // only consider strict interfaces
+       return (modifiers & (AccInterface | AccAnnotation)) == AccInterface;
 }
+
 /* Answer true if the receiver has private visibility
 */
-
 public final boolean isPrivate() {
        return (modifiers & AccPrivate) != 0;
 }
@@ -508,13 +680,13 @@ public final boolean isStrictfp() {
 * 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 +697,26 @@ public final boolean isViewedAsDeprecated() {
 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 (!this.isPartOfRawType()) return false;
+       if (!(targetType instanceof ReferenceBinding)) 
+               return false;
+       TypeBinding compatible = this.findSuperTypeErasingTo((ReferenceBinding)targetType.erasure());
+       if (compatible == null) 
+               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 +732,50 @@ public char[] qualifiedSourceName() {
        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 +792,7 @@ public char[] signature() /* Ljava/lang/Object; */ {
 public char[] sourceName() {
        return sourceName;
 }
+
 public ReferenceBinding superclass() {
        return null;
 }
@@ -583,6 +810,7 @@ public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
 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();
 }
index bfbb0b5..9b0209f 100644 (file)
  *******************************************************************************/
 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.HashtableOfObject;
 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;
-
-       protected Scope(int kind, Scope parent) {
-               this.kind = kind;
-               this.parent = 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;
 
-       /* 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 @@ public abstract class Scope
                return NotRelated;
        }
 
-       // Internal use only
-       protected final boolean areParametersAssignable(TypeBinding[] parameters, TypeBinding[] arguments) {
-               if (parameters == arguments)
-                       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;
+       }
 
-               int length = parameters.length;
-               if (length != arguments.length)
-                       return false;
+       public int kind;
+       public Scope parent;
+
+       protected Scope(int kind, Scope parent) {
+               this.kind = kind;
+               this.parent = parent;
+       }
 
-               for (int i = 0; i < length; i++)
-                       if (parameters[i] != arguments[i])
-                               if (!arguments[i].isCompatibleWith(parameters[i]))
-                                       return false;
-               return true;
+       /*
+        * 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 @@ public abstract class Scope
                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 abstract class Scope
        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 @@ public abstract class Scope
                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 @@ public abstract class Scope
                        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 @@ public abstract class Scope
                        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 @@ public abstract class Scope
                        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 @@ public abstract class Scope
                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 abstract class Scope
        */
        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 @@ public abstract class Scope
                // 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 @@ public abstract class Scope
                                        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 @@ public abstract class Scope
                                                        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 @@ public abstract class Scope
 
                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 @@ public abstract class Scope
                // 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 @@ public abstract class Scope
                                        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 @@ public abstract class Scope
                                                        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 @@ public abstract class Scope
 
                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 @@ public abstract class Scope
                        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 @@ public abstract class Scope
                                        }
                                }
                        }
-                       
+
                        if (currentLength == 1 && matchingMethod == null && found.size == 0) {
                                matchingMethod = currentMethods[0];
                        } else if (currentLength > 0) {
@@ -573,41 +923,65 @@ public abstract class Scope
                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 @@ public abstract class Scope
                        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 @@ public abstract class Scope
                                }
                                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 @@ public abstract class Scope
                        }
                }
                if (visiblesCount == 1) {
-                       compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
+                       unitScope.recordTypeReferences(candidates[0].thrownExceptions);
                        return candidates[0];
                }
                if (visiblesCount == 0) {
@@ -657,10 +1046,10 @@ public abstract class Scope
                        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 @@ public abstract class Scope
                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 @@ public abstract class Scope
                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 @@ public abstract class Scope
                                                // 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 @@ public abstract class Scope
                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 @@ public abstract class Scope
        }
 
        /* 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 @@ public abstract class Scope
                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 @@ public abstract class Scope
                                                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 @@ public abstract class Scope
                                                                                name,
                                                                                InheritedNameHidesEnclosingName);
                                                                }
-       
+
                                                                ProblemFieldBinding insideProblem = null;
                                                                if (fieldBinding.isValidBinding()) {
                                                                        if (!fieldBinding.isStatic()) {
@@ -954,8 +1368,7 @@ public abstract class Scope
                                                                                                        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 @@ public abstract class Scope
                                                                                                        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 @@ public abstract class Scope
                                        }
                                        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 @@ public abstract class Scope
                                        }
                                        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 abstract class Scope
 
        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 @@ public abstract class Scope
                        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 @@ public abstract class Scope
                                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 @@ public abstract class Scope
                } catch (AbortCompilation e) {
                        e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
                        throw e;
-               }
+               }                       
        }
 
        /* API
@@ -1159,17 +1623,14 @@ public abstract class Scope
         * 
         *      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 @@ public abstract class Scope
                                        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 @@ public abstract class Scope
                                                                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 @@ public abstract class Scope
                                                                                        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 @@ public abstract class Scope
                                                        }
                                                }
 
-                                               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 @@ public abstract class Scope
                        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 @@ public abstract class Scope
                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 @@ public abstract class Scope
                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 @@ public abstract class Scope
                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 @@ public abstract class Scope
                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 abstract class Scope
 
        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 @@ public abstract class Scope
                        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 @@ public abstract class Scope
                // 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 @@ public abstract class Scope
        * 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 @@ public abstract class Scope
 
                // 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 @@ public abstract class Scope
        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 @@ public abstract class Scope
                        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 @@ public abstract class Scope
                                                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 @@ public abstract class Scope
                                                                        // 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 @@ public abstract class Scope
                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 @@ public abstract class Scope
                                                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 @@ public abstract class Scope
                                                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 @@ public abstract class Scope
                }
 
                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 @@ public abstract class Scope
        }
 
        // 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 @@ public abstract class Scope
                        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 @@ public abstract class Scope
 
                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 @@ public abstract class Scope
                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 @@ public abstract class Scope
                        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 @@ public abstract class Scope
                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 @@ public abstract class Scope
                                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 @@ public abstract class Scope
                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 @@ public abstract class Scope
        * 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
-                       if (!method.isStatic()) previous = method;  // no ambiguity for static methods
+
+                       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 abstract class Scope
                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 @@ public abstract class Scope
                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 @@ public abstract class Scope
                } 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/src/org/eclipse/jdt/internal/compiler/lookup/SignatureWrapper.java b/src/org/eclipse/jdt/internal/compiler/lookup/SignatureWrapper.java
new file mode 100644 (file)
index 0000000..b4293a0
--- /dev/null
@@ -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$
+       }
+}
index e791f1e..0702691 100644 (file)
  *******************************************************************************/
 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.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 +34,17 @@ public class SourceTypeBinding extends ReferenceBinding {
        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 +113,18 @@ public void addDefaultAbstractMethods() {
 *      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 +145,7 @@ public FieldBinding addSyntheticField(LocalVariableBinding actualOuterLocalVaria
                                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 +160,20 @@ public FieldBinding addSyntheticField(LocalVariableBinding actualOuterLocalVaria
 *      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 +200,22 @@ public FieldBinding addSyntheticField(ReferenceBinding enclosingType) {
 *      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 +241,19 @@ public FieldBinding addSyntheticField(TypeBinding targetType, BlockScope blockSc
 /* 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 +274,54 @@ public FieldBinding addSyntheticField(AssertStatement assertStatement, BlockScop
                                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 +336,184 @@ public FieldBinding addSyntheticField(AssertStatement assertStatement, BlockScop
        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 +521,99 @@ void faultInTypesForFieldsAndMethods() {
        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();
+}
+public long getAnnotationTagBits() {
+       if ((this.tagBits & AnnotationResolved) == 0) {
+               TypeDeclaration typeDecl = this.scope.referenceContext;
+               typeDecl.resolveAnnotations(typeDecl.staticInitializerScope, typeDecl.annotations, this);
+       }
+       return this.tagBits;
+}
 public MethodBinding[] getDefaultAbstractMethods() {
        int count = 0;
        for (int i = methods.length; --i >= 0;)
@@ -413,7 +636,7 @@ public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
        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 +645,7 @@ public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
                        }
                }
        } 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 +662,8 @@ public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
 // 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 +699,86 @@ public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes
 
        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
 
+// 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();
-
-       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
-                               }
-                       }
-               }
-               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;
+       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
                        }
-                       return result;
+                       if (matchingMethods == null)
+                               matchingMethods = new java.util.ArrayList(2);
+                       matchingMethods.add(method);
                }
-       } 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 (matchingMethods == null) return NoMethods;
+
+       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 (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 +789,72 @@ public FieldBinding getSyntheticField(LocalVariableBinding actualOuterLocalVaria
        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 +873,10 @@ public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBi
 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 +897,83 @@ public boolean hasMemberTypes() {
 }
 // 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 +985,59 @@ private FieldBinding resolveTypeFor(FieldBinding field) {
                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 +1046,21 @@ private MethodBinding resolveTypesFor(MethodBinding method) {
                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 +1074,63 @@ private MethodBinding resolveTypesFor(MethodBinding method) {
                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 +1145,40 @@ public ReferenceBinding superclass() {
 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 +1188,9 @@ public SyntheticAccessMethodBinding[] syntheticAccessMethods() {
 
        // 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 +1210,108 @@ public FieldBinding[] syntheticFields() {
 
        // 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$
-
-       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$
-
-       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$
+    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$
+
+       buffer.append(isInterface() ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
+       buffer.append((compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED 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 +1334,11 @@ public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType, bool
        // 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;
                }
        }
  *******************************************************************************/
 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);
 }
index 521c6ea..7c08f8e 100644 (file)
@@ -34,14 +34,11 @@ public class SyntheticArgumentBinding extends LocalVariableBinding {
        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 @@ public class SyntheticArgumentBinding extends LocalVariableBinding {
 
                super(
                        CharOperation.concat(
-                               SyntheticArgumentBinding.EnclosingInstancePrefix,
+                               TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX,
                                String.valueOf(enclosingType.depth()).toCharArray()),
                        enclosingType, 
                        AccFinal,
@@ -14,33 +14,34 @@ import org.eclipse.jdt.core.compiler.CharOperation;
 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 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
                                this.parameters[0] = declaringSourceType;
                        }
                        this.targetReadField = targetField;
-                       this.accessType = FieldReadAccess;
+                       this.kind = FieldReadAccess;
                } else {
                        this.returnType = VoidBinding;
                        if (targetField.isStatic()) {
@@ -62,7 +63,7 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
                                this.parameters[1] = targetField.type;
                        }
                        this.targetWriteField = targetField;
-                       this.accessType = FieldWriteAccess;
+                       this.kind = FieldWriteAccess;
                }
                this.thrownExceptions = NoExceptions;
                this.declaringClass = declaringSourceType;
@@ -92,7 +93,7 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
                                }
                        }
                        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 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
                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 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
        }
 
        /**
+        * 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 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
                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 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
                                        }
                                }
                                // 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 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
                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 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
                                }
                        }
                        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 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
        }
 
        protected boolean isConstructorRelated() {
-               return accessType == ConstructorAccess;
+               return kind == ConstructorAccess;
        }
 }
index 556a7c4..ffc6b55 100644 (file)
  *******************************************************************************/
 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;
 }
index c6cd627..43455eb 100644 (file)
@@ -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 @@ import org.eclipse.jdt.core.compiler.CharOperation;
  */
 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 @@ public boolean canBeInstantiated() {
        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 @@ String debugName() {
 public int dimensions(){
        return 0;
 }
+/* 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 @@ public final boolean isNumericType() {
        }
 }
 
+/**
+ * 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 char[] qualifiedPackageName() {
 */
 
 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;
+}
 }
index 5f6064f..3a31669 100644 (file)
 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$
 }
index 5fe8af0..0e8beeb 100644 (file)
 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 @@ public interface TypeIds {
        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 @@ public interface TypeIds {
        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 @@ public interface TypeIds {
        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 @@ public interface TypeIds {
        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 @@ public interface TypeIds {
        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 @@ public interface TypeIds {
        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 @@ public interface TypeIds {
        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 @@ public interface TypeIds {
        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 @@ public interface TypeIds {
        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/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
new file mode 100644 (file)
index 0000000..eb4e4b1
--- /dev/null
@@ -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.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]).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() == 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() == 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
index 65ff088..3b4e74b 100644 (file)
@@ -13,29 +13,67 @@ package org.eclipse.jdt.internal.compiler.lookup;
 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;
+}
+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;
+       }
 }
-String debugName() {
+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$
index 2e06558..00bf26f 100644 (file)
@@ -13,32 +13,48 @@ package org.eclipse.jdt.internal.compiler.lookup;
 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/src/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
new file mode 100644 (file)
index 0000000..5e7de03
--- /dev/null
@@ -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;
+       }
+}
index ca99505..9b5dd5d 100644 (file)
@@ -32,6 +32,22 @@ public abstract class AbstractCommentParser {
        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 abstract class AbstractCommentParser {
        public final static int COMPIL_PARSER = 0x00000001;
        public final static int DOM_PARSER = 0x00000002;
        
-       // Public fields
+       // Parse infos
        public Scanner scanner;
+       public char[] source;
+       protected Parser sourceParser;
+       private int currentTokenType = -1;
+       
+       // Options
        public boolean checkDocComment = false;
+       public boolean reportProblems;
+       protected boolean jdk15;
        
-       // Protected fields
+       // Results
        protected boolean inherited, deprecated;
-       protected char[] source;
+       protected Object returnStatement;
+       
+       // Positions
        protected int index, endComment, lineEnd;
        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 @@ public abstract class AbstractCommentParser {
                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 @@ public abstract class AbstractCommentParser {
         * 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 {
@@ -161,15 +184,14 @@ public abstract class AbstractCommentParser {
                                
                                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,180 +213,14 @@ public abstract class AbstractCommentParser {
                                                        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 '-': 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;
-                                                                               }
-                                                                               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();
-                                                                               // 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().javadocInvalidTag(this.tagSourceStart, end);
-                                                                                       }
-                                                                               }
-                                                                               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;
                                                                        }
@@ -403,7 +259,7 @@ public abstract class AbstractCommentParser {
                                                        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);
                                                        }
@@ -436,7 +292,7 @@ public abstract class AbstractCommentParser {
                        // 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);
@@ -466,38 +322,16 @@ public abstract class AbstractCommentParser {
        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 getEndPosition() {
-               if (this.scanner.getCurrentTokenEndPosition() > this.lineEnd) {
+
+       private int getIndexPosition() {
+               if (this.index > this.lineEnd) {
                        return this.lineEnd;
                } else {
-                       return this.scanner.getCurrentTokenEndPosition();
-               }
-       }
-
-       /*
-        * 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.
-        *
-       private int getLineEnd(int lineNumber) {
-       
-               if (this.scanner.linePtr != -1) {
-                       return this.scanner.getLineEnd(lineNumber);
+                       return this.index-1;
                }
-               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
        }
-       */
 
        /**
         * Search the line number corresponding to a specific position.
@@ -533,6 +367,14 @@ public abstract class AbstractCommentParser {
                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
         */
@@ -568,7 +410,7 @@ public abstract class AbstractCommentParser {
                                        if (!verifySpaceOrEndComment()) {
                                                int end = this.starPosition == -1 ? this.lineEnd : this.starPosition;
                                                if (this.source[end]=='\n') end--;
-                                               if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
+                                               if (this.reportProblems) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
                                                return null;
                                        }
                                        this.lineStarted = true;
@@ -638,7 +480,7 @@ public abstract class AbstractCommentParser {
                                if (!verifySpaceOrEndComment()) {
                                        int end = this.starPosition == -1 ? this.lineEnd : this.starPosition;
                                        if (this.source[end]=='\n') end--;
-                                       if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
+                                       if (this.reportProblems) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
                                        return null;
                                }
                                // Create new argument
@@ -663,32 +505,48 @@ public abstract class AbstractCommentParser {
                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
+                                                       consumeToken();
                                                        // Skip all characters after string literal until closing '>' (see bug 68726)
-                                                       while (this.index <= this.lineEnd && readToken() != TerminalTokens.TokenNameGREATER) {
+                                                       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() == '>') {
@@ -710,7 +568,9 @@ public abstract class AbstractCommentParser {
                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;
        }
 
@@ -723,7 +583,7 @@ public abstract class AbstractCommentParser {
                this.identifierLengthPtr = -1;
                int start = this.scanner.getCurrentTokenStartPosition();
                this.memberStart = start;
-
+       
                // Get member identifier
                if (readToken() == TerminalTokens.TokenNameIdentifier) {
                        consumeToken();
@@ -740,28 +600,28 @@ public abstract class AbstractCommentParser {
                                                        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
                        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.sourceParser != null) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
+                               if (this.reportProblems) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
                                return null;
                        }
                        return createFieldReference(receiver);
                }
-               int end = getEndPosition() - 1;
+               int end = getTokenEndPosition() - 1;
                end = start > end ? start : end;
-               if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(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;
@@ -772,38 +632,201 @@ public abstract class AbstractCommentParser {
        /*
         * 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;
        }
 
@@ -884,36 +907,27 @@ public abstract class AbstractCommentParser {
        /*
         * Parse a reference in @see tag
         */
-       protected boolean parseReference(boolean plain) throws InvalidInputException {
-               Object typeRef = null;
-               Object reference = null;
-               int previousPosition = -1;
-               int typeRefStartPosition = -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();
-                                       consumeToken();
-                                       // 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 (expecting empty or end comment)
-                                       if (verifyEndLine(previousPosition)) {
-                                               return true;
-                                       }
-                                       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()) {
+       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();
+                                               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 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) {
@@ -921,87 +935,109 @@ public abstract class AbstractCommentParser {
                                                        previousPosition = start;
                                                        typeRef = null;
                                                }
-                                               // verify end line (expecting empty or end comment)
+                                               // verify end line
                                                if (verifyEndLine(previousPosition)) {
                                                        return true;
                                                }
-                                               if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(start, this.lineEnd);
-                                       }
-                                       return false;
-                               case TerminalTokens.TokenNameERROR :
-                                       if (this.scanner.currentCharacter == '#') { // @see ...#member
+                                               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();
-                                               reference = parseMember(typeRef);
-                                               if (reference != null) {
-                                                       return pushSeeRef(reference, plain);
+                                               start = this.scanner.getCurrentTokenStartPosition();
+                                               if (parseHref()) {
+                                                       consumeToken();
+                                                       // 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);
+                                               }
+                                               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) {
-                                               typeRefStartPosition = this.scanner.getCurrentTokenStartPosition();
-                                               typeRef = parseQualifiedName(true);
-                                               break;
-                                       }
-                                       break nextToken;
-                               default :
-                                       break nextToken;
+                                       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;
+                               }
                        }
-               }
-               
-               // 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;
-               }
 
-               // Reset position at the end of type reference
-               this.index = this.lastIdentifierEndPosition+1;
-               this.scanner.currentPosition = this.index;
-               this.currentTokenType = -1;
-
-               // 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.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(typeRefStartPosition, this.lineEnd);
-                       return false;
-               }
+                       // 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;
+                       }
 
-               // Verify that we get white space after reference
-               if (!verifySpaceOrEndComment()) {
-                       this.index = this.tokenPreviousPosition;
-                       this.scanner.currentPosition = this.tokenPreviousPosition;
+                       // Reset position at the end of type reference
+                       this.index = this.lastIdentifierEndPosition+1;
+                       this.scanner.currentPosition = this.index;
                        this.currentTokenType = -1;
-                       int end = this.starPosition == -1 ? this.lineEnd : this.starPosition;
-                       if (this.source[end]=='\n') end--;
-                       if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMalformedSeeReference(typeRefStartPosition, end);
-                       return false;
-               }
-               
-               // Everything is OK, store reference
-               return pushSeeRef(reference, plain);
-       }
 
-       /*
-        * Parse @return tag declaration
-        */
-       protected abstract boolean parseReturn();
+                       // 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;
+                       }
 
-       /*
-        * 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());
+                       // 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);
+               }
+               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;
@@ -1011,24 +1047,25 @@ public abstract class AbstractCommentParser {
        }
 
        /*
-        * 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;
        }
@@ -1036,7 +1073,7 @@ public abstract class AbstractCommentParser {
        /*
         * Return current character without move index position.
         */
-       private char peekChar() {
+       protected char peekChar() {
                int idx = this.index;
                char c = this.source[idx++];
                if (c == '\\' && this.source[idx] == 'u') {
@@ -1124,12 +1161,12 @@ public abstract class AbstractCommentParser {
        /*
         * 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 boolean pushSeeRef(Object statement);
 
        /*
         * Push a text element in ast node stack
@@ -1139,7 +1176,7 @@ public abstract class AbstractCommentParser {
        /*
         * 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.
@@ -1185,7 +1222,7 @@ public abstract class AbstractCommentParser {
                return this.currentTokenType;
        }
 
-       private int readTokenAndConsume() throws InvalidInputException {
+       protected int readTokenAndConsume() throws InvalidInputException {
                int token = readToken();
                consumeToken();
                return token;
@@ -1273,6 +1310,19 @@ public abstract class AbstractCommentParser {
         * Note that end of comment may be preceeding by several contiguous '*' chars.
         */
        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;
+               }
+               
                int startPosition = this.index;
                int previousPosition = this.index;
                this.starPosition = -1;
@@ -1282,7 +1332,7 @@ public abstract class AbstractCommentParser {
                                case '\r':
                                case '\n':
                                        if (this.kind == DOM_PARSER) {
-                                               parseTag();
+                                               createTag();
                                                pushText(textPosition, previousPosition);
                                        }
                                        this.index = previousPosition;
@@ -1298,7 +1348,7 @@ public abstract class AbstractCommentParser {
                                case '/':
                                        if (this.starPosition >= textPosition) {
                                                if (this.kind == DOM_PARSER) {
-                                                       parseTag();
+                                                       createTag();
                                                        pushText(textPosition, this.starPosition);
                                                }
                                                return true;
@@ -1316,45 +1366,6 @@ public abstract class AbstractCommentParser {
        }
 
        /*
-        * Verify that some text exists after a @return tag. Text must be different than
-        * end of comment which may be preceeding by several '*' chars.
-        */
-       private boolean verifyCharsAfterReturnTag(int startPosition) {
-               // Whitespace or inline tag closing brace
-               int previousPosition = this.index;
-               char ch = readChar();
-               boolean malformed = true;
-               while (Character.isWhitespace(ch)) {
-                       malformed = false;
-                       previousPosition = this.index;
-                       ch = readChar();        
-               }
-               // End of comment
-               this.starPosition = -1;
-               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 false;
-                                       }
-                               default :
-                                       // valid if any other character is encountered, even white spaces
-                                       this.index = startPosition;
-                                       return !malformed;
-                               
-                       }
-                       previousPosition = this.index;
-                       ch = readChar();
-               }
-               this.index = startPosition;
-               return false;
-       }
-
-       /*
         * 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
index 7786636..4d4c63b 100644 (file)
@@ -14,20 +14,8 @@ import java.util.List;
 
 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 @@ public class JavadocParser extends AbstractCommentParser {
        
        // 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 @@ public class JavadocParser extends AbstractCommentParser {
                                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 @@ public class JavadocParser extends AbstractCommentParser {
                                        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') &&
@@ -173,10 +166,11 @@ public class JavadocParser extends AbstractCommentParser {
                        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)
@@ -207,12 +201,14 @@ public class JavadocParser extends AbstractCommentParser {
                        // 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 @@ public class JavadocParser extends AbstractCommentParser {
                                        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 @@ public class JavadocParser extends AbstractCommentParser {
        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 @@ public class JavadocParser extends AbstractCommentParser {
                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];
-                                       }
-                                       int stackLength = this.invParamsStack.length;
-                                       if (++this.invParamsPtr >= stackLength) {
-                                               System.arraycopy(
-                                                       this.invParamsStack, 0,
-                                                       this.invParamsStack = new JavadocSingleNameReference[stackLength + AstStackIncrement], 0,
-                                                       stackLength);
+                       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;
                                        }
-                                       this.invParamsStack[this.invParamsPtr] = nameRef;
-                                       return false;
                                }
                        }
                        switch (this.astLengthPtr % ORDERED_TAGS_NUMBER) {
@@ -339,7 +478,7 @@ public class JavadocParser extends AbstractCommentParser {
        /*
         * 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 @@ public class JavadocParser extends AbstractCommentParser {
         * @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);
@@ -416,9 +582,9 @@ public class JavadocParser extends AbstractCommentParser {
                }
                
                // 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 @@ public class JavadocParser extends AbstractCommentParser {
                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);
+               }
        }
 }
index 81fd8d4..cedccfe 100644 (file)
@@ -24,10 +24,12 @@ 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.*;
+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.ProblemReporter;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
-public class Parser implements BindingIds, ParserBasicInformation, TerminalTokens, CompilerModifiers, OperatorIds, TypeIds {
-       protected ProblemReporter problemReporter;
-       protected CompilerOptions options;
-       public int firstToken ; // handle for multiple parsing goals
-       public int lastAct ; //handle for multiple parsing goals
-       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];
+       
+       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$
+       public static boolean VERBOSE_RECOVERY = false;
+
+
+
        protected int astLengthPtr;
        protected int[] astLengthStack;
+       protected int astPtr;
+       protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
        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 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;
-       Expression [] noExpressions = new Expression[ExpressionStackIncrement];
+       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];
+       
+       protected boolean hasError;
+       protected boolean hasReportedError;
+
        //identifiers stacks 
-       protected int identifierPtr;
-       protected char[][] identifierStack;
        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;
-       protected int endPosition; //accurate only when used ! (the start position is pushed into intStack while the end the current one)
-       protected int endStatementPosition;
+       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 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 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 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[] 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 JavadocParser javadocParser;
        public Javadoc javadoc;
-       
-       public static byte rhs[] = null;
-       public static char asb[] = null;
-       public static char asr[] = null;
-       public static char nasb[] = null;
-       public static char nasr[] = null;
-
-       public static char terminal_index[] = null;
-       public static char non_terminal_index[] = null;
-       
-       public static char term_action[] = null;
-       public static byte term_check[] = null;
-
-       private static final String UNEXPECTED_EOF = "Unexpected End Of File" ; //$NON-NLS-1$
-       private static final String INVALID_CHARACTER = "Invalid Character" ; //$NON-NLS-1$
-       private static final String EOF_TOKEN = "$eof" ; //$NON-NLS-1$
-       private static final String ERROR_TOKEN = "$error" ; //$NON-NLS-1$
-
-       public 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;
-       
-       public static char scope_prefix[] = null;
-    public static char scope_suffix[] = null;
-    public static char scope_lhs[] = null;
-    
-    public static byte scope_la[] = null;
-
-    public static char scope_state_set[] = null;
-    public static char scope_rhs[] = null;
-    public static char scope_state[] = null;
-    public static char in_symb[] = null;
-    
-       private final static String FILEPREFIX = "parser"; //$NON-NLS-1$
-       private final static String READABLE_NAMES_FILE = "readableNames"; //$NON-NLS-1$
-       private final static String READABLE_NAMES =
-               "org.eclipse.jdt.internal.compiler.parser." + READABLE_NAMES_FILE; //$NON-NLS-1$
+       public JavadocParser javadocParser;
+       // used for recovery
+       protected int lastJavadocEnd;
 
        static {
                try{
@@ -157,136 +191,21 @@ public class Parser implements BindingIds, ParserBasicInformation, TerminalToken
                        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 @@ private static void buildFileForReadableName(
        
        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 @@ private static void buildFileForReadableName(
        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 @@ private final static void buildFileForTable(String filename, char[] chars) throw
        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 @@ public final static void buildFilesFromLPG(String dataFilename, String dataFilen
        //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 @@ public final static void buildFilesFromLPG(String dataFilename, String dataFilen
        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 @@ public final static void buildFilesFromLPG(String dataFilename, String dataFilen
        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,78 +472,319 @@ public final static void buildFilesFromLPG(String dataFilename, String dataFilen
                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$
 }
-/*
- * Build initial recovery state.
- * Recovery state is inferred from the current state of the parser (reduced node stack).
- */
-public RecoveredElement buildInitialRecoveryState(){
+public static int in_symbol(int state) {
+       return in_symb[original_state(state)];
+}
+public final static void initTables() throws java.io.IOException {
 
-       /* initialize recovery by retrieving available reduced nodes 
-        * also rebuild bracket balance 
-        */
-       this.lastCheckPoint = 0;
+       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 {
 
-       RecoveredElement element = null;
-       if (this.referenceContext instanceof CompilationUnitDeclaration){
-               element = new RecoveredUnit(this.compilationUnit, 0, this);
-               
-               /* ignore current stack state, since restarting from the beginnning 
-                  since could not trust simple brace count */
-               if (true){ // experimenting restart recovery from scratch
-                       this.compilationUnit.currentPackage = null;
-                       this.compilationUnit.imports = null;
-                       this.compilationUnit.types = null;
-                       this.currentToken = 0;
-                       this.listLength = 0;
-                       this.endPosition = 0;
-                       this.endStatementPosition = 0;
-                       return element;
-               }
-               if (this.compilationUnit.currentPackage != null){
-                       this.lastCheckPoint = this.compilationUnit.currentPackage.declarationSourceEnd+1;
-               }
-               if (this.compilationUnit.imports != null){
-                       this.lastCheckPoint = this.compilationUnit.imports[this.compilationUnit.imports.length -1].declarationSourceEnd+1;              
-               }
-       } else {
-               if (this.referenceContext instanceof AbstractMethodDeclaration){
-                       element = new RecoveredMethod((AbstractMethodDeclaration) this.referenceContext, null, 0, this);
-                       this.lastCheckPoint = ((AbstractMethodDeclaration) this.referenceContext).bodyStart;
-               } else {
-                       /* Initializer bodies are parsed in the context of the type declaration, we must thus search it inside */
-                       if (this.referenceContext instanceof TypeDeclaration){
-                               TypeDeclaration type = (TypeDeclaration) this.referenceContext;
-                               for (int i = 0; i < type.fields.length; i++){
-                                       FieldDeclaration field = type.fields[i];                                        
-                                       if (field != null
-                                               && !field.isField()
-                                               && field.declarationSourceStart <= this.scanner.initialPosition
-                                               && this.scanner.initialPosition <= field.declarationSourceEnd
-                                               && this.scanner.eofPosition <= field.declarationSourceEnd+1){
-                                               element = new RecoveredInitializer(field, null, 1, this);
-                                               this.lastCheckPoint = field.declarationSourceStart;                                     
-                                               break;
-                                       }
-                               }
-                       } 
+       //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
                }
        }
-
-       if (element == null) return element;
+       return bytes;
+}
        
-       for(int i = 0; i <= this.astPtr; i++){
-               ASTNode node = this.astStack[i];
-               if (node instanceof AbstractMethodDeclaration){
+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).
+ */
+public RecoveredElement buildInitialRecoveryState(){
+
+       /* initialize recovery by retrieving available reduced nodes 
+        * also rebuild bracket balance 
+        */
+       this.lastCheckPoint = 0;
+       this.lastErrorEndPositionBeforeRecovery = this.scanner.currentPosition;
+
+       RecoveredElement element = null;
+       if (this.referenceContext instanceof CompilationUnitDeclaration){
+               element = new RecoveredUnit(this.compilationUnit, 0, this);
+               
+               /* ignore current stack state, since restarting from the beginnning 
+                  since could not trust simple brace count */
+               if (true){ // experimenting restart recovery from scratch
+                       this.compilationUnit.currentPackage = null;
+                       this.compilationUnit.imports = null;
+                       this.compilationUnit.types = null;
+                       this.currentToken = 0;
+                       this.listLength = 0;
+                       this.listTypeParameterLength = 0;
+                       this.endPosition = 0;
+                       this.endStatementPosition = 0;
+                       return element;
+               }
+               if (this.compilationUnit.currentPackage != null){
+                       this.lastCheckPoint = this.compilationUnit.currentPackage.declarationSourceEnd+1;
+               }
+               if (this.compilationUnit.imports != null){
+                       this.lastCheckPoint = this.compilationUnit.imports[this.compilationUnit.imports.length -1].declarationSourceEnd+1;              
+               }
+       } else {
+               if (this.referenceContext instanceof AbstractMethodDeclaration){
+                       element = new RecoveredMethod((AbstractMethodDeclaration) this.referenceContext, null, 0, this);
+                       this.lastCheckPoint = ((AbstractMethodDeclaration) this.referenceContext).bodyStart;
+               } else {
+                       /* Initializer bodies are parsed in the context of the type declaration, we must thus search it inside */
+                       if (this.referenceContext instanceof TypeDeclaration){
+                               TypeDeclaration type = (TypeDeclaration) this.referenceContext;
+                               for (int i = 0; i < type.fields.length; i++){
+                                       FieldDeclaration field = type.fields[i];                                        
+                                       if (field != null
+                                               && field.getKind() == AbstractVariableDeclaration.INITIALIZER
+                                               && field.declarationSourceStart <= this.scanner.initialPosition
+                                               && this.scanner.initialPosition <= field.declarationSourceEnd
+                                               && this.scanner.eofPosition <= field.declarationSourceEnd+1){
+                                               element = new RecoveredInitializer(field, null, 1, this);
+                                               this.lastCheckPoint = field.declarationSourceStart;                                     
+                                               break;
+                                       }
+                               }
+                       } 
+               }
+       }
+
+       if (element == null) return element;
+       
+       for(int i = 0; i <= this.astPtr; i++){
+               ASTNode node = this.astStack[i];
+               if (node instanceof AbstractMethodDeclaration){
                        AbstractMethodDeclaration method = (AbstractMethodDeclaration) node;
                        if (method.declarationSourceEnd == 0){
                                element = element.add(method, 0);
@@ -586,16 +840,14 @@ public RecoveredElement buildInitialRecoveryState(){
        }
        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 final void checkAndSetModifiers(int flag){
 }
 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 @@ public void checkComment() {
                // 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 void checkNonNLSAfterBodyEnd(int declarationEnd){
                }
        }
 }
-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 @@ protected void classInstanceCreation(boolean alwaysQualified) {
                && (this.astStack[this.astPtr] == null)) {
                //NO ClassBody
                this.astPtr--;
-               if (alwaysQualified) {
+               if (hasClassBody) {
                        alloc = new QualifiedAllocationExpression();
                } else {
                        alloc = new AllocationExpression();
@@ -703,6 +940,7 @@ protected void classInstanceCreation(boolean alwaysQualified) {
                                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 @@ protected void classInstanceCreation(boolean alwaysQualified) {
                }
                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 @@ protected void consumeAllocationHeader() {
                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,16 +1027,140 @@ protected void consumeAllocationHeader() {
        this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position
        this.restartRecovery = true; // request to restart from here on
 }
-protected void consumeArgumentList() {
-       // ArgumentList ::= ArgumentList ',' Expression
-       concatExpressionLists();
+protected void consumeAnnotationAsModifier() {
+       // nothing to do
 }
-protected void consumeArrayAccess(boolean unspecifiedReference) {
-       // ArrayAccess ::= Name '[' Expression ']' ==> true
-       // ArrayAccess ::= PrimaryNoNewArray '[' Expression ']' ==> false
-
+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);
+       }
 
-       //optimize push/pop
+       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
+
+
+       //optimize push/pop
        Expression exp;
        if (unspecifiedReference) {
                exp = 
@@ -802,12 +1179,15 @@ protected void consumeArrayAccess(boolean unspecifiedReference) {
        }
        exp.sourceEnd = this.endPosition;
 }
-protected void consumeArrayCreationExpressionWithoutInitializer() {
-       // ArrayCreationWithoutArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs
-       // ArrayCreationWithoutArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs
+protected void consumeArrayCreationExpressionWithInitializer() {
+       // ArrayCreationWithArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializer
+       // ArrayCreationWithArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializer
 
        int length;
        ArrayAllocationExpression aae = new ArrayAllocationExpression();
+       this.expressionLengthPtr -- ;
+       aae.initializer = (ArrayInitializer) this.expressionStack[this.expressionPtr--];
+               
        aae.type = getTypeReference(0);
        length = (this.expressionLengthStack[this.expressionLengthPtr--]);
        this.expressionPtr -= length ;
@@ -825,19 +1205,12 @@ protected void consumeArrayCreationExpressionWithoutInitializer() {
        }
        pushOnExpressionStack(aae);
 }
-
-protected void consumeArrayCreationHeader() {
-       // nothing to do
-}
-protected void consumeArrayCreationExpressionWithInitializer() {
-       // ArrayCreationWithArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializer
-       // ArrayCreationWithArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializer
+protected void consumeArrayCreationExpressionWithoutInitializer() {
+       // ArrayCreationWithoutArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs
+       // ArrayCreationWithoutArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs
 
        int length;
        ArrayAllocationExpression aae = new ArrayAllocationExpression();
-       this.expressionLengthPtr -- ;
-       aae.initializer = (ArrayInitializer) this.expressionStack[this.expressionPtr--];
-               
        aae.type = getTypeReference(0);
        length = (this.expressionLengthStack[this.expressionLengthPtr--]);
        this.expressionPtr -= length ;
@@ -855,19 +1228,23 @@ protected void consumeArrayCreationExpressionWithInitializer() {
        }
        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 @@ protected void consumeBinaryExpression(int op) {
                                                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 @@ protected void consumeCaseLabel() {
        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,35 +1546,152 @@ protected void consumeCastExpressionLL1() {
        updateSourcePosition(cast);
        cast.sourceEnd=exp.sourceEnd;
 }
-protected void consumeCatches() {
-       // Catches ::= Catches CatchClause
-       optimizedConcatNodeLists();
+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 consumeCatchHeader() {
-       // CatchDeclaration ::= 'catch' '(' FormalParameter ')' '{'
+protected void consumeCastExpressionWithNameArray() {
+       // CastExpression ::= PushLPAREN Name Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus
 
-       if (this.currentElement == null){
-               return; // should never occur, this consumeRule is only used in recovery mode
-       }
-       // current element should be a block due to the presence of the opening brace
-       if (!(this.currentElement instanceof RecoveredBlock)){
-               if(!(this.currentElement instanceof RecoveredMethod)) {
-                       return;
-               }
-               RecoveredMethod rMethod = (RecoveredMethod) this.currentElement;
-               if(!(rMethod.methodBody == null && rMethod.bracketBalance > 0)) {
-                       return;
-               }
-       }
+       Expression exp, cast, castType;
+       int end = this.intStack[this.intPtr--];
        
-       Argument arg = (Argument)this.astStack[this.astPtr--];
-       // convert argument to local variable
-       LocalDeclaration localDeclaration = new LocalDeclaration(arg.name, arg.sourceStart, arg.sourceEnd);
-       localDeclaration.type = arg.type;
-       localDeclaration.declarationSourceStart = arg.declarationSourceStart;
-       localDeclaration.declarationSourceEnd = arg.declarationSourceEnd;
+       // handle type arguments
+       pushOnGenericsLengthStack(0);
+       pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
        
-       this.currentElement = this.currentElement.add(localDeclaration, 0);
+       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();
+}
+protected void consumeCatchHeader() {
+       // CatchDeclaration ::= 'catch' '(' FormalParameter ')' '{'
+
+       if (this.currentElement == null){
+               return; // should never occur, this consumeRule is only used in recovery mode
+       }
+       // current element should be a block due to the presence of the opening brace
+       if (!(this.currentElement instanceof RecoveredBlock)){
+               if(!(this.currentElement instanceof RecoveredMethod)) {
+                       return;
+               }
+               RecoveredMethod rMethod = (RecoveredMethod) this.currentElement;
+               if(!(rMethod.methodBody == null && rMethod.bracketBalance > 0)) {
+                       return;
+               }
+       }
+       
+       Argument arg = (Argument)this.astStack[this.astPtr--];
+       // convert argument to local variable
+       LocalDeclaration localDeclaration = new LocalDeclaration(arg.name, arg.sourceStart, arg.sourceEnd);
+       localDeclaration.type = arg.type;
+       localDeclaration.declarationSourceStart = arg.declarationSourceStart;
+       localDeclaration.declarationSourceEnd = arg.declarationSourceEnd;
+       
+       this.currentElement = this.currentElement.add(localDeclaration, 0);
        this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position
        this.restartRecovery = true; // request to restart from here on
        this.lastIgnoredToken = -1;
@@ -1123,7 +1729,7 @@ protected void consumeClassBodyDeclarationsopt() {
 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 @@ protected void consumeClassDeclaration() {
        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 consumeClassHeader() {
 }
 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 @@ protected void consumeClassHeaderImplements() {
                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 @@ protected void consumeClassHeaderImplements() {
                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 @@ protected void consumeClassHeaderName() {
        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 @@ protected void consumeClassHeaderName() {
        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,71 @@ protected void consumeClassInstanceCreationExpressionName() {
 protected void consumeClassInstanceCreationExpressionQualified() {
        // ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
        // ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
+       classInstanceCreation(true);
+
+       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 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--;
 
-       classInstanceCreation(true); //  <-- push the Qualifed....
+               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 = 
@@ -1282,10 +1987,74 @@ protected void consumeClassInstanceCreationExpressionQualified() {
        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 @@ protected void consumeClassTypeList() {
        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 @@ protected void consumeConditionalExpression(int op) {
                        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 @@ protected void consumeConstructorDeclaration() {
        // 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 @@ protected void consumeConstructorDeclaration() {
        }
 
        //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,73 @@ protected void consumeConstructorHeaderName() {
        //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;
+
+       //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){
+               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;
@@ -1465,7 +2304,7 @@ protected void consumeConstructorHeaderName() {
        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){
@@ -1487,6 +2326,7 @@ protected void consumeDefaultModifiers() {
        pushOnIntStack(
                this.modifiersSourceStart >= 0 ? this.modifiersSourceStart : this.scanner.startPosition); 
        resetModifiers();
+       pushOnExpressionStackLengthStack(0); // no annotation
 }
 protected void consumeDiet() {
        // Diet ::= $empty
@@ -1513,11 +2353,19 @@ protected void consumeDimWithOrWithOutExprs() {
        // DimWithOrWithOutExprs ::= DimWithOrWithOutExprs DimWithOrWithOutExpr
        concatExpressionLists();
 }
+protected void consumeEmptyAnnotationTypeMemberDeclarationsopt() {
+       // AnnotationTypeMemberDeclarationsopt ::= $empty
+       pushOnAstLengthStack(0);
+}
 protected void consumeEmptyArgumentListopt() {
        // ArgumentListopt ::= $empty
        pushOnExpressionStackLengthStack(0);
 }
-protected void consumeEmptyArrayInitializer() {
+protected void consumeEmptyArguments() {
+       // Argumentsopt ::= $empty
+       pushOnExpressionStackLengthStack(0);
+}
+protected void consumeEmptyArrayInitializer() {
        // ArrayInitializer ::= '{' ,opt '}'
        arrayInitializer(0);
 }
@@ -1543,10 +2391,21 @@ protected void consumeEmptyClassMemberDeclaration() {
        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 @@ protected void consumeEmptyForUpdateopt() {
        // ForUpdateopt ::= $empty
        pushOnExpressionStackLengthStack(0);
 }
-protected void consumeEmptyImportDeclarationsopt() {
-       // ImportDeclarationsopt ::= $empty
-       pushOnAstLengthStack(0);
-}
 protected void consumeEmptyInterfaceMemberDeclaration() {
        // InterfaceMemberDeclaration ::= ';'
        pushOnAstLengthStack(0);
@@ -1571,6 +2426,19 @@ protected void consumeEmptyInterfaceMemberDeclarationsopt() {
        // 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,132 @@ protected void consumeEmptyTypeDeclaration() {
        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;
+       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
+       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;
-       alloc = anonymousType.allocation = new QualifiedAllocationExpression(anonymousType); 
+       QualifiedAllocationExpression alloc = new QualifiedAllocationExpression(anonymousType); 
        markEnclosingMemberWithLocalType();
        pushOnAstStack(anonymousType);
 
@@ -1615,7 +2598,7 @@ protected void consumeEnterAnonymousClassBody() {
                        0, 
                        argumentLength); 
        }
-       alloc.type = getTypeReference(0);
+       alloc.type = typeReference;
 
        anonymousType.sourceEnd = alloc.sourceEnd;
        //position at the type while it impacts the anonymous declaration
@@ -1667,6 +2650,16 @@ protected void consumeEnterVariable() {
                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 @@ protected void consumeEnterVariable() {
                        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 @@ protected void consumeEnterVariable() {
                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 @@ protected void consumeEnterVariable() {
                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 @@ protected void consumeEqualityExpression(int op) {
                        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 @@ protected void consumeExitVariableWithoutInitialization() {
        
        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 @@ protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
        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 @@ protected void consumeFieldDeclaration() {
        // 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 @@ protected void consumeFieldDeclaration() {
                        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 @@ protected void consumeForInit() {
        // 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 @@ protected void consumeFormalParameter() {
                        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 @@ protected void consumeFormalParameterListopt() {
        // FormalParameterListopt ::= $empty
        pushOnAstLengthStack(0);
 }
-protected void consumeImportDeclarations() {
-       // ImportDeclarations ::= ImportDeclarations ImportDeclaration 
-       optimizedConcatNodeLists();
+protected void consumeGenericType() {
+       // nothing to do
+       // Will be consume by a getTypeRefence call
 }
-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 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 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 @@ protected void consumeInstanceOfExpression(int op) {
        }
        //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 @@ protected void consumeInterfaceHeaderExtends() {
                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 @@ protected void consumeInterfaceHeaderExtends() {
                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 @@ protected void consumeInterfaceHeaderName() {
        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 consumeInterfaceMemberDeclarationsopt() {
 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 @@ protected void consumeInterfaceTypeList() {
        // 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 @@ protected void consumeLocalVariableDeclaration() {
        // 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 consumeLocalVariableDeclarationStatement() {
        }
 
 }
+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 @@ protected void consumeMethodDeclaration(boolean isNotAbstract) {
        // 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 @@ protected void consumeMethodDeclaration(boolean isNotAbstract) {
                        }
                }
        }
-       // 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 @@ protected void consumeMethodHeader() {
        }
        // 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 @@ protected void consumeMethodHeader() {
                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,72 @@ protected void consumeMethodHeaderExtendedDims() {
                }               
        }
 }
-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];
+       long selectorSource = this.identifierPositionStack[this.identifierPtr--];
+       this.identifierLengthPtr--;
+       //type
+       md.returnType = getTypeReference(this.intStack[this.intPtr--]);
+       //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;
+
+       //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 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];
@@ -2281,9 +3888,24 @@ protected void consumeMethodHeaderName() {
        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;
@@ -2293,7 +3915,7 @@ protected void consumeMethodHeaderName() {
        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 +3932,7 @@ protected void consumeMethodHeaderName() {
                }
        }               
 }
-protected void consumeMethodHeaderParameters() {
+protected void consumeMethodHeaderRightParen() {
        // MethodHeaderParameters ::= FormalParameterListopt ')'
        int length = this.astLengthStack[this.astLengthPtr--];
        this.astPtr -= length;
@@ -2326,7 +3948,7 @@ protected void consumeMethodHeaderParameters() {
                        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 @@ protected void consumeMethodHeaderThrowsClause() {
                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 @@ protected void consumeMethodInvocationName() {
        }
        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 @@ protected void consumeMethodInvocationPrimary() {
        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 @@ protected void consumeMethodInvocationSuper() {
        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 @@ protected void consumeModifiers() {
        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 @@ protected void consumeNestedType() {
        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 @@ protected void consumeOnlySynchronized() {
        // 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 @@ protected void consumePackageDeclarationName() {
                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 @@ protected void consumePackageDeclarationName() {
                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,67 +4259,172 @@ protected void consumePackageDeclarationName() {
                this.restartRecovery = true; // used to avoid branching back into the regular automaton         
        }       
 }
-protected void consumePostfixExpression() {
-       // PostfixExpression ::= Name
-       pushOnExpressionStack(getUnspecifiedReferenceOptimized());
-}
-protected void consumePrimaryNoNewArray() {
-       // PrimaryNoNewArray ::=  PushLPAREN Expression PushRPAREN 
-       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 consumePrimaryNoNewArrayArrayType() {
-       // PrimaryNoNewArray ::= ArrayType '.' 'class'
-       this.intPtr--;
-       pushOnExpressionStack(
-               new ClassLiteralAccess(this.intStack[this.intPtr--],
-               getTypeReference(this.intStack[this.intPtr--])));
-}
-protected void consumePrimaryNoNewArrayName() {
-       // PrimaryNoNewArray ::= Name '.' 'class'
-       this.intPtr--;
-       pushOnExpressionStack(
-               new ClassLiteralAccess(this.intStack[this.intPtr--],
-               getTypeReference(0)));
-}
-protected void consumePrimaryNoNewArrayNameSuper() {
-       // PrimaryNoNewArray ::= Name '.' 'super'
-       pushOnExpressionStack(
-               new QualifiedSuperReference(
-                       getTypeReference(0),
-                       this.intStack[this.intPtr--],
-                       this.endPosition));
-}
-protected void consumePrimaryNoNewArrayNameThis() {
-       // PrimaryNoNewArray ::= Name '.' 'this'
-       pushOnExpressionStack(
+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());
+}
+protected void consumePrimaryNoNewArray() {
+       // PrimaryNoNewArray ::=  PushLPAREN Expression PushRPAREN 
+       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 consumePrimaryNoNewArrayArrayType() {
+       // 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--])));
+}
+protected void consumePrimaryNoNewArrayName() {
+       // PrimaryNoNewArray ::= Name '.' 'class'
+       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--], typeReference));
+}
+protected void consumePrimaryNoNewArrayNameSuper() {
+       // PrimaryNoNewArray ::= Name '.' 'super'
+       // handle type arguments
+       pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+       pushOnGenericsLengthStack(0);
+       TypeReference typeReference = getTypeReference(0);
+
+       pushOnExpressionStack(
+               new QualifiedSuperReference(
+                       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 @@ protected void consumeQualifiedName() {
 
        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 @@ protected void consumeRightParen() {
 }
 // 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 : // 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 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 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 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 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 @@ protected void consumeSimpleAssertStatement() {
        this.expressionLengthPtr--;
        pushOnAstStack(new AssertStatement(this.expressionStack[this.expressionPtr--], this.intStack[this.intPtr--]));  
 }
-       
-protected void consumeSingleTypeImportDeclaration() {
-       // SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName ';'
+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 = (ImportReference) this.astStack[this.astPtr];
-       // flush comments defined prior to import statements
-       impt.declarationEnd = this.endStatementPosition;
-       impt.declarationSourceEnd = 
-               this.flushCommentsDefinedPriorTo(impt.declarationSourceEnd); 
+       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)
+       
+       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(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 @@ protected void consumeSingleTypeImportDeclarationName() {
                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 consumeSingleTypeImportDeclarationName() {
 }
 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 consumeStatementCatch() {
 }
 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 consumeStatementContinue() {
 }
 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 consumeStatementContinueWithLabel() {
 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 @@ protected void consumeStatementFor() {
                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 @@ protected void consumeStatementFor() {
                                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 consumeStatementLabel() {
 }
 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 @@ protected void consumeStatementWhile() {
                        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 @@ protected void consumeToken(int type) {
        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 @@ protected void consumeToken(int type) {
                                        this.scanner.getCurrentTokenSource(), 
                                        this.scanner.startPosition, 
                                        this.scanner.currentPosition - 1)); 
-//                     this.scanner.commentPtr = -1;
                        break;
                case TokenNameLongLiteral :
                        pushOnExpressionStack(
@@ -4047,7 +6785,6 @@ protected void consumeToken(int type) {
                                        this.scanner.getCurrentTokenSource(), 
                                        this.scanner.startPosition, 
                                        this.scanner.currentPosition - 1)); 
-//                     this.scanner.commentPtr = -1;
                        break;
                case TokenNameFloatingPointLiteral :
                        pushOnExpressionStack(
@@ -4055,7 +6792,6 @@ protected void consumeToken(int type) {
                                        this.scanner.getCurrentTokenSource(), 
                                        this.scanner.startPosition, 
                                        this.scanner.currentPosition - 1)); 
-//                     this.scanner.commentPtr = -1;
                        break;
                case TokenNameDoubleLiteral :
                        pushOnExpressionStack(
@@ -4063,7 +6799,6 @@ protected void consumeToken(int type) {
                                        this.scanner.getCurrentTokenSource(), 
                                        this.scanner.startPosition, 
                                        this.scanner.currentPosition - 1)); 
-//                     this.scanner.commentPtr = -1;
                        break;
                case TokenNameCharacterLiteral :
                        pushOnExpressionStack(
@@ -4071,7 +6806,6 @@ protected void consumeToken(int type) {
                                        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 @@ protected void consumeToken(int type) {
                                        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 @@ protected void consumeToken(int type) {
                        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 @@ protected void consumeToken(int type) {
                        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 @@ protected void consumeToken(int type) {
                        //  case TokenNameOR  :
                        //  case TokenNameDIVIDE :
                        //  case TokenNameGREATER  :
-                       //  case TokenNameLESS  :
        }
 }
-protected void consumeTypeDeclarations() {
-       // TypeDeclarations ::= TypeDeclarations TypeDeclaration
-       concatNodeLists();
+protected void consumeTypeArgument() {
+       pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--]));    
 }
-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 consumeTypeArgumentList() {
+       concatGenericsLists();
 }
-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); 
+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--;
 
-       // 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
+       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 consumeTypeImportOnDemandDeclarationName() {
        // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
        /* push an ImportRef build from the last name 
@@ -4251,7 +7013,7 @@ protected void consumeTypeImportOnDemandDeclarationName() {
                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 @@ protected void consumeTypeImportOnDemandDeclarationName() {
                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 @@ protected void consumeUnaryExpression(int op) {
        //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 @@ protected void consumeUnaryExpression(int op, boolean post) {
        // ++ 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 @@ protected void consumeVariableInitializers() {
        // 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 boolean containsComment(int sourceStart, int sourceEnd) {
 }
 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 @@ public MethodDeclaration convertToMethodDeclaration(ConstructorDeclaration c, Co
        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 FieldDeclaration createFieldDeclaration(char[] fieldDeclarationName, i
 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 @@ public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, Compila
        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 @@ protected void dispatchDeclarationInto(int length) {
                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 @@ protected void dispatchDeclarationInto(int length) {
                                                size1 - length2, 
                                                length2); 
                                        break;
-                               case 3 :
+                               case 2 :
                                        size2 += (length2 = end - start);
                                        System.arraycopy(
                                                this.astStack, 
@@ -4464,7 +7438,7 @@ protected void dispatchDeclarationInto(int length) {
                                                size2 - length2, 
                                                length2); 
                                        break;
-                               case 4 :
+                               case 3 :
                                        size3 += (length2 = end - start);
                                        System.arraycopy(
                                                this.astStack, 
@@ -4484,6 +7458,95 @@ protected void dispatchDeclarationInto(int length) {
                }
        }
 }
+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 @@ public int flushCommentsDefinedPriorTo(int position) {
        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 @@ public int[] getJavaDocPositions() {
                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 @@ public int[] getJavaDocPositions() {
                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 @@ This variable is a type reference and dim will be its dimensions*/
        }
        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 @@ protected NameReference getUnspecifiedReferenceOptimized() {
                                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 @@ protected NameReference getUnspecifiedReferenceOptimized() {
                        (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 @@ public void goForCompilationUnit(){
        //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 goForGenericMethodDeclaration(){
 }
 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 @@ public void goForInitializer(){
        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 @@ protected void ignoreInvalidConstructorDeclaration(boolean hasBody) {
        // 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 @@ protected void ignoreMethodBody() {
        // 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 @@ public void initialize() {
        }
        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 @@ public void initialize() {
        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 @@ public void initializeScanner(){
                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 void markInitializersWithLocalType(TypeDeclaration type) {
 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 @@ protected boolean moveRecoveryCheckpoint() {
        }
        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 @@ protected boolean moveRecoveryCheckpoint() {
        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 @@ protected boolean moveRecoveryCheckpoint() {
        }
        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 @@ protected MessageSend newMessageSend() {
        }
        return m;
 }
-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 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;
 }
-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 @@ called in order to remember (when needed) the consumed token */
 // (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 @@ protected void parse() {
                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 @@ protected void parse() {
                }
                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 @@ protected void parse() {
                        }
                        break ProcessTerminals;
                }
+                       
                ProcessNonTerminals : do { /* reduce */
                        consumeRule(act);
                        this.stateStackTop -= (rhs[act] - 1);
@@ -5377,68 +8490,7 @@ protected void parse() {
        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 @@ public void parse(
 }
 // 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, 
@@ -5619,94 +8722,43 @@ public void parse(MethodDeclaration md, CompilationUnitDeclaration unit) {
 
        initialize();
        goForBlockStatementsopt();
-       this.nestedMethod[this.nestedType]++;
-       pushOnRealBlockStack(0);
-
-       this.referenceContext = md;
-       this.compilationUnit = unit;
-
-       this.scanner.resetTo(md.bodyStart, md.bodyEnd);
-       // reset the scanner to parser from { down to }
-       try {
-               parse();
-       } catch (AbortCompilation ex) {
-               this.lastAct = ERROR_ACTION;
-       } finally {
-               this.nestedMethod[this.nestedType]--;           
-       }
-
-       checkNonNLSAfterBodyEnd(md.declarationSourceEnd);
-       
-       if (this.lastAct == ERROR_ACTION) {
-               return;
-       }
-
-       //refill statements
-       md.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
-       int length;
-       if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
-               System.arraycopy(
-                       this.astStack, 
-                       (this.astPtr -= length) + 1, 
-                       md.statements = new Statement[length], 
-                       0, 
-                       length); 
-       } else {
-               if (!containsComment(md.bodyStart, md.bodyEnd)) {
-                       md.bits |= ASTNode.UndocumentedEmptyBlockMASK;
-               }
-       }
-}
-// 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 */
+       this.nestedMethod[this.nestedType]++;
+       pushOnRealBlockStack(0);
+
+       this.referenceContext = md;
+       this.compilationUnit = unit;
+
+       this.scanner.resetTo(md.bodyStart, md.bodyEnd);
+       // reset the scanner to parser from { down to }
+       try {
                parse();
+       } catch (AbortCompilation ex) {
+               this.lastAct = ERROR_ACTION;
        } finally {
-               unit = this.compilationUnit;
-               this.compilationUnit = null; // reset parser
-               // tag unit has having read bodies
-               if (!this.diet) unit.bits |= ASTNode.HasAllMethodBodies;                
+               this.nestedMethod[this.nestedType]--;           
+       }
+
+       checkNonNLSAfterBodyEnd(md.declarationSourceEnd);
+       
+       if (this.lastAct == ERROR_ACTION) {
+               return;
+       }
+
+       //refill statements
+       md.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
+       int length;
+       if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+               System.arraycopy(
+                       this.astStack, 
+                       (this.astPtr -= length) + 1, 
+                       md.statements = new Statement[length], 
+                       0, 
+                       length); 
+       } else {
+               if (!containsComment(md.bodyStart, md.bodyEnd)) {
+                       md.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+               }
        }
-       return unit;
 }
 public ASTNode[] parseClassBodyDeclarations(char[] source, int offset, int length, CompilationUnitDeclaration unit) {
        /* automaton initialization */
@@ -5771,6 +8823,31 @@ public Expression parseExpression(char[] source, int offset, int length, Compila
 
        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 @@ protected void pushOnExpressionStackLengthStack(int pos) {
        }
        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 @@ protected void pushOnRealBlockStack(int i){
        }
        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 @@ public void recoveryTokenCheck() {
                                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 @@ public void recoveryTokenCheck() {
        }
        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 @@ protected void resetStacks() {
        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 void resetStacks() {
  */
 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 @@ protected boolean resumeAfterRecovery() {
        // 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 @@ protected boolean resumeOnSyntaxError() {
        /* 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 updateSourceDeclarationParts(int variableDeclaratorsCounter) {
 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
index bdb077b..6360b0f 100644 (file)
@@ -12,25 +12,24 @@ package org.eclipse.jdt.internal.compiler.parser;
 
 /*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
index 4133b61..a3849d4 100644 (file)
@@ -13,6 +13,7 @@ package org.eclipse.jdt.internal.compiler.parser;
 /**
  * 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 String toString(int tab){
 }
 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 FieldDeclaration updatedFieldDeclaration(){
 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 @@ public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
                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);  
index 66d1aae..ed9d6c3 100644 (file)
@@ -156,7 +156,7 @@ public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceV
        }
        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;
index b76bf04..64e38f5 100644 (file)
@@ -23,6 +23,7 @@ import org.eclipse.jdt.internal.compiler.ast.Statement;
 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 @@ public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceV
                }
                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 @@ public void updateFromParserState(){
                                                }
                                        }
                                        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 void updateFromParserState(){
                }
        }
 }
+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.
index 9ac355e..c93242e 100644 (file)
@@ -12,12 +12,15 @@ package org.eclipse.jdt.internal.compiler.parser;
 
 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 class RecoveredType extends RecoveredStatement implements TerminalTokens,
        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 @@ public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bra
        }
        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 @@ public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanc
                                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 @@ public RecoveredElement add(TypeDeclaration memberTypeDeclaration, int bracketBa
                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 int bodyEnd(){
 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 @@ public TypeDeclaration updatedTypeDeclaration(){
        /* 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 @@ public TypeDeclaration updatedTypeDeclaration(){
                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 @@ public TypeDeclaration updatedTypeDeclaration(){
                }
                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 @@ public TypeDeclaration updatedTypeDeclaration(){
                                }
                                parentElement = parentElement.parent;
                        }
-                       typeDeclaration.createsInternalConstructor(!parser().diet || insideFieldInitializer, true);
+                       typeDeclaration.createDefaultConstructor(!parser().diet || insideFieldInitializer, true);
                } 
        }
        if (parent instanceof RecoveredType){
@@ -409,6 +437,30 @@ public void updateFromParserState(){
                                // 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 @@ public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
                        case -1 :
                        case TokenNameextends :
                        case TokenNameimplements :
+                       case TokenNameGREATER :
+                       case TokenNameRIGHT_SHIFT :
+                       case TokenNameUNSIGNED_RIGHT_SHIFT :
                                if (parser.recoveredStaticInitializerStart == 0) break;
                        default:
                                this.foundOpeningBrace = true;                          
index 61b1f53..73a9e49 100644 (file)
@@ -15,9 +15,11 @@ package org.eclipse.jdt.internal.compiler.parser;
  */
 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 @@ public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bra
        /* 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
index 70e8242..6ec4cf4 100644 (file)
@@ -14,6 +14,7 @@ import java.util.Iterator;
 
 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 @@ public class Scanner implements TerminalTokens {
         - 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 class Scanner implements TerminalTokens {
        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 class Scanner implements TerminalTokens {
        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 class Scanner implements TerminalTokens {
        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 @@ public Scanner(
        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 @@ public  final boolean atEnd() {
        return this.source.length == this.currentPosition;
 }
 
-private void checkNonExternalizedString() {
+protected void checkNonExternalizedString() {
        if (this.currentLine == null) 
                return;
        parseTags(this.currentLine);
@@ -925,6 +932,13 @@ public int getNextToken() throws InvalidInputException {
                        // ---------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 @@ public int getNextToken() throws InvalidInputException {
                                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 @@ public int getNextToken() throws InvalidInputException {
                                case '>' :
                                        {
                                                int test;
+                                               if (this.returnOnlyGreater) {
+                                                       return TokenNameGREATER;
+                                               }
                                                if ((test = getNextChar('=', '>')) == 0)
                                                        return TokenNameGREATER_EQUAL;
                                                if (test > 0) {
@@ -1367,7 +1412,9 @@ public int getNextToken() throws InvalidInputException {
                                                                if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
                                                                        checkNonExternalizedString();
                                                                        if (this.recordLineSeparator) {
-                                                                               if (!isUnicode) {
+                                                                               if (isUnicode) {
+                                                                                       pushUnicodeLineSeparator();
+                                                                               } else {
                                                                                        pushLineSeparator();
                                                                                }
                                                                        } else {
@@ -1397,7 +1444,9 @@ public int getNextToken() throws InvalidInputException {
                                                                        if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
                                                                                checkNonExternalizedString();
                                                                                if (this.recordLineSeparator) {
-                                                                                       if (!isUnicode) {
+                                                                                       if (isUnicode) {
+                                                                                               pushUnicodeLineSeparator();
+                                                                                       } else {
                                                                                                pushLineSeparator();
                                                                                        }
                                                                                } else {
@@ -1450,8 +1499,9 @@ public int getNextToken() throws InvalidInputException {
                                default :
                                        if (Character.isJavaIdentifierStart(this.currentCharacter))
                                                return scanIdentifierOrKeyword();
-                                       if (isDigit(this.currentCharacter))
+                                       if (isDigit(this.currentCharacter)) {
                                                return scanNumber(false);
+                                       }                                               
                                        return TokenNameERROR;
                        }
                }
@@ -1513,7 +1563,7 @@ public final void getNextUnicodeChar()
 public char[] getSource(){
        return this.source;
 }
-private boolean isDigit(char c) throws InvalidInputException {
+protected boolean isDigit(char c) throws InvalidInputException {
        if (Character.isDigit(c)) {
                switch(c) {
                        case '0' :
@@ -1528,7 +1578,7 @@ private boolean isDigit(char c) throws InvalidInputException {
                        case '9' :
                                return true;
                }
-               throw new InvalidInputException(Scanner.INVALID_INPUT);
+               throw new InvalidInputException(Scanner.INVALID_DIGIT);
        } else {
                return false;
        }
@@ -2164,7 +2214,7 @@ final char[] optimizedCurrentTokenSource6() {
        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();
@@ -2413,6 +2463,7 @@ public int scanIdentifierOrKeyword() {
        //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;
@@ -2459,7 +2510,7 @@ public int scanIdentifierOrKeyword() {
                                                && (data[++index] == 'e')
                                                && (data[++index] == 'r')
                                                && (data[++index] == 't')) {
-                                                       if (this.assertMode) {
+                                                       if (this.sourceLevel >= ClassFileConstants.JDK1_4) {
                                                                this.containsAssertKeyword = true;
                                                                return TokenNameassert;
                                                        } else {
@@ -2584,8 +2635,18 @@ public int scanIdentifierOrKeyword() {
                                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')
@@ -2985,25 +3046,114 @@ public int scanNumber(boolean dotPrefix) throws InvalidInputException {
        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
@@ -3161,6 +3311,21 @@ public final void setSource(char[] sourceString){
        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() {
@@ -3200,7 +3365,7 @@ public String toString() {
                + "<-- 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$
index c05ff33..45ea344 100644 (file)
@@ -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 @@ package org.eclipse.jdt.internal.compiler.parser;
  * 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 @@ package org.eclipse.jdt.internal.compiler.parser;
 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
index 58e0506..6c53f6a 100644 (file)
@@ -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 @@ import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 
 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 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
        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 class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
            }
        }
 
-       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 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
                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 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
                        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 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
                        }
                } 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 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
                }
 
                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 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
 
                        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 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
                                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 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
                                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]
index 4c53fa2..00b8d97 100644 (file)
@@ -158,7 +158,7 @@ public class RangeUtil {
                                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 {
index a35d6d8..8d6c3d9 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser1.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser1.rsc differ
index 57084e8..082965a 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser10.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser10.rsc differ
index 4ed7d3b..d1a5283 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser11.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser11.rsc differ
index a114c91..955f911 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser12.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser12.rsc differ
index 6b56156..9dc419e 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser13.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser13.rsc differ
index e701a9e..ecfa021 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser14.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser14.rsc differ
index 4497913..d7836e5 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser15.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser15.rsc differ
index 0046bb9..64e337c 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser16.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser16.rsc differ
index ca3af17..6f199d2 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser17.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser17.rsc differ
index 66f0156..cd31f71 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser18.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser18.rsc differ
index 0f1c471..3b7856e 100644 (file)
@@ -1 +1 @@
-\1d\1d\1d\1d\1d\1d\1dWW\1d\1d\1d\1d\17\17\17\1dEEE\1d;;X(((\175\1d\1d\1d\1d\1d\1d\1d\1d\1d\17\17E\1dV\17\17\175(((((S\1e\1d5F \17\17ZZ\ 3\ 3
\ No newline at end of file
+\1d\1d\1d\1d\1d\1d\1d\1d\1d\1d\1d\1d\1d\1d\1d\1d\1d\1d\1dff\1d\1d\1d\1d\e\e\1f\e\1d\1d\1d\1d\1f\1d\1f\1fFFF\1dBBh\1f\1f\1f\1f\e\1eAAA\1d\1d\1d\1d\1d\1e\1d\1d\1d\1d\1d\e\e!\1f\1d\1fF\1de\e\e\eA\1f\1f\1f\1fd\1d\1d\1eA\1dI\eB     \b\fJJ\1aB!\e\e\eBB\e\eB\ e\1e\a\1e\a\1egGGP!\1aH\ 3!!!\a!!\a,\a\ 3\ 3\ 3\ 3
\ No newline at end of file
index 3d7327b..3f73142 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser2.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser2.rsc differ
index 8dc5ace..c371c1c 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser20.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser20.rsc differ
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/parser21.rsc b/src/org/eclipse/jdt/internal/compiler/parser/parser21.rsc
new file mode 100644 (file)
index 0000000..3a223d8
Binary files /dev/null and b/src/org/eclipse/jdt/internal/compiler/parser/parser21.rsc differ
index 81f96e1..8f173bd 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser3.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser3.rsc differ
index 2842e17..6246280 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser4.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser4.rsc differ
index 26aa971..f45b140 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser5.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser5.rsc differ
index 69c1580..188784f 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser6.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser6.rsc differ
index a4e445a..77673a0 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser7.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser7.rsc differ
index 8ce79a7..fcb83ba 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser8.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser8.rsc differ
index 6f68468..f8ca6a7 100644 (file)
Binary files a/src/org/eclipse/jdt/internal/compiler/parser/parser9.rsc and b/src/org/eclipse/jdt/internal/compiler/parser/parser9.rsc differ
index ecc98bf..6ddd4ae 100644 (file)
@@ -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 @@ ClassBody=ClassBody
 ClassBodyDeclaration=ClassBodyDeclaration
 ClassBodyDeclarations=ClassBodyDeclarations
 ClassBodyDeclarationsopt=ClassBodyDeclarations
+ClassBodySimpleNameopt=ClassBody
 ClassBodyopt=ClassBody
 ClassDeclaration=ClassDeclaration
 ClassHeader=ClassHeader
@@ -37,24 +60,30 @@ ClassHeaderExtends=ClassHeaderExtends
 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 @@ DimsLoop=Dimensions
 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 @@ FormalParameter=FormalParameter
 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 @@ LabeledStatementNoShortIf=LabeledStatement
 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 @@ Modifier=Modifier
 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 @@ StatementExpression=Expression
 StatementExpressionList=StatementExpressionList
 StatementNoShortIf=Statement
 StatementWithoutTrailingSubstatement=Statement
+StaticImportOnDemandDeclaration=StaticImportOnDemandDeclaration
+StaticImportOnDemandDeclarationName=StaticImportOnDemandDeclarationName
 StaticInitializer=StaticInitializer
 StaticOnly=StaticOnly
 SwitchBlock=SwitchBlock
@@ -186,13 +266,29 @@ ThrowStatement=ThrowStatement
 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 @@ VariableInitializer=VariableInitializer
 VariableInitializers=VariableInitializers
 WhileStatement=WhileStatement
 WhileStatementNoShortIf=WhileStatement
+Wildcard1=Wildcard1
+Wildcard2=Wildcard2
+Wildcard3=Wildcard3
+Wildcard=Wildcard
+WildcardBounds1=WildcardBounds1
+WildcardBounds2=WildcardBounds2
+WildcardBounds3=WildcardBound3
+WildcardBounds=WildcardBounds
index d75e6ae..7ab9b07 100644 (file)
@@ -20,9 +20,9 @@ import org.eclipse.jdt.internal.compiler.CompilationResult;
  * 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);
 }
index 7feb32e..7d8a3c9 100644 (file)
@@ -20,8 +20,8 @@ import org.eclipse.jdt.internal.compiler.CompilationResult;
  * should only be thrown from within problem handlers.
  */
 public class AbortMethod extends AbortType {
-
-    private static final long serialVersionUID = -1480267398969840003L; // backward compatible 
+       
+       private static final long serialVersionUID = -1480267398969840003L; // backward compatible      
        
 public AbortMethod(CompilationResult compilationResult, IProblem problem) {
        super(compilationResult, problem);
index f357469..77e7a0f 100644 (file)
@@ -20,9 +20,9 @@ import org.eclipse.jdt.internal.compiler.CompilationResult;
  * 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);
 }
index ba31625..c12e008 100644 (file)
@@ -85,18 +85,18 @@ public void abstractMethodMustBeImplemented(SourceTypeBinding type, MethodBindin
                // 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 @@ public void alreadyDefinedLabel(char[] labelName, ASTNode location) {
                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 @@ public void argumentTypeCannotBeVoidArray(SourceTypeBinding type, AbstractMethod
                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,37 @@ public void attemptToReturnVoidValue(ReturnStatement returnStatement) {
                returnStatement.sourceStart,
                returnStatement.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 +381,23 @@ public void cannotDefineDimensionsAndInitializer(ArrayAllocationExpression expre
 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,6 +448,15 @@ public void cannotThrowType(SourceTypeBinding type, AbstractMethodDeclaration me
                exceptionType.sourceStart,
                exceptionType.sourceEnd);
 }
+public void cannotUseSuperInCodeSnippet(int start, int end) {
+       this.handle(
+               IProblem.CannotUseSuperInCodeSnippet,
+               NoArgument,
+               NoArgument,
+               Error | Abort,
+               start,
+               end);
+}
 public void cannotUseSuperInJavaLangObject(ASTNode reference) {
        this.handle(
                IProblem.ObjectHasNoSuperclass,
@@ -359,14 +465,14 @@ public void cannotUseSuperInJavaLangObject(ASTNode reference) {
                reference.sourceStart,
                reference.sourceEnd);
 }
-public void cannotUseSuperInCodeSnippet(int start, int end) {
+public void cannotUseQualifiedEnumConstantInCaseLabel(QualifiedNameReference reference) {
+       String[] arguments = new String[]{ String.valueOf(reference.fieldBinding().name) };
        this.handle(
-               IProblem.CannotUseSuperInCodeSnippet,
-               NoArgument,
-               NoArgument,
-               Error | Abort,
-               start,
-               end);
+                       IProblem.IllegalQualifiedEnumConstantLabel,
+                       arguments,
+                       arguments,
+                       reference.sourceStart,
+                       reference.sourceEnd);   
 }
 public void caseExpressionMustBeConstant(Expression expression) {
        this.handle(
@@ -376,15 +482,15 @@ public void caseExpressionMustBeConstant(Expression expression) {
                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 +572,8 @@ public int computeSeverity(int problemId){
 
                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 +634,48 @@ public int computeSeverity(int problemId){
                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.UnsafeTypeOperation);
+
+               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.InconsistentNullCheck);
+                       
                /*
                 * 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 +691,17 @@ public int computeSeverity(int problemId){
                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 +711,32 @@ public int computeSeverity(int problemId){
                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 +759,7 @@ public int computeSeverity(int problemId){
                        } else {
                                return ProblemSeverities.Ignore;
                        }
-
+                       
                // by default problems are errors.
                default:
                        return Error;
@@ -683,6 +836,15 @@ public void constantOutOfRange(Literal literal, TypeBinding literalType) {
                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 +857,28 @@ public void deprecatedMethod(MethodBinding method, ASTNode location) {
        if (method.isConstructor()) {
                this.handle(
                        IProblem.UsingDeprecatedConstructor,
-                       new String[] {new String(method.declaringClass.readableName()), parametersAsString(method)},
-                       new String[] {new String(method.declaringClass.shortReadableName()), parametersAsShortString(method)},
+                       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 +888,32 @@ public void deprecatedType(TypeBinding type, ASTNode location) {
                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 +938,7 @@ public void duplicateFieldInType(SourceTypeBinding type, FieldDeclaration fieldD
                fieldDecl.sourceStart,
                fieldDecl.sourceEnd);
 }
+
 public void duplicateImport(ImportReference importRef) {
        String[] arguments = new String[] {CharOperation.toString(importRef.tokens)};
        this.handle(
@@ -750,6 +948,22 @@ public void duplicateImport(ImportReference importRef) {
                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 +982,70 @@ public void duplicateInitializationOfFinalLocal(LocalVariableBinding local, ASTN
                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 +1112,14 @@ public void duplicateSuperinterface(SourceTypeBinding type, TypeDeclaration type
                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 +1139,26 @@ public void emptyControlFlowStatement(int sourceStart, int sourceEnd) {
                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 +1194,19 @@ public void errorThisSuperInStatic(ASTNode reference) {
                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;
-       }
-       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);
+public void cannotInvokeSuperConstructorInEnum(ExplicitConstructorCall constructorCall, MethodBinding enumConstructor) {
+       this.handle(
+               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 +1268,6 @@ public void fieldsOrThisBeforeConstructorInvocation(ThisReference reference) {
                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 +1286,24 @@ public void finalMethodCannotBeOverridden(MethodBinding currentMethod, MethodBin
                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,6 +1312,22 @@ public void forwardReference(Reference reference, int indexInQualification, Type
                reference.sourceStart,
                reference.sourceEnd);
 }
+public void forwardTypeVariableReference(ASTNode location, TypeVariableBinding type) {
+       this.handle(
+               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
 // as arguments
@@ -1065,47 +1348,47 @@ private void handle(
                        this.referenceContext == null ? null : this.referenceContext.compilationResult()); 
        this.referenceContext = null;
 }
-// use this private API when the compilation unit result can be found through the
-// reference context. Otherwise, use the other API taking a problem and a compilation result
-// as arguments
+// use this private API when the compilation unit result cannot be found through the
+// reference context. 
+
 private void handle(
        int problemId, 
        String[] problemArguments,
        String[] messageArguments,
-       int severity,
        int problemStartPosition, 
-       int problemEndPosition){
+       int problemEndPosition,
+       CompilationResult unitResult){
 
        this.handle(
                        problemId,
                        problemArguments,
                        messageArguments,
-                       severity,
                        problemStartPosition,
                        problemEndPosition,
                        this.referenceContext, 
-                       this.referenceContext == null ? null : this.referenceContext.compilationResult()); 
+                       unitResult); 
        this.referenceContext = null;
 }
-// use this private API when the compilation unit result cannot be found through the
-// reference context. 
-
+// 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,
-       CompilationResult unitResult){
+       int problemEndPosition){
 
        this.handle(
                        problemId,
                        problemArguments,
                        messageArguments,
+                       severity,
                        problemStartPosition,
                        problemEndPosition,
                        this.referenceContext, 
-                       unitResult); 
+                       this.referenceContext == null ? null : this.referenceContext.compilationResult()); 
        this.referenceContext = null;
 }
 public void hiddenCatchBlock(ReferenceBinding exceptionType, ASTNode location) {
@@ -1132,34 +1415,27 @@ public void hidingEnclosingType(TypeDeclaration typeDecl) {
 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 +1457,56 @@ public void illegalAbstractModifierCombinationForMethod(ReferenceBinding type, A
                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 +1536,42 @@ public void illegalModifierForClass(SourceTypeBinding type) {
                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 +1590,34 @@ public void illegalModifierForInterface(SourceTypeBinding type) {
                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 +1648,67 @@ public void illegalModifierForMemberInterface(SourceTypeBinding type) {
                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.IllegalModifierForMethod,
+               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,
+               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 +1740,30 @@ public void illegalStaticModifierForMemberType(SourceTypeBinding type) {
                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 +1809,31 @@ public void illegalVoidExpression(ASTNode location) {
                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;
+       }
+       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;
        }
-       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]);
+       invalidType(importRef, (TypeBinding)expectedImport);
 }
 public void incompatibleExceptionInThrowsClause(SourceTypeBinding type, MethodBinding currentMethod, MethodBinding inheritedMethod, ReferenceBinding exceptionType) {
        if (type == currentMethod.declaringClass) {
@@ -1472,13 +1923,46 @@ public void incompatibleReturnType(MethodBinding currentMethod, MethodBinding in
                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 +1975,8 @@ public void indirectAccessToStaticField(ASTNode location, FieldBinding field){
 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 +1988,26 @@ public void indirectAccessToStaticType(ASTNode location, ReferenceBinding type)
                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 +2094,23 @@ public void interfaceCannotHaveInitializers(SourceTypeBinding type, FieldDeclara
                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 +2128,18 @@ public void invalidConstructor(Statement statement, MethodBinding targetConstruc
                (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 +2158,10 @@ public void invalidConstructor(Statement statement, MethodBinding targetConstruc
                        } else {
                                id = IProblem.NotVisibleConstructor;
                        }
+                       ProblemMethodBinding problemConstructor = (ProblemMethodBinding) targetConstructor;
+                       if (problemConstructor.closestMatch != null) {
+                           shownConstructor = problemConstructor.closestMatch.original();
+                   }                                   
                        break;
                case Ambiguous :
                        if (insideDefaultConstructor){
@@ -1644,6 +2172,109 @@ public void invalidConstructor(Statement statement, MethodBinding targetConstruc
                                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 +2283,10 @@ public void invalidConstructor(Statement statement, MethodBinding targetConstruc
 
        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 +2326,17 @@ public void invalidEnclosingType(Expression expression, TypeBinding type, Refere
                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 +2506,56 @@ public void invalidField(QualifiedNameReference nameRef, FieldBinding field, int
                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 +2577,122 @@ public void invalidMethod(MessageSend messageSend, MethodBinding method) {
                                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 +2752,14 @@ public void invalidOperator(UnaryExpression expression, TypeBinding type) {
                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 +2768,6 @@ public void invalidParenthesizedExpression(ASTNode reference) {
                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 +2786,12 @@ public void invalidType(ASTNode location, TypeBinding type) {
                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 +2803,45 @@ public void invalidType(ASTNode location, TypeBinding type) {
                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 +2858,14 @@ public void invalidTypeToSynchronize(Expression expression, TypeBinding type) {
                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 +2874,70 @@ public void invalidUnaryExpression(Expression expression) {
                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 +2949,88 @@ public void isClassPathCorrect(char[][] wellKnownTypeName, CompilationUnitDeclar
                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 +3047,15 @@ public void javadocDeprecatedMethod(MethodBinding method, ASTNode location, int
                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 +3072,24 @@ public void javadocDeprecatedType(TypeBinding type, ASTNode location, int modifi
                        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 +3114,30 @@ public void javadocErrorNoMethodFor(MessageSend messageSend, TypeBinding recType
 }
 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 +3165,7 @@ public void javadocInvalidField(int sourceStart, int sourceEnd, Binding fieldBin
                        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 +3179,8 @@ public void javadocInvalidField(int sourceStart, int sourceEnd, Binding fieldBin
  *     - 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 +3200,13 @@ public void javadocInvalidMethod(MessageSend messageSend, MethodBinding method,
                        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 +3230,26 @@ public void javadocInvalidMethod(MessageSend messageSend, MethodBinding method,
                                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 javadocInvalidParamTypeParameter(int sourceStart, int sourceEnd) {
+       this.handle(IProblem.JavadocInvalidParamTagTypeParameter, NoArgument, NoArgument, sourceStart, sourceEnd);
 }
-public void javadocInvalidSeeReference(int sourceStart, int sourceEnd) {
-       this.handle(IProblem.JavadocInvalidSeeReference, 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 +3301,15 @@ public void javadocInvalidType(ASTNode location, TypeBinding type, int modifiers
                        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 +3320,41 @@ public void javadocMissing(int sourceStart, int sourceEnd, int modifiers){
                }
        }
 }
-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 javadocMissingParamName(int sourceStart, int sourceEnd, int modifiers){
+       if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers))
+               this.handle(IProblem.JavadocMissingParamName, NoArgument, NoArgument, sourceStart, sourceEnd);
 }
-public void javadocMissingParamTag(Argument param, int modifiers) {
-       boolean overriding = (modifiers & (CompilerModifiers.AccImplementing+CompilerModifiers.AccOverriding)) != 0;
+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 +3362,23 @@ public void javadocMissingThrowsTag(TypeReference typeRef, int modifiers){
                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 +3415,24 @@ private String javadocVisibilityArgument(int visibility, int modifiers) {
        }
        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 +3459,27 @@ public void localVariableHiding(LocalDeclaration local, Binding hiddenVariable,
                        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 +3504,24 @@ public void methodWithConstructorName(MethodDeclaration methodDecl) {
                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 +3538,24 @@ public void missingSemiColon(Expression expression){
                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 +3576,8 @@ public void mustSpecifyPackage(CompilationUnitDeclaration compUnitDecl) {
 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 +3594,11 @@ public void nativeMethodsCannotBeStrictfp(ReferenceBinding type, AbstractMethodD
 public void needImplementation() {
        this.abortDueToInternalError(Util.bind("abort.missingCode")); //$NON-NLS-1$
 }
-public void needToEmulateFieldReadAccess(FieldBinding field, ASTNode location) {
-       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) {
+public void needToEmulateFieldAccess(FieldBinding field, ASTNode location, boolean isReadAccess) {
        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 +3613,11 @@ public void needToEmulateMethodAccess(
                        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 +3627,12 @@ public void needToEmulateMethodAccess(
                        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 +3658,16 @@ public void noMoreAvailableSpaceForArgument(LocalVariableBinding local, ASTNode
                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 +3678,39 @@ public void noMoreAvailableSpaceForLocal(LocalVariableBinding local, ASTNode loc
                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,11 +3722,19 @@ public void nonStaticAccessToStaticField(ASTNode location, FieldBinding field) {
                location.sourceStart,
                fieldLocation(field, location));
 }
-public void noSuchEnclosingInstance(TypeBinding targetType, ASTNode location, boolean isConstructorCall) {
-
-       int id;
-
-       if (isConstructorCall) {
+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;
+
+       if (isConstructorCall) {
                //28 = No enclosing instance of type {0} is available due to some intermediate constructor invocation
                id = IProblem.EnclosingInstanceInConstructorCall;
        } else if ((location instanceof ExplicitConstructorCall)
@@ -2817,6 +3791,30 @@ public void notCompatibleTypesError(InstanceOfExpression expression, TypeBinding
                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 +3823,14 @@ public void objectCannotHaveSuperTypes(SourceTypeBinding type) {
                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 +3905,21 @@ public void packageIsNotExpectedPackage(CompilationUnitDeclaration compUnitDecl)
                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()));
-       }
-       return buffer.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()));
+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();
 }
+
 public void parseError(
        int startPosition, 
        int endPosition, 
@@ -2987,137 +3988,331 @@ public void parseError(
                startPosition,
                endPosition);
 }
-public void possibleAccidentalBooleanAssignment(Assignment assignment) {
-       String[] arguments = new String[] {};
-       this.handle(
-               IProblem.PossibleAccidentalBooleanAssignment,
-               arguments,
-               arguments,
-               assignment.sourceStart,
-               assignment.sourceEnd);
+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 publicClassMustMatchFileName(CompilationUnitDeclaration compUnitDecl, TypeDeclaration typeDecl) {
-       this.referenceContext = typeDecl; // report the problem against the type not the entire compilation unit
-       String[] arguments = new String[] {new String(compUnitDecl.getFileName()), new String(typeDecl.name)};
+public void parseErrorDeleteTokens(
+       int start,
+       int end){
        this.handle(
-               IProblem.PublicClassMustMatchFileName,
-               arguments,
-               arguments,
-               typeDecl.sourceStart,
-               typeDecl.sourceEnd,
-               compUnitDecl.compilationResult);
+               IProblem.ParsingErrorDeleteTokens,
+               NoArgument,
+               NoArgument,
+               start,
+               end);
 }
-public void recursiveConstructorInvocation(ExplicitConstructorCall constructorCall) {
-
-       this.handle(
-               IProblem.RecursiveConstructorInvocation,
-               new String[] {
-                       new String(constructorCall.binding.declaringClass.readableName()), 
-                       parametersAsString(constructorCall.binding)
-               },
-               new String[] {
-                       new String(constructorCall.binding.declaringClass.shortReadableName()), 
-                       parametersAsShortString(constructorCall.binding)
-               },
-               constructorCall.sourceStart,
-               constructorCall.sourceEnd);
+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 redefineArgument(Argument arg) {
-       String[] arguments = new String[] {new String(arg.name)};
+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.RedefinedArgument,
+               IProblem.ParsingErrorInsertToComplete,
                arguments,
                arguments,
-               arg.sourceStart,
-               arg.sourceEnd);
+               start,
+               end);
 }
-public void redefineLocal(LocalDeclaration localDecl) {
-       String[] arguments = new String[] {new String(localDecl.name)};
+public void parseErrorInsertToCompletePhrase(
+       int start,
+       int end,
+       String inserted){
+       String[] arguments = new String[] {inserted};
        this.handle(
-               IProblem.RedefinedLocal,
+               IProblem.ParsingErrorInsertToCompletePhrase,
                arguments,
                arguments,
-               localDecl.sourceStart,
-               localDecl.sourceEnd);
+               start,
+               end);
 }
-public void referenceMustBeArrayTypeAt(TypeBinding arrayType, ArrayReference arrayRef) {
+public void parseErrorInsertToCompleteScope(
+       int start,
+       int end,
+       String inserted){
+       String[] arguments = new String[] {inserted};
        this.handle(
-               IProblem.ArrayReferenceRequired,
-               new String[] {new String(arrayType.readableName())},
-               new String[] {new String(arrayType.shortReadableName())},
-               arrayRef.sourceStart,
-               arrayRef.sourceEnd);
+               IProblem.ParsingErrorInsertToCompleteScope,
+               arguments,
+               arguments,
+               start,
+               end);
 }
-public void returnTypeCannotBeVoidArray(SourceTypeBinding type, MethodDeclaration methodDecl) {
-       String[] arguments = new String[] {new String(methodDecl.selector)};
+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.ReturnTypeCannotBeVoidArray,
+               IProblem.ParsingErrorMergeTokens,
                arguments,
                arguments,
-               methodDecl.sourceStart,
-               methodDecl.sourceEnd);
+               start,
+               end);
 }
-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;
-       }
+public void parseErrorMisplacedConstruct(
+       int start,
+       int end){
        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);
+               IProblem.ParsingErrorMisplacedConstruct,
+               NoArgument,
+               NoArgument,
+               start,
+               end);
 }
-public void scannerError(Parser parser, String errorTokenName) {
-       Scanner scanner = parser.scanner;
-
-       int flag = IProblem.ParsingErrorNoSuggestion;
-       int startPos = scanner.startPosition;
-
-       //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))
+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) {
+       this.handle(
+               IProblem.PossibleAccidentalBooleanAssignment,
+               NoArgument,
+               NoArgument,
+               assignment.sourceStart,
+               assignment.sourceEnd);
+}
+public void publicClassMustMatchFileName(CompilationUnitDeclaration compUnitDecl, TypeDeclaration typeDecl) {
+       this.referenceContext = typeDecl; // report the problem against the type not the entire compilation unit
+       String[] arguments = new String[] {new String(compUnitDecl.getFileName()), new String(typeDecl.name)};
+       this.handle(
+               IProblem.PublicClassMustMatchFileName,
+               arguments,
+               arguments,
+               typeDecl.sourceStart,
+               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()), 
+                       typesAsString(constructorCall.binding.isVarargs(), constructorCall.binding.parameters, false)
+               },
+               new String[] {
+                       new String(constructorCall.binding.declaringClass.shortReadableName()), 
+                       typesAsString(constructorCall.binding.isVarargs(), constructorCall.binding.parameters, true)
+               },
+               constructorCall.sourceStart,
+               constructorCall.sourceEnd);
+}
+
+public void redefineArgument(Argument arg) {
+       String[] arguments = new String[] {new String(arg.name)};
+       this.handle(
+               IProblem.RedefinedArgument,
+               arguments,
+               arguments,
+               arg.sourceStart,
+               arg.sourceEnd);
+}
+public void redefineLocal(LocalDeclaration localDecl) {
+       String[] arguments = new String[] {new String(localDecl.name)};
+       this.handle(
+               IProblem.RedefinedLocal,
+               arguments,
+               arguments,
+               localDecl.sourceStart,
+               localDecl.sourceEnd);
+}
+public void referenceMustBeArrayTypeAt(TypeBinding arrayType, ArrayReference arrayRef) {
+       this.handle(
+               IProblem.ArrayReferenceRequired,
+               new String[] {new String(arrayType.readableName())},
+               new String[] {new String(arrayType.shortReadableName())},
+               arrayRef.sourceStart,
+               arrayRef.sourceEnd);
+}
+public void returnTypeCannotBeVoidArray(SourceTypeBinding type, MethodDeclaration methodDecl) {
+       String[] arguments = new String[] {new String(methodDecl.selector)};
+       this.handle(
+               IProblem.ReturnTypeCannotBeVoidArray,
+               arguments,
+               arguments,
+               methodDecl.sourceStart,
+               methodDecl.sourceEnd);
+}
+
+public void scannerError(Parser parser, String errorTokenName) {
+       Scanner scanner = parser.scanner;
+
+       int flag = IProblem.ParsingErrorNoSuggestion;
+       int startPos = scanner.startPosition;
+
+       //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;
@@ -3125,8 +4320,8 @@ public void scannerError(Parser parser, String errorTokenName) {
                flag = IProblem.UnterminatedComment;
        else if (errorTokenName.equals(Scanner.INVALID_CHAR_IN_STRING))
                flag = IProblem.UnterminatedString;
-       else if (errorTokenName.equals(Scanner.INVALID_INPUT))
-               flag = IProblem.InvalidInput;
+       else if (errorTokenName.equals(Scanner.INVALID_DIGIT))
+               flag = IProblem.InvalidDigit;
 
        String[] arguments = flag == IProblem.ParsingErrorNoSuggestion 
                        ? new String[] {errorTokenName}
@@ -3199,6 +4394,24 @@ public void staticInheritedMethodConflicts(SourceTypeBinding type, MethodBinding
                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,
@@ -3223,14 +4436,67 @@ public void superfluousSemicolon(int sourceStart, int sourceEnd) {
                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,
@@ -3292,37 +4558,53 @@ public void typeCollidesWithPackage(CompilationUnitDeclaration compUnitDecl, Typ
                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 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.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);
 }
-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;
+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.TypeMismatch,
-               new String[] {constantTypeName, expectedTypeName},
-               new String[] {constantTypeShortName, expectedTypeShortName},
-               expression.sourceStart,
-               expression.sourceEnd);
+               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)};
@@ -3333,12 +4615,21 @@ public void undefinedLabel(BranchStatement statement) {
                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);
 }
@@ -3426,6 +4717,22 @@ public void unnecessaryCastForArgument(CastExpression castExpression, TypeBindin
                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(
@@ -3448,22 +4755,6 @@ public void unqualifiedFieldAccess(NameReference reference, FieldBinding field)
                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,
@@ -3508,6 +4799,91 @@ public void unresolvableReference(NameReference nameRef, Binding binding) {
                nameRef.sourceStart,
                end);
 }
+public void unsafeCast(CastExpression castExpression) {
+       TypeBinding castedExpressionType = castExpression.expression.resolvedType;
+       this.handle(
+               IProblem.UnsafeGenericCast,
+               new String[]{ new String(castedExpressionType.readableName()), new String(castExpression.resolvedType.readableName())},
+               new String[]{ new String(castedExpressionType.shortReadableName()), new String(castExpression.resolvedType.shortReadableName())},
+               castExpression.sourceStart,
+               castExpression.sourceEnd);
+}
+public void 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)};
@@ -3524,12 +4900,12 @@ public void unusedDeclaredThrownException(ReferenceBinding exceptionType, Abstra
                        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,
@@ -3540,13 +4916,13 @@ public void unusedDeclaredThrownException(ReferenceBinding exceptionType, Abstra
                        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,
@@ -3583,11 +4959,11 @@ public void unusedPrivateConstructor(ConstructorDeclaration constructorDecl) {
                        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);
@@ -3650,14 +5026,14 @@ public void unusedPrivateMethod(AbstractMethodDeclaration methodDecl) {
        }
        // 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;
@@ -3667,12 +5043,12 @@ public void unusedPrivateMethod(AbstractMethodDeclaration methodDecl) {
                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);
@@ -3701,7 +5077,32 @@ public void useAssertAsAnIdentifier(int sourceStart, int sourceEnd) {
                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(
@@ -3731,348 +5132,71 @@ public void visibilityConflict(MethodBinding currentMethod, MethodBinding inheri
                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);
-}
-
-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;
-       }
-}
-
-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$
+               location.sourceEnd);    
+}
+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;
+               }
        }
-       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.
@@ -4092,5 +5216,4 @@ public void wrongSequenceOfExceptionTypesError(TryStatement statement, TypeBindi
                typeRef.sourceStart,
                typeRef.sourceEnd);
 }
-
 }
index a6533e5..acceeda 100644 (file)
@@ -17,9 +17,7 @@ package org.eclipse.jdt.internal.compiler.problem;
  *     (internal only)
  */
 public class ShouldNotImplement extends RuntimeException {
-    
-       private static final long serialVersionUID = 2669970476264283736L; // backward compatible
-
+       private static final long serialVersionUID = 2669970476264283736L; // backward compatible
        public ShouldNotImplement(String message) {
                super(message);
        }
index e45ae5d..f110447 100644 (file)
@@ -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
 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}
 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
 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}
 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
 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 ++/--
 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}
 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}
 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
+
+###[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
 
-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
 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
 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}
 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}) 
 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
 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
 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
 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 end space separator)
-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 raw type {0} is converted to {1}. 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} will not check conformance of type arguments at runtime
+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}
+
+### 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/src/org/eclipse/jdt/internal/compiler/util/FloatUtil.java b/src/org/eclipse/jdt/internal/compiler/util/FloatUtil.java
new file mode 100644 (file)
index 0000000..6f2c816
--- /dev/null
@@ -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/src/org/eclipse/jdt/internal/compiler/util/HashtableOfIntValues.java b/src/org/eclipse/jdt/internal/compiler/util/HashtableOfIntValues.java
deleted file mode 100644 (file)
index 7c42adb..0000000
+++ /dev/null
@@ -1,148 +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.util;
-
-import org.eclipse.jdt.core.compiler.CharOperation;
-
-/**
- * Hashtable of {char[] --> int}
- */
-public final class HashtableOfIntValues implements Cloneable {
-       
-       public static final int NO_VALUE = Integer.MIN_VALUE;
-       
-       // to avoid using Enumerations, walk the individual tables skipping nulls
-       public char[] keyTable[];
-       public int valueTable[];
-
-       public int elementSize; // number of elements in the table
-       int threshold;
-
-       public HashtableOfIntValues() {
-               this(13);
-       }
-
-       public HashtableOfIntValues(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 char[extraRoom][];
-               this.valueTable = new int[extraRoom];
-       }
-
-       public Object clone() throws CloneNotSupportedException {
-               HashtableOfIntValues result = (HashtableOfIntValues) super.clone();
-               result.elementSize = this.elementSize;
-               result.threshold = this.threshold;
-
-               int length = this.keyTable.length;
-               result.keyTable = new char[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(char[] key) {
-
-               int index = CharOperation.hashCode(key) % valueTable.length;
-               int keyLength = key.length;
-               char[] currentKey;
-               while ((currentKey = keyTable[index]) != null) {
-                       if (currentKey.length == keyLength && CharOperation.equals(currentKey, key))
-                               return true;
-                       index = (index + 1) % keyTable.length;
-               }
-               return false;
-       }
-
-       public int get(char[] key) {
-
-               int index = CharOperation.hashCode(key) % valueTable.length;
-               int keyLength = key.length;
-               char[] currentKey;
-               while ((currentKey = keyTable[index]) != null) {
-                       if (currentKey.length == keyLength && CharOperation.equals(currentKey, key))
-                               return valueTable[index];
-                       index = (index + 1) % keyTable.length;
-               }
-               return NO_VALUE;
-       }
-
-       public int put(char[] key, int value) {
-
-               int index = CharOperation.hashCode(key) % valueTable.length;
-               int keyLength = key.length;
-               char[] currentKey;
-               while ((currentKey = keyTable[index]) != null) {
-                       if (currentKey.length == keyLength && CharOperation.equals(currentKey, key))
-                               return valueTable[index] = value;
-                       index = (index + 1) % keyTable.length;
-               }
-               keyTable[index] = key;
-               valueTable[index] = value;
-
-               // assumes the threshold is never equal to the size of the table
-               if (++elementSize > threshold)
-                       rehash();
-               return value;
-       }
-
-       public int removeKey(char[] key) {
-
-               int index = CharOperation.hashCode(key) % valueTable.length;
-               int keyLength = key.length;
-               char[] currentKey;
-               while ((currentKey = keyTable[index]) != null) {
-                       if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) {
-                               int value = valueTable[index];
-                               elementSize--;
-                               keyTable[index] = null;
-                               valueTable[index] = NO_VALUE;
-                               rehash();
-                               return value;
-                       }
-                       index = (index + 1) % keyTable.length;
-               }
-               return NO_VALUE;
-       }
-
-       private void rehash() {
-
-               HashtableOfIntValues newHashtable = new HashtableOfIntValues(elementSize * 2);          // double the number of expected elements
-               char[] currentKey;
-               for (int i = keyTable.length; --i >= 0;)
-                       if ((currentKey = keyTable[i]) != null)
-                               newHashtable.put(currentKey, 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$
-               char[] key;
-               for (int i = 0, length = valueTable.length; i < length; i++)
-                       if ((key = keyTable[i]) != null)
-                               s += new String(key) + " -> " + valueTable[i] + "\n";   //$NON-NLS-2$ //$NON-NLS-1$
-               return s;
-       }
-}
diff --git a/src/org/eclipse/jdt/internal/compiler/util/HashtableOfLong.java b/src/org/eclipse/jdt/internal/compiler/util/HashtableOfLong.java
deleted file mode 100644 (file)
index 7437a6d..0000000
+++ /dev/null
@@ -1,92 +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.util;
- /**
-  *    Hashtable for non-zero long keys.
-  */
-  
-public final class HashtableOfLong {
-       // to avoid using Enumerations, walk the individual tables skipping nulls
-       public long[] keyTable;
-       public Object[] valueTable;
-
-       public int elementSize; // number of elements in the table
-       int threshold;
-public HashtableOfLong() {
-       this(13);
-}
-public HashtableOfLong(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 long[extraRoom];
-       this.valueTable = new Object[extraRoom];
-}
-public boolean containsKey(long key) {
-       int index = ((int)(key >>> 32)) % valueTable.length;
-       long currentKey;
-       while ((currentKey = keyTable[index]) != 0) {
-               if (currentKey == key)
-                       return true;
-               index = (index + 1) % keyTable.length;
-       }
-       return false;
-}
-public Object get(long key) {
-       int index = ((int)(key >>> 32)) % valueTable.length;
-       long currentKey;
-       while ((currentKey = keyTable[index]) != 0) {
-               if (currentKey == key)  return valueTable[index];
-               index = (index + 1) % keyTable.length;
-       }
-       return null;
-}
-public Object put(long key, Object value) {
-       int index = ((int)(key >>> 32)) % valueTable.length;
-       long currentKey;
-       while ((currentKey = keyTable[index]) != 0) {
-               if (currentKey == key)  return valueTable[index] = value;
-               index = (index + 1) % keyTable.length;
-       }
-       keyTable[index] = key;
-       valueTable[index] = value;
-
-       // assumes the threshold is never equal to the size of the table
-       if (++elementSize > threshold)
-               rehash();
-       return value;
-}
-private void rehash() {
-       HashtableOfLong newHashtable = new HashtableOfLong(elementSize * 2); // double the number of expected elements
-       long currentKey;
-       for (int i = keyTable.length; --i >= 0;)
-               if ((currentKey = keyTable[i]) != 0)
-                       newHashtable.put(currentKey, 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 object;
-       for (int i = 0, length = valueTable.length; i < length; i++)
-               if ((object = valueTable[i]) != null)
-                       s += keyTable[i] + " -> " + object.toString() + "\n"; //$NON-NLS-2$ //$NON-NLS-1$
-       return s;
-}
-}
diff --git a/src/org/eclipse/jdt/internal/compiler/util/SimpleLookupTable.java b/src/org/eclipse/jdt/internal/compiler/util/SimpleLookupTable.java
new file mode 100644 (file)
index 0000000..978c301
--- /dev/null
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * A simple lookup table is a non-synchronized Hashtable, whose keys
+ * and values are Objects. It also uses linear probing to resolve collisions
+ * rather than a linked list of hash table entries.
+ */
+public final class SimpleLookupTable 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
+public int threshold;
+
+public SimpleLookupTable() {
+       this(13);
+}
+
+public SimpleLookupTable(int size) {
+       this.elementSize = 0;
+       this.threshold = size; // size represents the expected number of elements
+       int extraRoom = (int) (size * 1.5f);
+       if (this.threshold == extraRoom)
+               extraRoom++;
+       this.keyTable = new Object[extraRoom];
+       this.valueTable = new Object[extraRoom];
+}
+
+public Object clone() throws CloneNotSupportedException {
+       SimpleLookupTable result = (SimpleLookupTable) 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 length = keyTable.length;
+       int index = (key.hashCode() & 0x7FFFFFFF) % length;
+       Object currentKey;
+       while ((currentKey = keyTable[index]) != null) {
+               if (currentKey.equals(key)) return true;
+               if (++index == length) index = 0;
+       }
+       return false;
+}
+
+public Object get(Object key) {
+       int length = keyTable.length;
+       int index = (key.hashCode() & 0x7FFFFFFF) % length;
+       Object currentKey;
+       while ((currentKey = keyTable[index]) != null) {
+               if (currentKey.equals(key)) return valueTable[index];
+               if (++index == length) index = 0;
+       }
+       return null;
+}
+
+public Object keyForValue(Object valueToMatch) {
+       if (valueToMatch != null)
+               for (int i = 0, l = valueTable.length; i < l; i++)
+                       if (valueToMatch.equals(valueTable[i]))
+                               return keyTable[i];
+       return null;
+}
+
+public Object put(Object key, Object value) {
+       int length = keyTable.length;
+       int index = (key.hashCode() & 0x7FFFFFFF) % length;
+       Object currentKey;
+       while ((currentKey = keyTable[index]) != null) {
+               if (currentKey.equals(key)) return valueTable[index] = value;
+               if (++index == length) index = 0;
+       }
+       keyTable[index] = key;
+       valueTable[index] = value;
+
+       // assumes the threshold is never equal to the size of the table
+       if (++elementSize > threshold) rehash();
+       return value;
+}
+
+public Object removeKey(Object key) {
+       int length = keyTable.length;
+       int index = (key.hashCode() & 0x7FFFFFFF) % length;
+       Object currentKey;
+       while ((currentKey = keyTable[index]) != null) {
+               if (currentKey.equals(key)) {
+                       elementSize--;
+                       Object oldValue = valueTable[index];
+                       keyTable[index] = null;
+                       valueTable[index] = null;
+                       if (keyTable[index + 1 == length ? 0 : index + 1] != null)
+                               rehash(); // only needed if a possible collision existed
+                       return oldValue;
+               }
+               if (++index == length) index = 0;
+       }
+       return null;
+}
+
+public void removeValue(Object valueToRemove) {
+       boolean rehash = false;
+       for (int i = 0, l = valueTable.length; i < l; i++) {
+               Object value = valueTable[i];
+               if (value != null && value.equals(valueToRemove)) {
+                       elementSize--;
+                       keyTable[i] = null;
+                       valueTable[i] = null;
+                       if (!rehash && keyTable[i + 1 == l ? 0 : i + 1] != null)
+                               rehash = true; // only needed if a possible collision existed
+               }
+       }
+       if (rehash) rehash();
+}
+
+private void rehash() {
+       SimpleLookupTable newLookupTable = new SimpleLookupTable(elementSize * 2); // double the number of expected elements
+       Object currentKey;
+       for (int i = keyTable.length; --i >= 0;)
+               if ((currentKey = keyTable[i]) != null)
+                       newLookupTable.put(currentKey, valueTable[i]);
+
+       this.keyTable = newLookupTable.keyTable;
+       this.valueTable = newLookupTable.valueTable;
+       this.elementSize = newLookupTable.elementSize;
+       this.threshold = newLookupTable.threshold;
+}
+
+public String toString() {
+       String s = ""; //$NON-NLS-1$
+       Object object;
+       for (int i = 0, l = valueTable.length; i < l; i++)
+               if ((object = valueTable[i]) != null)
+                       s += keyTable[i].toString() + " -> " + object.toString() + "\n";        //$NON-NLS-2$ //$NON-NLS-1$
+       return s;
+}
+}
index 94b7567..ef2e5bd 100644 (file)
@@ -29,40 +29,47 @@ public class Util implements SuffixConstants {
        public interface Displayable {
                String displayString(Object o);
        }
-
-       public static String LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$
-       public static char[] LINE_SEPARATOR_CHARS = LINE_SEPARATOR.toCharArray();
-       
-       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 
+        */
+       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 strings.
+        * substitution locations with the given string.
         */
-       public static String bind(String id, String binding1, String binding2) {
-               return bind(id, new String[] { binding1, binding2 });
+       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 string.
+        * substitution locations with the given strings.
         */
-       public static String bind(String id, String binding) {
-               return bind(id, new String[] { binding });
+       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 @@ public class Util implements SuffixConstants {
                        // 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 @@ public class Util implements SuffixConstants {
                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 @@ public class Util implements SuffixConstants {
                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 {
@@ -424,6 +422,21 @@ public class Util implements SuffixConstants {
         * 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 @@ public class Util implements SuffixConstants {
                }
                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 @@ public class Util implements SuffixConstants {
                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;
+       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;
+               }
+       }
 
-               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;
+       /**
+        * 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;
                }
-               return true;            
        }
        /**
         * Converts an array of Objects into String.
@@ -507,17 +572,4 @@ public class Util implements SuffixConstants {
                }
                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;
-               }
-       }
 }
index 8a1f05c..7a53316 100644 (file)
@@ -54,10 +54,6 @@ parser.endOfConstructor = end of constructor
 parser.endOfMethod = end of method
 parser.endOfInitializer = end of initializer
 
-### binding
-binding.subclass = anonymous subclass of {0}
-binding.implementation = anonymous implementation of {0}
-
 ### ast
 ast.missingCode = Missing code gen implementation
 
@@ -66,4 +62,5 @@ constant.cannotCastedInto =  {0} constant cannot be casted into {1}
 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
index 382cf74..7c771a6 100644 (file)
@@ -385,171 +385,11 @@ public class Compiler {
         }
     }
 
-    // ClassLoader Wrappers ///////////////////////////////////////////////////
-
-    final static class LoadedNestedType implements IBinaryNestedType {
-        private Class c;
-        LoadedNestedType(Class c) { this.c = c; }
-        public char[] getName() { return name(c); }
-        public char[] getEnclosingTypeName() { return name(c.getDeclaringClass()); }
-        public int getModifiers() { return c.getModifiers(); }
-    }
-
-    final static class LoadedField implements IBinaryField {
-        private Field f;
-        private Constant c;
-
-        LoadedField(Field f) {
-            this.f = f;
-            int m = f.getModifiers();
-
-            c = Constant.NotAConstant;
-            if (Modifier.isFinal(m) && Modifier.isStatic(m)) {
-                try {
-                    Class type = f.getType();
-                    if (type == Boolean.TYPE) {
-                        c = new BooleanConstant(f.getBoolean(null));
-                    } else if (type == Byte.TYPE) {
-                        c = new ByteConstant(f.getByte(null));
-                    } else if (type == Character.TYPE) {
-                        c = new CharConstant(f.getChar(null));
-                    } else if (type == Double.TYPE) {
-                        c = new DoubleConstant(f.getDouble(null));
-                    } else if (type == Float.TYPE) {
-                        c = new FloatConstant(f.getFloat(null));
-                    } else if (type == Integer.TYPE) {
-                        c = new IntConstant(f.getInt(null));
-                    } else if (type == Long.TYPE) {
-                        c = new LongConstant(f.getLong(null));
-                    } else if (type == Short.TYPE) {
-                        c = new ShortConstant(f.getShort(null));
-                    } else if (type == String.class) {
-                        c = new StringConstant((String)f.get(null));
-                    }
-                } catch (IllegalAccessException e) {}
-            }
-        }
-        public Constant getConstant() { return c; }
-        public char[] getTypeName() { return typeName(f.getType()); }
-        public char[] getName() { return f.getName().toCharArray(); }
-        public int getModifiers() { return f.getModifiers(); }
-    }
-
-    final static class LoadedConstructor implements IBinaryMethod {
-        private Constructor c;
-        private char[][] ex;
-        private char[] desc;
-
-        LoadedConstructor(Constructor c) {
-            this.c = c;
-
-            Class[] exs = c.getExceptionTypes();
-            ex = new char[exs.length][];
-            for (int i=0; i < ex.length; i++) ex[i] = name(exs[i]);
-
-            desc = descriptor(c.getParameterTypes(), null);
-        }
-        public int getModifiers() { return c.getModifiers(); }
-        public char[] getSelector() { return c.getName().toCharArray(); }
-        public boolean isConstructor() { return true; }
-        public boolean isClinit() { return false; }
-        public char[][] getArgumentNames() { return null; }
-        public char[][] getExceptionTypeNames() { return ex; }
-        public char[] getMethodDescriptor() { return desc; }
-    }
-
-    final static class LoadedMethod implements IBinaryMethod {
-        private Method m;
-        private char[][] ex;
-        private char[] desc;
-
-        LoadedMethod(Method m) {
-            this.m = m;
-
-            Class[] exs = m.getExceptionTypes();
-            ex = new char[exs.length][];
-            for (int i=0; i < ex.length; i++) ex[i] = name(exs[i]);
-
-            desc = descriptor(m.getParameterTypes(), m.getReturnType());
-        }
-        public int getModifiers() { return m.getModifiers(); }
-        public char[] getSelector() { return m.getName().toCharArray(); }
-        public boolean isConstructor() { return false; }
-        public boolean isClinit() { return false; }
-        public char[][] getArgumentNames() { return null; } // FEATURE: does this do anything cool?
-        public char[][] getExceptionTypeNames() { return ex; }
-        public char[] getMethodDescriptor() { return desc; }
-    }
-
-    final static class LoadedClass implements IBinaryType {
-        private Class c;
-        private IBinaryField[] f;
-        private char[][] inf;
-        private IBinaryNestedType[] nested;
-        private IBinaryMethod[] meth = null;
-
-        LoadedClass(Class c) {
-            this.c = c;
-
-            Field[] fields = c.getDeclaredFields();
-            List flist = new ArrayList(fields.length);
-            for (int i=0; i < fields.length; i++)
-                if (!Modifier.isPrivate(fields[i].getModifiers()))
-                    flist.add(new LoadedField(fields[i]));
-            f = new IBinaryField[flist.size()];
-            flist.toArray(f);
-
-            Class[] interfaces = c.getInterfaces();
-            inf = new char[interfaces.length][];
-            for (int i=0; i < inf.length; i++) inf[i] = name(interfaces[i]);
-
-            Class[] classes = c.getClasses();
-            nested = new IBinaryNestedType[classes.length];
-            for (int i=0; i < nested.length; i++)
-                nested[i] = new LoadedNestedType(classes[i]);
-
-            Constructor[] constructors = c.getDeclaredConstructors();
-            Method[] methods = c.getDeclaredMethods();
-            if (methods.length + constructors.length > 0) {
-                List m = new ArrayList(methods.length + constructors.length);
-                for (int j=0; j < methods.length; j++)
-                    if (!Modifier.isPrivate(methods[j].getModifiers()))
-                        m.add(new LoadedMethod(methods[j]));
-                for (int j=0; j < constructors.length; j++)
-                    if (!Modifier.isPrivate(constructors[j].getModifiers()))
-                        m.add(new LoadedConstructor(constructors[j]));
-                meth = new IBinaryMethod[m.size()]; m.toArray(meth);
-            }
-        }
-
-        public char[] getName() { return name(c); }
-        public char[] getEnclosingTypeName() { return name(c.getDeclaringClass()); }
-        public char[] getSuperclassName() { return name(c.getSuperclass()); }
-        public IBinaryField[] getFields() { return f; }
-        public char[][] getInterfaceNames() { return inf; }
-        public IBinaryNestedType[] getMemberTypes() { return nested; }
-        public IBinaryMethod[] getMethods() { return meth; }
-        public int getModifiers() { return c.getModifiers(); }
-
-        public boolean isBinaryType() { return true; }
-        public boolean isClass() { return true; }
-        public boolean isInterface() { return c.isInterface(); }
-        public boolean isAnonymous() { return false; }
-        public boolean isLocal() { return false; } // FIXME
-        public boolean isMember() { return false; } // FIXME
-        public char[] sourceFileName() { return null; }
-        public char[] getFileName() { return null; }
-
-        public boolean equals(Object o) {
-            return o == this || super.equals(o) ||
-                   (o != null && o instanceof LoadedClass &&
-                    c.equals(((LoadedClass)o).c));
-        }
-    }
-
-
     // Compiler Parameters ////////////////////////////////////////////////////
 
+    // FEATURE: may be able to use this to block access to APIs generated for stack objects
+    final AccessRestriction access = new AccessRestriction(null, null, null, null);
+
     /** Used by compiler to resolve classes. */
     final INameEnvironment env = new INameEnvironment() {
         public NameEnvironmentAnswer findType(char[][] c) { return findType(name(c), pack(c)); }
@@ -557,12 +397,23 @@ public class Compiler {
             if (veryverbose) System.out.print("findType: "+ str(p, '.') + "."+new String(n));
 
             try {
-                Class c = Class.forName(str(p, '.') + '.' + new String(n));
+                String classname = new String(n);
+                Class c = Class.forName(str(p, '.') + '.' + classname);
                 if (veryverbose) System.out.println("  found in classloader: "+ c);
                 IBinaryType b = (IBinaryType)loaded.get(c);
-                if (b == null) loaded.put(c, b = new LoadedClass(c));
-                return new NameEnvironmentAnswer(b);
-            } catch (ClassNotFoundException e) {}
+                if (b == null) loaded.put(c, b = new ClassFileReader(
+                    read(c.getResourceAsStream(classname)),
+                    (str(p, '/') + '/' + classname).toCharArray()));
+                return new NameEnvironmentAnswer(b, access);
+            } catch (ClassNotFoundException e) {
+            } catch (ClassFormatException e) {
+                e.printStackTrace();
+                throw new Error("ClassFormatException reading system class: " +
+                    str(p, '.')+new String(n));
+            } catch (IOException e) {
+                e.printStackTrace();
+                throw new Error("IOException reading system class: "+str(p, '.')+new String(n));
+            }
 
             // cut out searches for java.* packages in sources list
             if (p.length > 0 && eq(p[0], "java".toCharArray())) {
@@ -576,16 +427,16 @@ public class Compiler {
                     if (eq(n, s.n) && eq(p, s.p)) {
                         if (s.reader != null) {
                             if (veryverbose) System.out.println("  found reader");
-                            return new NameEnvironmentAnswer(s.reader);
+                            return new NameEnvironmentAnswer(s.reader, access);
                         }
                         if (s.compiled != null) {
                             if (veryverbose) System.out.println("  found compiled, new reader");
                             s.reader = new ClassFileReader(s.compiled,
-                                s.orig.getName().toCharArray(), true);
-                            return new NameEnvironmentAnswer(s.reader);
+                                s.orig.getName().toCharArray());
+                            return new NameEnvironmentAnswer(s.reader, access);
                         }
                         if (veryverbose) System.out.println("  found unit");
-                        return new NameEnvironmentAnswer(sources[i].unit);
+                        return new NameEnvironmentAnswer(sources[i].unit, access);
                     }
                 }
             } catch (ClassFormatException e) {
@@ -703,7 +554,7 @@ public class Compiler {
 
     /** Convert source file path into class name block.
      *  eg. in:  java/lang/String.java -> { {java} {lang} {String} } */
-    private char[][] classname(String name) {
+    private static char[][] classname(String name) {
         String delim = name.indexOf('/') == -1 ? "." : "/";
         name = name.trim();
         if (name.endsWith(".java")) name = name.substring(0, name.length() - 5);
@@ -801,4 +652,23 @@ public class Compiler {
         return sb.toString().toCharArray();
     }
 
+    private static byte[] read(InputStream in) throws IOException {
+        byte[] bytes = new byte[16];
+        int off = 0, ret;
+        while ((ret = in.read(bytes, off, bytes.length - off)) != -1) {
+            off += ret;
+            if (off == bytes.length) {
+                byte[] nb = new byte[bytes.length * 2];
+                System.arraycopy(bytes, 0, nb, 0, bytes.length);
+                bytes = nb;
+            }
+        }
+        if (off != bytes.length) {
+            byte[] nb = new byte[off];
+            System.arraycopy(bytes, 0, nb, 0, off);
+            bytes = nb;
+        }
+        return bytes;
+    }
+
 }